链接:点击打开链接
题意:给一个给定括号序列,给该括号序列上色,上色有三个要求1.每个括号只有三种情况,不上色,上红色,上蓝色,2.每对括号必须只能给其中的一个上色3.相邻的两个不能上同色,可以都不上色,求所有的上色种数
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const long long MOD=1000000007;
char s[705];
long long dp[705][705][3][3],a[705],b[705];
int main(){
long long i,j,k,l,p,x,y,xx,yy,ans,len;
while(scanf("%s",s+1)!=EOF){
p=1;
len=strlen(s+1);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(dp,0,sizeof(dp));
for(i=1;i<=len;i++){
if(s[i]=='(')
a[p++]=i;
else{
b[a[p-1]]=i;
b[i]=a[p-1];
p--;
}
} //模拟栈进行括号匹配
for(i=1;i<len;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;
}
for(l=2;l<=len;l++){
for(i=1;i<=len-l+1;i++){
j=i+l-1;
if(b[i]==j){
dp[i][j][0][1]+=(dp[i+1][j-1][0][0]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][2]+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][2][0]+dp[i+1][j-1][0][2]+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][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][1][2])%MOD;
} //匹配的括号只能有一个染色并且颜色不能相同
else if(b[i]<j){
for(x=0;x<=2;x++)
for(y=0;y<=2;y++)
for(xx=0;xx<=2;xx++)
for(yy=0;yy<=2;yy++)
if(xx==0||yy==0||xx!=yy){
dp[i][j][x][y]+=(dp[i][b[i]][x][xx]*dp[b[i]+1][j][yy][y])%MOD;
dp[i][j][x][y]%=MOD;
} //处理相邻两个括号不能是相同颜色的情况
}
}
}
ans=0;
for(i=0;i<=2;i++)
for(j=0;j<=2;j++)
ans=(ans+dp[1][len][i][j])%MOD;
printf("%I64d\n",ans);
}
return 0;
}