Codeforces149D - Coloring Brackets(区间DP)

题目大意

要求你对一个合法的括号序列进行染色,并且需要满足以下条件

1、要么不染色,要么染红色或者蓝色

2、对于任何一对括号,他们当中有且仅有一个被染色

3、相邻的括号不能染相同的颜色

题解

用区间dp[i][j][cl][cr]表示区间[i,j]被染色之后(第i个括号被染成cl色,第j个括号被染成cr色)的合法方案数

分为匹配和不匹配两种情况来处理,需要用到乘法原理,用记忆化比较好写~~~具体请看代码

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

#define MAXN 705

#define MOD 1000000007

typedef long long LL;

LL dp[MAXN][MAXN][3][3];

int match[MAXN],q[MAXN];

char s[MAXN];

bool check(int i,int j)

{

    if(i==0||j==0||i!=j) return true;

    return false;

}

LL dfs(int l,int r,int cl,int cr)

{

    LL &ret=dp[l][r][cl] [cr];

    if(ret!=-1) return ret;

    ret=0;

    if(match[l]==r)

    {

        if((cl==0)^(cr==0))

        {

            if(l+1==r) return ret=1;

            for(int i=0; i<3; i++)

                for(int j=0; j<3; j++)

                    if(check(cl,i)&&check(j,cr))

                        ret=(ret+dfs(l+1,r-1,i,j))%MOD;

        }

    }

    else

    {

        for(int i=0; i<3; i++)

            for(int j=0; j<3; j++)

                if(check(i,j))

                    ret=(ret+dfs(l,match[l],cl,i)*dfs(match[l]+1,r,j,cr))%MOD;

    }

    return ret;

}

int main()

{

    while(~scanf("%s",s+1))

    {

        int n=strlen(s+1),t=1;

        for(int i=1; i<=n; i++)

            if(s[i]=='(') q[t++]=i;

            else

                match[q[--t]]=i;

        LL ans=0;

        memset(dp,-1,sizeof(dp));

        for(int i=0; i<3; i++)

            for(int j=0; j<3; j++)

                ans=(ans+dfs(1,n,i,j))%MOD;

        printf("%I64d\n",ans);

    }

    return 0;

}

 

 

你可能感兴趣的:(codeforces)