dp,洛谷p1044,栈
程序员文章站
2022-07-13 11:51:42
...
思路:
状态: dp(i,j)表示进栈了i个,出栈了j个,显然,i>=j
dp(i-1,j) 再进一个栈 就是dp(i,j) ,dp(i,j-1)再出一个栈就是dp(i,j)
故dp(i,j)=dp(i-1,j)+dp(i,j-1);
边界条件:dp(i,0) 进栈i个,出栈0个,情况只有一种
#include<iostream>
using namespace std;
typedef long long ll;
/*
状态: dp(i,j)表示进栈了i个,出栈了j个,显然,i>=j
dp(i-1,j) 再进一个栈 就是dp(i,j) ,dp(i,j-1)再出一个栈就是dp(i,j)
故dp(i,j)=dp(i-1,j)+dp(i,j-1);
边界条件:dp(i,0) 进栈i个,出栈0个,情况只有一种
*/
ll dp[20][20] = {0};
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++){
dp[i][1] = 1;
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= i+1; j++){
if (i == 1 && j == 1);
else dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
cout << dp[n][n];
return 0;
}
/*
解释一下原理:
建立数组f。f[i]表示i个数的全部可能性。
f[0] = 1, f[1] = 1; //当然只有一个
设 x 为当前出栈序列的最后一个,则x有n种取值
由于x是最后一个出栈的,所以可以将已经出栈的数分成两部分
比x小
比x大
比x小的数有x-1个,所以这些数的全部出栈可能为f[x-1]
比x大的数有n-x个,所以这些数的全部出栈可能为f[n-x]
这两部分互相影响,所以一个x的取值能够得到的所有可能性为f[x-1] * f[n-x]
另外,由于x有n个取值,所以
ans = f[0]*f[n-1] + f[1]*f[n-2] + ... + f[n-1]*f[0];
这,就是传说中的卡特兰数
*/
int n, f[30];
int main2()
{
//递推实现卡特兰数
scanf("%d", &n);
f[0] = 1, f[1] = 1;
for (int i = 2; i <= n; i++)
for (int j = 0; j<i; j++)
f[i] += f[j] * f[i - j - 1]; //递推公式
printf("%d", f[n]);
return 0;
}
上一篇: P1044 栈(洛谷)
下一篇: 洛谷日常:P1044 栈(1)