codeforces 629C Famil Door and Brackets (dp + 枚举)

题目链接:

  codeforces 629C Famil Door and Brackets

题目描述:

  给出完整的括号序列长度n,现在给出一个序列s长度为m。枚举串p,q,使得p+s+q是合法的括号串,长度为n,问p,q的取值数目。

解题思路:

  枚举p的长度,可以直接得到q的长度。因为要满足在任意位置'(' 数目大于 ’)‘ 的数目,所以统计一下s串中 ’(‘ - ')' 的最小数目minx。dp[i][j] 代表 到位置 i 时,满足 '(' - ')' == j 的情况数目。然后枚举p的 j (i > -minx), 然后根据p串推出q串满足合法串的状态,两者相乘。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef __int64 LL;
 5 const int INF = 1e9 + 7;
 6 const int maxn = 100010;
 7 const int N = 2100;
 8 const int mod = 1e9+7;
 9 
10 
11 ///dp[i][j] 到第i个位置,有j个不平衡(括号
12 LL dp[N][N], n, m;
13 char str[maxn];
14 
15 void init ()
16 {
17     int num = 2010;
18     memset (dp, 0, sizeof(dp));
19     dp[0][0] = 1;
20 
21     for (int i=1; i<=num; i++)
22         for (int j=0; j<=i; j++)
23         {
24             if (j > 0)
25                 dp[i][j] = (dp[i][j] + dp[i-1][j-1]) % mod;
26             dp[i][j] = (dp[i][j] + dp[i-1][j+1]) % mod;
27         }
28 }
29 
30 LL solve ()
31 {
32     int minx = INF, tmp = 0, num = n - m;
33 
34     for (int i=0; str[i]; i++)
35     {
36         if (str[i] == '(')
37             tmp ++;
38         else
39             tmp --;
40         minx = min (minx, tmp);
41     }
42 
43     LL ans = 0;
44     for (int i=0; i<=num; i++)
45         for (int j=0; j<=i; j++)
46             if (j >= -minx && num-i >= j + tmp)
47                 ans = (ans + dp[i][j]*dp[num-i][j+tmp]) % mod;
48 
49     return ans;
50 }
51 
52 int main ()
53 {
54     init ();
55     while (scanf ("%I64d %I64d", &n, &m) != EOF)
56     {
57         scanf ("%s", str);
58         printf ("%I64d\n", solve ());
59     }
60     return 0;
61 }

 

posted @ 2016-05-11 11:09  罗茜  阅读(326)  评论(0编辑  收藏  举报