codeforce 149D Coloring Brackets ----区间dp

题目大意:给出一组括号,询问你给括号上色的情况数,颜色有两种,要求有两点:

                ①一对匹配的括号,最多且必须有一个上色,即每一对对应的括号都是一个有颜色,另一个没有颜色。

                ②相邻的两个字符,不能为同一种颜色,但是可以是都不染色。

dp[i][j][k1][k2]表示区间[i,j]且i为颜色k1、j为颜色k2时,合法解的数目。我们可以假设0为不染色、1和2为另外两种颜色。

DP方程有两个部分,第一部分为当i和j为一对匹配的括号时,需要注意满足条件一。

          第二部分为当i匹配的后半括号时,注意条件二来进行状态转移。

这里分别拿出一个例子来详细说明:

  b[i]为处理出来的辅助数组,值的意义为a[i]字符对应另一半括号的位置。左右括号相互标明。

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

     因为左边没染色,右边为颜色1,所以左边i+1无颜色限制而右边的j-1不能为颜色1,能够转移到这个状态的状态有6个。枚举k1,k2的值,并且注意写全能够继承的状态。

  ②  if(k3==0||k4==0||k3!=k4)

    {
      dp[i][j][k1][k2]+=(dp[i][b[i]][k1][k3]*dp[b[i]+1][j][k4][k2])%mod;
      dp[i][j][k1][k2]%=mod;
    }

   枚举k1,k2,k3,k4.此时的 i和 j 一定不匹配,所以可以存在所有的3X3=9种的组合,需要注意的只有相互匹配的k1与k3(受限于条件1)与k3和k4(受限于条件2)。 此情况只有讨论到合法解时值才不为0,如若遇到dp[i][j][0][0]这种,那么会由于值为0而使结果不改变,不影响答案。

       具体代码如下:

#include<iostream>
using namespace std;
#define ll long long
const ll mod=1000000007;
ll dp[705][705][3][3];
int b[705],c[360];

int main()
{
    string a;
    cin>>a;
    int n=a.size();
    int i,k,j,s=1;
    for(i=0;i<n;i++)
    {
        if(a[i]=='(') c[s++]=i;
        else
        {
            b[c[s-1]]=i;
            b[i]=c[s-1];
            s--;
        }
    }
    for(i=0;i<n-1;i++) 
    if(b[i]==i+1)
    {
        dp[i][i+1][0][1]=dp[i][i+1][1][0]=1;
        dp[i][i+1][0][2]=dp[i][i+1][2][0]=1;
        //dp[i][i+1][0][0]=1;
    }
    for(k=1;k<n;k++)
    for(i=0;i+k<n;i++)
    {
        j=i+k;
        if(b[i]==j)
        {
            dp[i][j][0][1]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][2])%mod;
            dp[i][j][0][2]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1])%mod;
            dp[i][j][1][0]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1]+dp[i+1][j-1][2][2])%mod;
            dp[i][j][2][0]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][1][2])%mod;
        }
        else if(b[i]<j)
        {
            int k1,k2,k3,k4;
            for(k1=0;k1<=2;k1++)
            for(k2=0;k2<=2;k2++)
            for(k3=0;k3<=2;k3++)
            for(k4=0;k4<=2;k4++)
            {
                if(k3==0||k4==0||k3!=k4)
                {
                    dp[i][j][k1][k2]+=(dp[i][b[i]][k1][k3]*dp[b[i]+1][j][k4][k2])%mod;
                    dp[i][j][k1][k2]%=mod;
                }
            }
        }
    }
    ll ans=0;
    for(i=0;i<=2;i++)
    for(j=0;j<=2;j++)
    {
        //cout<<dp[0][n-1][i][j]<<endl;
        ans=(ans+dp[0][n-1][i][j])%mod;
    }
    cout<<ans<<endl;
}
原文地址:https://www.cnblogs.com/wsblm/p/10713039.html