题意:

给一个给定括号序列,给该括号上色,上色有三个要求

1、只有三种上色方案,不上色,上红色,上蓝色

2、每对括号必须只能给其中的一个上色

3、相邻的两个不能上同色,可以都不上色

求0-len-1这一区间内有多少种上色方案

我按最基本的区间dp思路果断跑了810ms,看了别人30ms的代码。。

就是要找0到n-1区间的方案数,当用到l到r区间的方案数时递归找l到r区间方案数

这样就省去记录所有的状态了

因为如果i与j不匹配的时候,只需要找到i到u和u+1到j的方案数就可以了(u为与i匹配的括号)

附上我的渣渣代码~

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <cstdio>
using namespace std;
const int mod=1e9+7;
char s[710];
int n,mapp[710];
long long dp[710][710][3][3];
void getmap()
{
    memset(mapp,0,sizeof(mapp));
    stack<int>q;
    while(!q.empty()) q.pop();
    for(int i=0; i<n; i++)
    {
        if(s[i]=='(') q.push(i);
        else
        {
            if(q.empty()) continue;
            int p=q.top();
            q.pop();
            mapp[p]=i;
            mapp[i]=p;
        }
    }
}
void solve()
{
    while(~scanf("%s",s))
    {
        n=strlen(s);
        getmap();
        memset(dp,0,sizeof(dp));
        for(int i=0; i<n-1; i++)
        {
            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;
            if(mapp[i]!=i+1)
                dp[i][i+1][0][0]=dp[i][i+1][1][2]=dp[i][i+1][2][1]=1;
        }
        for(int l=2; l<n; l++)
        {
            for(int i=0; i+l<n; i++)
            {
                int j=i+l;
                if(mapp[i]==j)
                {
                    for(int p=0; p<=2; p++)
                    {
                        for(int q=0; q<=2; q++)
                        {
                            if(q!=1)
                                dp[i][j][0][1]=(dp[i][j][0][1]+dp[i+1][j-1][p][q])%mod;
                            if(p!=1)
                                dp[i][j][1][0]=(dp[i][j][1][0]+dp[i+1][j-1][p][q])%mod;
                            if(q!=2)
                                dp[i][j][0][2]=(dp[i][j][0][2]+dp[i+1][j-1][p][q])%mod;
                            if(p!=2)
                                dp[i][j][2][0]=(dp[i][j][2][0]+dp[i+1][j-1][p][q])%mod;
                        }
                    }
                }
                else
                {
                    int u=mapp[i];
                    for(int p=0; p<=2; p++)
                        for(int q=0; q<=2; q++)
                            for(int x=0; x<=2; x++)
                                for(int y=0; y<=2; y++)
                                    if(!((x==1&&y==1)||(x==2&&y==2)))
                                        dp[i][j][p][q]=(dp[i][j][p][q]+(dp[i][u][p][x]*dp[u+1][j][y][q])%mod)%mod;
                }
            }
        }
        long long ans=0;
        for(int i=0; i<=2; i++)
            for(int j=0; j<=2; j++)
                ans=(ans+dp[0][n-1][i][j])%mod;
        printf("%lld\n",ans);
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    solve();
    return 0;
}