Codeforces Round #106 (Div. 2), problem: (D) Coloring Brackets 区间DP+组合

题意:给括号对染色,这里的括号对的确定必须是括号a,b之间必须是没有括号,或者是还有完整的括号

做法:区间DP,先使最小的括号染色,然后根据区间两端是否可以匹配,进行分别计算。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#define LL long long
#define mod  1000000007
const int LMT=705;
using namespace std;
char str[LMT];
LL dp[LMT][LMT][3][3];//定义的时候要小心啊...
bool is[LMT][LMT];
int main()
{
    int len;
    LL ans=0;
    stack<int>q;
    scanf("%s",str);
    len=strlen(str);
    for(int i=0;i<len;i++)
    if(str[i]=='(')q.push(i);
    else
    {
        is[q.top()][i]=1;
        q.pop();
    }
    for(int i=0;i<len-1;i++)
    if(is[i][i+1])
    { dp[i][i+1][0][1]=dp[i][i+1][0][2]
       =dp[i][i+1][1][0]=dp[i][i+1][2][0]=1;
    }
    for(int k=3;k<=len;k++)
      for(int i=0,j;i+k-1<len;i++)
      {
          j=i+k-1;
          if(is[i][j])//能盖就盖吧
          {
           for(int c10=0;c10<3;c10++)
            for(int c01=0;c01<3;c01++)
            if((c10||c01)&&c10*c01==0)
              for(int c20=0;c20<3;c20++)
              if(c20!=c10||c20*c10==0)
                for(int c02=0;c02<3;c02++)
                if(c01!=c02||c01*c02==0)
                {
                    dp[i][j][c10][c01]+=dp[i+1][j-1][c20][c02];
                    dp[i][j][c10][c01]%=mod;
                }
          }
           else if(str[i]=='('&&str[j]==')')
           {
               int kk;
               for(kk=i;kk<=j&&!is[i][kk];kk++);
             if(kk<=j)
               for(int c10=0;c10<3;c10++)
                 for(int c01=0;c01<3;c01++)
                  for(int c20=0;c20<3;c20++)
                  if(c20!=c01||c20*c01==0)
                     for(int c02=0;c02<3;c02++)
                     {
                         dp[i][j][c10][c02]+=dp[i][kk][c10][c01]*dp[kk+1][j][c20][c02];
                         dp[i][j][c10][c02]%=mod;
                     }
           }
      }
      for(int c10=0;c10<3;c10++)
        for(int c01=0;c01<3;c01++)
        {
            ans+=dp[0][len-1][c10][c01];
            ans%=mod;
        }
        printf("%I64d\n",ans);
    return 0;
}


你可能感兴趣的:(Codeforces Round #106 (Div. 2), problem: (D) Coloring Brackets 区间DP+组合)