Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)

题意:给你一组括号序列,让你进行染色,对于每个括号,有无色,红色,蓝色三种方案。染色需要满足这样的条件:互相匹配的括号,有且只有一个有颜色,相邻的括号不能颜色相同(可以同为无色),问合法的染色方案数(答案%1e9+7)

分析:根据题意能够看出是区间DP,并且状态转移的时候,依赖于左右两端的颜色,所以我们用dp[i][j][x][y]表示i到j的区间内左端颜色为x,右端颜色为y的方案数。

        区间[i,j]可以由两种情况得到,一种是str[i],str[j]匹配,产生新的相匹配的括号,考虑在只有一端染色的情况下,由[i+1][j-1]的状态转移得到

         二是由已经匹配好的两个区间得到,这里,我们可以先用栈预处理出,括号的匹配对应关系,这样就能找到匹配好的区间位置。

代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <functional>
#include  <map>
#include <vector>
#include <stack>
using namespace std;
#define INF 100000000
typedef long long LL;
stack<int>S;
const int MOD=1e9+7;
LL dp[710][710][3][3];
LL to[710];
char str[710];
int main()
{
    scanf("%s",str+1);
    int len=strlen(str+1);
    for(int i=1;i<=len;i++)
    {
        if(str[i]=='(')
        S.push(i);
        else
        {
           int x=S.top();
           to[i]=x;
           to[x]=i;
           S.pop();
        }
    }
    for(int i=1;i<=len-1;i++)
    {
       if(str[i]=='('&&str[i+1]==')')
       {
         dp[i][i+1][1][0]=1;
         dp[i][i+1][2][0]=1;
         dp[i][i+1][0][1]=1;
         dp[i][i+1][0][2]=1;
       }
    }

    for(int l=3;l<=len-1;l+=2)
        for(int i=1;i<=len-l;i++)
    {
        int j=i+l;
        if(str[i]=='('&&str[j]==')')
        {
            dp[i][j][1][0]+=(dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1]+dp[i+1][j-1][2][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]);
            dp[i][j][1][0]%=MOD;

            dp[i][j][2][0]+=(dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][1][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]);
            dp[i][j][2][0]%=MOD;

            dp[i][j][0][1]+=(dp[i+1][j-1][0][2]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]);
            dp[i][j][0][1]%=MOD;

            dp[i][j][0][2]+=(dp[i+1][j-1][0][1]+dp[i+1][j-1][1][1]+dp[i+1][j-1][2][1]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]);
            dp[i][j][0][2]%=MOD;
        }
           int k=to[i];
            for(int x=0;x<3;x++)
                for(int y=0;y<3;y++)
            {
                  LL res=0;
                  for(int q1=0;q1<3;q1++)
                     for(int q2=0;q2<3;q2++)
                  {
                      if(q1==q2&&q1!=0)continue;
                      res=(res+dp[i][k][x][q1]*dp[k+1][j][q2][y])%MOD;
                  }
                 dp[i][j][x][y]=max(dp[i][j][x][y],res);
            }
    }

     LL ans=0;
    for(int i=0;i<=2;i++)
     for(int j=0;j<=2;j++)
    {
        ans+=dp[1][len][i][j];
    }
    printf("%lld\n",ans%MOD);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/a249189046/p/9668200.html
今日推荐