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 }

 

posted @ 2015-11-04 18:01  罗茜  阅读(1113)  评论(0编辑  收藏  举报