CF149D Coloring Brackets
一道很有意思的区间DP
我们用0表示不染色,1表示红色,2表示蓝色
定义状态fi,j,k,u表示将合法序列[i,j]染色且i染为k,j染为u的方案数
那么序列就可以分为三种情况
1°:()
fi,j,0,1=fi,f,1,0=fi,j,0,2=fi,j,2,0
2°:((…))
fi,j,0,k=u=0∑u≤2v=0∑v≤2,v=kfi+1,j−1,u,v
fi,j,k,0=u=0∑u≤2,u=kv=0∑v≤2fi+1,j−1,u,v
3°:(…)(…)
用l,rr,ll,r分别表示上面括号的位置
fl,r,u,v=a=0∑a≤2b=0∑b≤2c=0∑c≤2d=0∑d≤2fl,rr,a,b∗fll,r,c,d并且需要满足端点颜色不同
那么只需要递归转移状态即可
代码
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MOD = 1000000007;
char str[705]; int stk[705], top, poi[705], col[705]; long long f[705][705][3][3];
void dfs(int l, int r) { if (l + 1 == r) f[l][r][1][0] = f[l][r][2][0] = f[l][r][0][2] = f[l][r][0][1] = 1; else if (poi[l] == r) { dfs(l + 1, r - 1); for (int i = 0; i <= 2; i++) for (int j = 0; j <= 2; j++) { if (j != 2) f[l][r][0][2] = (f[l + 1][r - 1][i][j] + f[l][r][0][2]) % MOD; if (j != 1) f[l][r][0][1] = (f[l + 1][r - 1][i][j] + f[l][r][0][1]) % MOD; if (i != 2) f[l][r][2][0] = (f[l + 1][r - 1][i][j] + f[l][r][2][0]) % MOD; if (i != 1) f[l][r][1][0] = (f[l + 1][r - 1][i][j] + f[l][r][1][0]) % MOD; } } else { dfs(l, poi[l]), dfs(poi[l] + 1, r); for (int i = 0; i <= 2; i++) { for (int j = 0; j <= 2; j++) { if (j > 0 && j == i) continue; for (int k = 0; k <= 2; k++) for (int u = 0; u <= 2;u++) f[l][r][k][u] = (f[l][r][k][u] + f[l][poi[l]][k][i] * f[poi[l] + 1][r][j][u]) % MOD; } } } }
int main() { scanf("%s", str + 1); int len; for (int i = 1; str[i]; i++) { if (str[i] == '(') stk[++top] = i; else if(str[i] == ')') poi[stk[top--]] = i; len = i; } dfs(1, len); long long ans = 0; for (int i = 0; i <= 2; i++) { for (int j = 0; j <= 2; j++) ans = (ans + f[1][len][i][j]) % MOD; } printf("%lld", ans); return 0; }
|