1. 程式人生 > 實用技巧 >Coloring Brackets

Coloring Brackets

題目連結:https://vjudge.net/problem/CodeForces-149D

題意:給你個完全匹配的括號序列,你現在可以給這個匹配的括號序列中的括號染色,且有三個要求:1.每個括號只有三種情況,不上色,上紅色,上藍色。2.每對括號必須只能給其中的一個上色,且必須給一個上色。3.相鄰的兩個不能上同色,可以都不上色。求滿足條件的括號序列染色的方法數。

思路:假設不染色為0,另外兩種色為1,2。那對於一個匹配的括號對來說,只允許(1,0),(2,0),(0,1),(0,2)。定義dp[l][r][i][j]表示區間[l,r]的左端點狀態為i,右端點狀態為j時的當前區間方案數。

可以得出當l+1=r時,只有上述四種存在方案數。

除此以外還有兩種情況
1.當前處理區間[l,r]兩端點恰好是一個匹配括號對
2.當前處理區間[l,r]兩端點不是一個匹配括號對

情況1可以先遞迴處理[l+1,r1]的方案,最後合併方案數。
情況2也可分治[l,b[l]][b[l]+1,r]兩個區間處理。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 705;
const int mod = 1000000007;
ll dp[maxn][maxn][3][3];
char a[maxn];
stack<int> zha;
int b[maxn]; int n; void dfs(int l,int r) { if(l+1==r)//只有那四種方案 { dp[l][r][1][0]=dp[l][r][0][1]=1; dp[l][r][2][0]=dp[l][r][0][2]=1; return; } if(b[l]==r) { dfs(l+1,r-1); for(int i=0;i<3;i++) for(int j=0;j<3;j++) {
if(j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mod; if(i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mod; if(j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mod; if(i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mod; } return; } int mid=b[l]; dfs(l,mid); dfs(mid+1,r); for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) for(int h=0;h<3;h++) { if (!(k==1&&h==1) && !(k==2&&h==2) && !(i==0&&k==0)) dp[l][r][i][j]=(dp[l][r][i][j]+dp[l][mid][i][k]*dp[mid+1][r][h][j])%mod; } } int main() { scanf("%s",a); n=strlen(a); for(int i=0;i<n;i++) { if(a[i]=='(') zha.push(i); else { b[i]=zha.top(); b[zha.top()]=i; zha.pop(); } } dfs(0,n-1); ll ans=0; for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans=(ans+dp[0][n-1][i][j])%mod; cout<<ans<<endl; }