codeforces 149D Coloring Brackets (区间DP + dfs)
题目链接:
codeforces 149D Coloring Brackets
题目描述:
给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的。
1,每个括号只有三种选择:涂红色,涂蓝色,不涂色。
2,每对括号有且仅有其中一个被涂色。
3,相邻的括号不能涂相同的颜色,但是相邻的括号可以同时不涂色。
解题思路:
这个题目的确是一个好题,无奈我太蠢,读错题意。以为(())这样的括号序列在涂色的时候,第一个括号与第三个括号也可以看做是一对。这样的话还要统计合法的括号匹配数目,还要计算涂色的方案。然后想了好久好久。最后发现并不是这样的,给出的括号序列,括号的匹配都是固定的,也就是说只需要给这些固定匹配的括号按照上面限制涂色就好啦。
可以定义 dp[l][r][x][y] 表示区间 [l, r] 在左端点涂x色,右端点涂y色的情况下的方案数。其中0代表不涂色, 1代表涂红色, 2代表涂蓝色。
窝们可以把括号序列可以分为两类分别进行状态转移:
括号套括号,状态转移是:dp[l][r][x][y] += dp[l+1][r-1][x'][y'] (0<=x'<3, x'!=x, 0<=y'<3, y!=y')
多个匹配串连起来,转台转移是:dp[l][r][x][y] += dp[l][nu][x'][y'] * dp[nu][r][x''][y''] (nu是l对应的另一边括号)
当l+1 == r的时候有:dp[l][r][0][1] = 1; dp[l][r][1][0] = 1;
dp[l][r][0][2] = 1; dp[l][r][2][0] = 1;
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 typedef __int64 LL; 9 const LL mod = 1000000007; 10 const LL maxn = 710; 11 LL dp[maxn][maxn][3][3], match[maxn], tep[maxn]; 12 13 void get_macth (char a[]) 14 { 15 int p = 0; 16 for (int i=0; a[i]; i++) 17 { 18 if (a[i] == '(') 19 tep[p ++] = i; 20 else 21 { 22 match[i] = tep[p-1]; 23 match[tep[p-1]] = i; 24 p --; 25 } 26 } 27 } 28 29 void dfs (int l, int r) 30 { 31 if (l + 1 == r) 32 { 33 dp[l][r][0][1] = 1; 34 dp[l][r][1][0] = 1; 35 dp[l][r][0][2] = 1; 36 dp[l][r][2][0] = 1; 37 return ; 38 } 39 40 else if (match[l] == r) 41 { 42 dfs (l+1, r-1); 43 for (int i=0; i<3; i++) 44 for (int j=0; j<3; j++) 45 { 46 if (j != 1) 47 dp[l][r][0][1] = (dp[l][r][0][1] + dp[l+1][r-1][i][j]) % mod; 48 if (i != 1) 49 dp[l][r][1][0] = (dp[l][r][1][0] + dp[l+1][r-1][i][j]) % mod; 50 if (j != 2) 51 dp[l][r][0][2] = (dp[l][r][0][2] + dp[l+1][r-1][i][j]) % mod; 52 if (i != 2) 53 dp[l][r][2][0] = (dp[l][r][2][0] + dp[l+1][r-1][i][j]) % mod; 54 } 55 return ; 56 } 57 58 else 59 { 60 int nu = match[l]; 61 dfs (l, nu); 62 dfs (nu+1, r); 63 64 for (int i=0; i<3; i++) 65 for (int j=0; j<3; j++) 66 for (int x=0; x<3; x++) 67 for (int y=0; y<3; y++) 68 if (!(x==1&&y==1 || x==2&&y==2)) 69 dp[l][r][i][j] = (dp[l][r][i][j] + dp[l][nu][i][x]*dp[nu+1][r][y][j]) % mod; 70 } 71 72 } 73 74 int main () 75 { 76 char s[maxn]; 77 78 while (scanf ("%s", s) != EOF) 79 { 80 memset(dp, 0, sizeof(dp)); 81 int len = strlen (s); 82 get_macth (s); 83 dfs (0, len-1); 84 85 LL ans = 0; 86 for (int i=0; i<3; i++) 87 for (int j=0; j<3; j++) 88 ans = (ans + dp[0][len-1][i][j]) % mod; 89 printf ("%I64d\n", ans); 90 91 } 92 return 0; 93 }
本文为博主原创文章,未经博主允许不得转载。