洛谷1044栈C语言
这是一道利用了栈进行种类的求解的题目,一开始想使用深搜进行解决但是这样不仅时间复杂度会很高而且很难实现
没辙了,看题解——卡特兰数 ?什么鬼
后面我才意识到这道题和栈的所谓联系就是这个卡特兰数,事实上是一道考验知识点的动态规划题目
卡特兰数
卡特兰数(Catalan Number)是一组经典的组合数学序列,广泛应用于计算机科学和数学领域。它用来描述许多具有递归结构的问题,例如栈混洗、二叉树的构造、括号匹配等。
应用场景
-
栈混洗问题:(本题)
-
给定一个长度为 n 的序列,通过栈操作可以生成多少种不同的输出序列。(数字不重复)
-
-
合法括号序列:
-
构造长度为 2n2n 的合法括号序列(如 n=3n=3 时,可能的序列为
()()()
,(())()
,()(())
,(()())
,((()))
)。
-
-
二叉树的构造:
-
使用 nn 个节点可以构造多少种不同的二叉树。
-
-
凸多边形的三角剖分:
-
一个 n+2n+2 边形可以通过对角线划分为多少种不同的三角形。
-
-
路径计数问题:
-
在网格中从左下角到右上角的路径中,要求路径不越过对角线,计算有多少条路径。
-
使用动态规划进行卡特兰数的计算(栈混洗问题)
问题进行拆解(分治思想): 假设有长度为n的序列[1,2……n],我们通过栈操作生成所有可能的输出序列:
-
假设第一个出栈的元素是 kk(1≤k≤n1≤k≤n)。
-
在 k 出栈之前,必须先将 [1,2,…,k−1][1,2,…,k−1] 全部入栈并弹出,这对应于一个规模为k−1 的子问题。这些子问题有Ck-1种情况
-
在 k 出栈之后,剩下的 [k+1,k+2,…,n][k+1,k+2,…,n] 需要按照同样的规则生成输出序列,这对应于一个规模为n−k 的子问题,有Cn-k种情况(这里数字是不可能出现重复的——况且只让你输入了一个数字)
当前第一个出栈元素对应的总方案数:
方案数(n)=方案数(k−1)⋅方案数(n−k)
由于k可以是1-n中的任意一个值,需要将所有的情况进行相加才是真正该数量的数字进行栈混洗后的结果个数
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
int dp[55]={1};//栈混洗问题当中,当数组昌都为0时,只有一种可能的输出:啥都没有
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i]+=dp[j-1]*dp[i-j];
}
}
printf("%d",dp[n]);
return 0;
}