Codeforces Round #106 (Div. 2) Coloring Brackets

链接

https://codeforces.com/contest/149/problem/D

题意

给定一个字符串 $s$,是一个合法的括号序列。我们打算对这个括号序列进行染色,有以下要求:

  • 每个字符有三种情况:不染色,染成红色,染成蓝色。
  • 每对匹配的括号,有且仅有一个字符被染色。
  • 所有相邻的两个字符,不能染成同一种颜色。

求满足要求的括号序列染色方案数,答案可能很大,输出答案对 $1e9 + 7$ 取模的结果。

思路

区间 DP。

因为 $s$ 是一个合法的括号序列,所以每个 ( 都有一个对应的 )

若 $s_i$ 为 (,将与其对应的 ) 记为 $nxt_i$,定义 $dp_{l,r,cl,cr}$ 为区间左端 $l$ 颜色为 $cl$ 右端 $r$ 颜色为 $cr$ 的方案数,考虑如下情况:

  • 当 $nxt_l=r$ 时,$dp_{l,r,cl,cr}=\sum dp_{l+1,r-1,cl^{‘},cr^{‘}}$;
  • 当 $nxt_l\neq r$ 时,$dp_{l,r,cl,cr}=\sum dp_{l,nxt_l,cl,cr^{‘}} \times dp_{nxt_l+1,r,cl^{‘},cr}$;
  • 当 $l+1=r$ 时,$dp_{l,r,cl,cr}=1$。

当左右端颜色符合要求才能转移,记忆化搜索求解。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long double LD;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VPII;
// head
const LL MOD=1e9+7;
const int N=705;
int nxt[N],stk[N],top;
LL dp[N][N][3][3];
LL dfs(int l,int r,int cl,int cr) {
if(dp[l][r][cl][cr]!=-1) return dp[l][r][cl][cr];
dp[l][r][cl][cr]=0;
if(l+1==r) {
if(cl==cr||cl+cr==3) return 0;
return dp[l][r][cl][cr]=1;
}
if(nxt[l]==r) {
if(cl==cr||cl+cr==3) return 0;
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
if(cl&&i&&cl==i||j&&cr&&j==cr) continue;
dp[l][r][cl][cr]=(dp[l][r][cl][cr]+dfs(l+1,r-1,i,j))%MOD;
}
}
return dp[l][r][cl][cr];
}
dp[l][r][cl][cr]=0;
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
if(i&&j&&i==j) continue;
dp[l][r][cl][cr]=(dp[l][r][cl][cr]+dfs(l,nxt[l],cl,i)*dfs(nxt[l]+1,r,j,cr))%MOD;
}
}
return dp[l][r][cl][cr];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;cin>>s;
int n=SZ(s);
for(int i=n-1;~i;i--) {
if(s[i]==')') stk[++top]=i;
else nxt[i]=stk[top--];
}
memset(dp,-1,sizeof dp);
LL res=0;
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
res=(res+dfs(0,n-1,i,j))%MOD;
}
}
cout<<res<<'\n';
return 0;
}