原题传送:http://www.spoj.pl/problems/SQRBR
动态规划。
设f[i][j]表示前i个位置在合法情况下缺少j个右括号的方案数。
转移方程为:
f[i][j] = f[i-1][j-1] (第i个地方必须为'[')
f[i][j] = f[i-1][j-1] + f[i-1][j+1] (分第i个位置放左括号和右括号的情况)
写的第一份代码不是很严谨,j-1变为负值,但spoj判ac了。
1 #include <stdio.h> 2 #include <string.h> 3 #define N 205 4 5 int f[N][N], n, k; 6 bool h[N]; 7 8 int main() 9 { 10 int t, d; 11 scanf("%d", &t); 12 while(t--) 13 { 14 scanf("%d%d", &n, &k); 15 memset(h, 0, sizeof h); 16 memset(f, 0, sizeof f); 17 f[0][0] = 1; 18 for(int i = 1; i <= k; i++) 19 { 20 scanf("%d", &d); 21 h[d] = 1; 22 } 23 for(int i = 1; i <= 2 * n; i++) 24 { 25 for(int j = 0; j <= 2 * n; j++) 26 { 27 if(h[i]) 28 { 29 f[i][j] = f[i-1][j-1]; 30 } 31 else 32 { 33 f[i][j] = f[i-1][j-1] + f[i-1][j+1]; 34 } 35 } 36 } 37 printf("%d ", f[2*n][0]); 38 } 39 return 0; 40 }
修改后为:
1 #include <stdio.h> 2 #include <string.h> 3 #define N 205 4 5 int f[N][N], n, k; 6 bool h[N]; 7 8 int main() 9 { 10 int t, d; 11 scanf("%d", &t); 12 while(t--) 13 { 14 scanf("%d%d", &n, &k); 15 memset(h, 0, sizeof h); 16 memset(f, 0, sizeof f); 17 f[0][0] = 1; 18 for(int i = 1; i <= k; i++) 19 { 20 scanf("%d", &d); 21 h[d] = 1; 22 } 23 for(int i = 1; i <= 2 * n; i++) 24 { 25 for(int j = 0; j <= 2 * n; j++) 26 { 27 if(h[i]) 28 { 29 if(j != 0) 30 f[i][j] = f[i-1][j-1]; 31 else 32 f[i][j] = 0; 33 } 34 else 35 { 36 if(j != 0) 37 f[i][j] = f[i-1][j-1] + f[i-1][j+1]; 38 else 39 f[i][j] = f[i-1][j+1]; 40 } 41 } 42 } 43 printf("%d ", f[2*n][0]); 44 } 45 return 0; 46 }