九度oj 1547
- 题目描述:
-
给定一个初始为空的栈,和n个操作组成的操作序列,每个操作只可能是出栈或者入栈。
要求在操作序列的执行过程中不会出现非法的操作,即不会在空栈时执行出栈操作,同时保证当操作序列完成后,栈恰好为一个空栈。
求符合条件的操作序列种类。
例如,4个操作组成的操作序列符合条件的如下:
入栈,出栈,入栈,出栈
入栈,入栈,出栈,出栈
共2种。
- 输入:
-
输入包含多组测试用例,每组测试用例仅包含一个整数n(1<=n<=1000)。
- 输出:
-
输出仅一个整数,表示符合条件的序列总数,为了防止总数过多超出int的范围,结果对1000000007取模(mod 1000000007)。
- 样例输入:
-
2 4 10
- 样例输出:
-
1 2 42
1 /*i = 3; j = 1 2 111 0 3 110 1 4 101 1 5 6 i = 2; j = 1 7 110 8 101 9 10 i = 3 j = 0 11 111 12 3 3 = 2 3 + 3 2 13 i = 3; j = 2 14 1110 0 15 1101 0 16 1011 0 17 1100 1 18 1010 1 19 20 i = 2; j = 2 21 1100 22 1010 23 24 i = 3; j = 1 25 1110 26 1101 27 1011 28 */ 29 /* 30 状态dp[i][j](i >= j)表示入栈i次出栈j次的种类数 31 32 状态转移方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]
最后一个是入栈 最后一个是出栈 33 */ 34 #include <cstdio> 35 #include <cstdlib> 36 #define MAX 1002 37 38 int dp[MAX][MAX]; 39 int top(int n) { 40 int temp = n/2; 41 if(temp *2 == n) { 42 return temp; 43 } 44 return temp + 1; 45 } 46 int main(int argc, char const *argv[]) 47 { 48 int n; 49 for(int i = 0; i < 502; i++) { 50 dp[i][0] = 1; 51 dp[0][i] = 0; 52 } 53 for(int i = 1; i <= 502; i++) { 54 for(int j = 1; j <= 502; j++) { 55 if(i >= j) { 56 dp[i][j] = (dp[i-1][j] + dp[i][j-1])%1000000007; 57 } 58 else { 59 dp[i][j] = 0; 60 } 61 } 62 } 63 while(scanf("%d",&n) != EOF) { 64 if(n & 1) { 65 printf("%d\n",0); 66 } 67 else { 68 printf("%d\n",dp[n/2][n/2]); 69 } 70 71 72 } 73 return 0; 74 } 75
这道题一开始完全没有思路,最重要的是得出状态转移方程,利用动态规划求解。
另外,while(scanf("%d",&n))会导致结果output limit exceed
要写成 while(scanf("%d",&n) != EOF)
还有,题目说“同时保证当操作序列完成后,栈恰好为一个空栈”不是说它的输入保证这一点,而是如果有这样的输入,答案是0,也就是如果输入时奇数,答案是0