给定一个合法括号序列,对序列按照如下方法染色:
- 每个括号的颜色:红色、蓝色、或不染色;
- 每对匹配的括号:有且仅有其中一个被染色;
- 相邻两个括号:若都有颜色,要求它们的颜色互不相同。
求符合条件的染色方案数,对 109+7 取模。
序列长度:2≤∣s∣≤700.
区间DP.
将颜色映射到三个数:
Color=⎩⎨⎧012No ColorRedBlue
设 f[l][r][x][y] 为区间 [l,r] 内,且 Colorl=x,Colorr=y 的方案数。
下面分类讨论状态转移方式:#
情况一:()#
若 l+1=r,则这段序列仅有一对左右括号,只能对其中一个染色。
作为初始情况,可直接赋值:
f[l][r][0][1]=f[l][r][0][2]=f[l][r][1][0]=f[l][r][2][0]=1
情况二:(……)#
若 l 与 r 配成一对括号,则枚举 Colorl+1 和 Colorr−1,从 f[l+1][r−1] 进行转移。
f[l][r][x][y]=i=0∨i=x∑j=0∨j=y∑f[l+1][r−1][i][j]
情况三:(……)…(…)#
要求 l 是左括号,r 是右括号。设 R[i] 表示与 i 配对的右括号。
用 f[l][R[l]]×f[R[l]+1][r] 进行转移,具体过程要枚举四个颜色,就不做形式化表达了。
for(int i = 0; i <= 2; i++) {
for(int j = 0; j <= 2; j++) {
for(int p = 0; p <= 2; p++) {
for(int q = 0; q <= 2; q++) {
if((j == 1 && p == 1) || (j == 2 && p == 2)) continue;
(f[l][r][i][q] += (f[l][R[l]][i][j] * f[R[l] + 1][r][p][q]) % mod) %= mod;
}
}
}
}
cpp