!-- Loading 底层遮罩 -->

CF149D Coloring Brackets

感谢所有AC

传送门

思路

    在只定义两个状态而无法转移后,选择增加两个状态。定义 $f(i,j,u,v)$ 为序列区间 $i$ 到 $j$ 且 $i$ 染成 $u$ 色,$j$ 染成 $v$ 色的方案数。

    在转移时需要进行一下分类。

    第一类是(),第二类是(……),第三类是(……)……(……)。

    第一类可以直接给符合条件的赋值为 1 。第二类则可以从内部即 $f(i+1,j-1,u,v)$ 转移而来。第三类可以从 $f(i,match,u,v)$ 和$f(match+1,j,u,v)$ 转移而来,需要注意每一类情况转移时的计算方式(第二类计数为累加,第三类计数为相乘)。对于第一类情况 )( 也同样赋值为 1 ,因为题目所给的序列是合法的,那么这类情况也必然是合法的。

    而改题用循环求解稍微复杂,因为在求解时会受序列的合法性的影响,不如记忆化搜索来得直观和简单。

代码

#include<iostream>
#include<cstring>
#include<stack>
#define maxn 1000
using namespace std;
char kh[maxn];
stack<int> s;
const int mod = 1e9 + 7;
int match[maxn];
long long dp[maxn][maxn][3][3];
void dfs(int l, int r)
{
    if (l + 1 == r)
        dp[l][r][0][2] = dp[l][r][0][1] = dp[l][r][1][0] = dp[l][r][2][0] = 1;
    else if (r == match[l])
    {
        dfs(l + 1, r - 1);
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
            {
                if (j != 1)
                {
                    dp[l][r][0][1] += dp[l + 1][r - 1][i][j];
                    dp[l][r][0][1] %= mod;
                }
                if (j != 2)
                {
                    dp[l][r][0][2] += dp[l + 1][r - 1][i][j];
                    dp[l][r][0][2] %= mod;
                }
                if (i != 1)
                {
                    dp[l][r][1][0] += dp[l + 1][r - 1][i][j];
                    dp[l][r][1][0] %= mod;
                }
                if (i != 2)
                {
                    dp[l][r][2][0] += dp[l + 1][r - 1][i][j];
                    dp[l][r][2][0] %= mod;
                }
            }
    }
    else
    {
        dfs(l, match[l]), dfs(match[l] + 1, r);
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                for (int x = 0; x < 3; x++)
                    for (int y = 0; y < 3; y++)
                        if (x == y && x && y)
                            continue;
                        else
                        {
                            dp[l][r][i][j] += (dp[l][match[l]][i][x] * dp[match[l] + 1][r][y][j]) % mod;
                            dp[l][r][i][j] %= mod;
                        }
    }
}
int main(void)   
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> kh + 1;
    int len = strlen(kh + 1);
    for (int i = 1; i <= len; i++)
    {
        if (kh[i] == '(')
            s.push(i);
        else
        {
            match[s.top()] = i;
            match[i] = s.top();
            s.pop();
        }
    }
    dfs(1, len);
    long long ans = 0;
    for(int i=0;i<3;i++)
        for (int j = 0; j < 3; j++)
        {
            ans += dp[1][len][i][j];
            ans %= mod;
        }
    cout << ans;
    return 0;
}

 

posted @ 2022-05-16 23:41  Thinker-X  阅读(30)  评论(0)    收藏  举报