题解CF149D Coloring Brackets

CF149D Coloring Brackets
一道很有意思的区间DP
我们用0表示不染色,1表示红色,2表示蓝色
定义状态\(f_{i,j,k,u}\)表示将合法序列[i,j]染色且\(i染为k,j染为u\)的方案数
那么序列就可以分为三种情况
1°:()
\(f_{i,j,0,1}=f_{i,f,1,0}=f_{i,j,0,2}=f_{i,j,2,0}\)
2°:((...))
\(f_{i,j,0,k}=\sum\limits_{u=0}^{u \le 2} \sum\limits_{v=0}^{v \le 2,v \ne k}f_{i+1,j-1,u,v}\)
\(f_{i,j,k,0}=\sum\limits_{u=0}^{u \le 2,u \ne k} \sum\limits_{v=0}^{v \le 2}f_{i+1,j-1,u,v}\)
3°:(...)(...)
\(l,rr,ll,r\)分别表示上面括号的位置
\(f_{l,r,u,v}=\sum\limits_{a=0}^{a \le 2} \sum\limits_{b=0}^{b \le 2} \sum\limits_{c=0}^{c \le 2} \sum\limits_{d=0}^{d \le 2}f_{l,rr,a,b}*f_{ll,r,c,d}\)并且需要满足端点颜色不同
那么只需要递归转移状态即可
代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MOD = 1000000007;

char str[705];
int stk[705], top, poi[705], col[705];
long long f[705][705][3][3];

void dfs(int l, int r)
{
    if (l + 1 == r)
        f[l][r][1][0] = f[l][r][2][0] = f[l][r][0][2] = f[l][r][0][1] = 1;
    else if (poi[l] == r)
    {
        dfs(l + 1, r - 1);
        for (int i = 0; i <= 2; i++)
            for (int j = 0; j <= 2; j++)
            {
                if (j != 2)
                    f[l][r][0][2] = (f[l + 1][r - 1][i][j] + f[l][r][0][2]) % MOD;
                if (j != 1)
                    f[l][r][0][1] = (f[l + 1][r - 1][i][j] + f[l][r][0][1]) % MOD;
                if (i != 2)
                    f[l][r][2][0] = (f[l + 1][r - 1][i][j] + f[l][r][2][0]) % MOD;
                if (i != 1)
                    f[l][r][1][0] = (f[l + 1][r - 1][i][j] + f[l][r][1][0]) % MOD;
            }
    }
    else 
    {
        dfs(l, poi[l]), dfs(poi[l] + 1, r);
        for (int i = 0; i <= 2; i++)
        {
            for (int j = 0; j <= 2; j++)
            {
                if (j > 0 && j == i)
                    continue;
                for (int k = 0; k <= 2; k++)
                    for (int u = 0; u <= 2;u++)
                        f[l][r][k][u] = (f[l][r][k][u] + f[l][poi[l]][k][i] * f[poi[l] + 1][r][j][u]) % MOD;
            }
        }
    }
}

int main()
{
    scanf("%s", str + 1);
    int len;
    for (int i = 1; str[i]; i++)
    {
        if (str[i] == '(')
            stk[++top] = i;
        else if(str[i] == ')')
            poi[stk[top--]] = i;
        len = i;
    }
    dfs(1, len);
    long long ans = 0;
    for (int i = 0; i <= 2; i++)
    {
        for (int j = 0; j <= 2; j++)
            ans = (ans + f[1][len][i][j]) % MOD;
    }
    printf("%lld", ans);
    return 0;
}
posted @ 2021-02-04 11:07  DSHUAIB  阅读(60)  评论(0编辑  收藏  举报