CodeForces 149D Coloring Brackets

区间DP。dp[i][j][h][k]表示[i,j]这段区间染色,左端点为颜色h,右端点为颜色k的方案数。

递推式很容易写出来。注意中间过程爆int。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int MOD = 1e9 + 7;
const int maxn = 1000;
char s[maxn];
long long dp[maxn][maxn][3][3];
int len;
int link[maxn];
int Stack[maxn], top;

void init()
{
    len = strlen(s);
    for (int i = len - 1; i >= 0; i--) s[i + 1] = s[i];
    memset(dp, 0, sizeof dp);
}

void work()
{
    for (int i = 1; i <= len; i++)
    {
        if (i % 2 != 0) continue;
        for (int j = 1; j <= len; j++)
        {
            int st = j, en = st + i - 1;
            if (en > len) break;
            if (i == 2)
            {
                if (s[st] == '('&&s[en] == ')')
                {
                    dp[st][en][1][0] = dp[st][en][2][0] = 1;
                    dp[st][en][0][1] = dp[st][en][0][2] = 1;
                }
                continue;
            }

            if (link[st]==en)
            {
                for (int k = 0; k<3; k++)
                    for (int h = 0; h<3; h++)
                        if (k != 1) dp[st][en][1][0] = (dp[st][en][1][0] + dp[st + 1][en - 1][k][h]) % MOD;

                for (int k = 0; k<3; k++)
                    for (int h = 0; h<3; h++)
                        if (k != 2) dp[st][en][2][0] = (dp[st][en][2][0] + dp[st + 1][en - 1][k][h]) % MOD;

                for (int k = 0; k<3; k++)
                    for (int h = 0; h<3; h++)
                        if (h != 1) dp[st][en][0][1] = (dp[st][en][0][1] + dp[st + 1][en - 1][k][h]) % MOD;

                for (int k = 0; k<3; k++)
                    for (int h = 0; h<3; h++)
                        if (h != 2) dp[st][en][0][2] = (dp[st][en][0][2] + dp[st + 1][en - 1][k][h]) % MOD;
                continue;
            }

            int p = link[st];
            for (int k = 0; k<3; k++)
                for (int h = 0; h<3; h++)
                    for (int kk = 0; kk<3; kk++)
                        for (int hh = 0; hh<3; hh++)
                            if (!((kk == 1 && hh == 1) || (kk == 2 && hh == 2)))
                                dp[st][en][k][h] = (
                                dp[st][en][k][h] +
                                (dp[st][p][k][kk] * dp[p + 1][en][hh][h]) % MOD
                                ) % MOD;
        }
    }
    long long ans = 0;
    for (int k = 0; k<3; k++)
        for (int h = 0; h<3; h++)
            ans = (ans + dp[1][len][k][h]) % MOD;
    printf("%lld
", ans);
}

void f()
{
    memset(link, -1, sizeof link);
    top = -1;
    for (int i = 1; i <= len; i++)
    {
        if (top == -1) Stack[++top] = i;
        else
        {
            if (s[i] == ')') { link[Stack[top]] = i; top--; }
            else Stack[++top] = i;
        }
    }
}

int main()
{
    while (~scanf("%s", s))
    {
        init();
        f();
        work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5225376.html