Codeforces Round #343 (Div. 2) C. Famil Door and Brackets
题目链接:
http://codeforces.com/contest/629/problem/C
题意:
长度为n的括号,已经知道的部分的长度为m,现在其前面和后面补充‘(',或')',使得其长度为n,且每个左括号都能找到右括号与它匹配。
题解:
dp[i][j]表示长度为i,平衡度为j的合法括号序列的总数,这里平衡度定义是‘('比')'多多少个,或')'比’('多多少个。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 2222; 8 const int maxm = 1e5 + 10; 9 const int mod = 1e9 + 7; 10 const int INF = 0x3f3f3f3f; 11 typedef __int64 LL; 12 13 LL dp[maxn][maxn]; 14 void pre() { 15 memset(dp, 0, sizeof(dp)); 16 dp[0][0] = 1; 17 for (int i = 1; i < maxn; i++) { 18 dp[i][0] = dp[i - 1][1]; 19 for (int j = 1; j <= i; j++) { 20 dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % mod; 21 } 22 } 23 } 24 25 int n, m; 26 char str[maxm]; 27 28 int main() { 29 pre(); 30 scanf("%d%d", &n, &m); 31 scanf("%s", str); 32 int l = 0, r = 0, mi = INF; 33 for (int i = 0; i < m; i++) { 34 if (str[i] == '(') l++; 35 else r++; 36 mi = min(mi, l - r); 37 } 38 LL ans = 0; 39 for (int i = 0; i <= n - m; i++) { 40 for (int j = max(0, -mi); j <= i; j++) { 41 int t = j + l - r; 42 if (t > n - m - i) continue; 43 ans = (ans + dp[i][j] * dp[n - m - i][t] % mod) % mod; 44 } 45 } 46 printf("%I64d\n", ans); 47 return 0; 48 }