Codeforces Round #106 (Div. 2) Coloring Brackets(区间DP)
题意:给你一组括号序列,让你进行染色,对于每个括号,有无色,红色,蓝色三种方案。染色需要满足这样的条件:互相匹配的括号,有且只有一个有颜色,相邻的括号不能颜色相同(可以同为无色),问合法的染色方案数(答案%1e9+7)
分析:根据题意能够看出是区间DP,并且状态转移的时候,依赖于左右两端的颜色,所以我们用dp[i][j][x][y]表示i到j的区间内左端颜色为x,右端颜色为y的方案数。
区间[i,j]可以由两种情况得到,一种是str[i],str[j]匹配,产生新的相匹配的括号,考虑在只有一端染色的情况下,由[i+1][j-1]的状态转移得到
二是由已经匹配好的两个区间得到,这里,我们可以先用栈预处理出,括号的匹配对应关系,这样就能找到匹配好的区间位置。
代码如下:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <vector> #include <queue> #include <functional> #include <map> #include <vector> #include <stack> using namespace std; #define INF 100000000 typedef long long LL; stack<int>S; const int MOD=1e9+7; LL dp[710][710][3][3]; LL to[710]; char str[710]; int main() { scanf("%s",str+1); int len=strlen(str+1); for(int i=1;i<=len;i++) { if(str[i]=='(') S.push(i); else { int x=S.top(); to[i]=x; to[x]=i; S.pop(); } } for(int i=1;i<=len-1;i++) { if(str[i]=='('&&str[i+1]==')') { dp[i][i+1][1][0]=1; dp[i][i+1][2][0]=1; dp[i][i+1][0][1]=1; dp[i][i+1][0][2]=1; } } for(int l=3;l<=len-1;l+=2) for(int i=1;i<=len-l;i++) { int j=i+l; if(str[i]=='('&&str[j]==')') { dp[i][j][1][0]+=(dp[i+1][j-1][2][0]+dp[i+1][j-1][2][1]+dp[i+1][j-1][2][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]); dp[i][j][1][0]%=MOD; dp[i][j][2][0]+=(dp[i+1][j-1][1][0]+dp[i+1][j-1][1][1]+dp[i+1][j-1][1][2]+dp[i+1][j-1][0][1]+dp[i+1][j-1][0][2]+dp[i+1][j-1][0][0]); dp[i][j][2][0]%=MOD; dp[i][j][0][1]+=(dp[i+1][j-1][0][2]+dp[i+1][j-1][1][2]+dp[i+1][j-1][2][2]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]); dp[i][j][0][1]%=MOD; dp[i][j][0][2]+=(dp[i+1][j-1][0][1]+dp[i+1][j-1][1][1]+dp[i+1][j-1][2][1]+dp[i+1][j-1][1][0]+dp[i+1][j-1][2][0]+dp[i+1][j-1][0][0]); dp[i][j][0][2]%=MOD; } int k=to[i]; for(int x=0;x<3;x++) for(int y=0;y<3;y++) { LL res=0; for(int q1=0;q1<3;q1++) for(int q2=0;q2<3;q2++) { if(q1==q2&&q1!=0)continue; res=(res+dp[i][k][x][q1]*dp[k+1][j][q2][y])%MOD; } dp[i][j][x][y]=max(dp[i][j][x][y],res); } } LL ans=0; for(int i=0;i<=2;i++) for(int j=0;j<=2;j++) { ans+=dp[1][len][i][j]; } printf("%lld\n",ans%MOD); return 0; }