1. 程式人生 > >Codeforces Round #106 (Div. 2) Coloring Brackets(區間DP)

Codeforces Round #106 (Div. 2) Coloring Brackets(區間DP)

strlen 括號序列 pre names clas 依賴 return stack pri

題意:給你一組括號序列,讓你進行染色,對於每個括號,有無色,紅色,藍色三種方案。染色需要滿足這樣的條件:互相匹配的括號,有且只有一個有顏色,相鄰的括號不能顏色相同(可以同為無色),問合法的染色方案數(答案%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; }

Codeforces Round #106 (Div. 2) Coloring Brackets(區間DP)