栈
【题目描述】
考虑这样一个问题,有一个1~n的操作数序列,栈的深度大于n。
现在可以进行以下两种操作:
(1)将一个数,从操作数序列的头端移到栈的头端;
(2)将一个数,从栈的头端移到输出序列的尾端;
使用这两种操作,由一个操作数序列就可以得到一系列的输出序列。
现在给定一个n,询问经过操作1~n操作数序列可能得到的输出序列的总数。
【输入描述】
输入一个整数n(1 ≤ n ≤ 18)。
【输出描述】
输出一个数,表示可能的输出序列的总数。
【样例输入】
3
【样例输出】
5
【数据范围及提示】
样例解释:
源代码: #include<cstdio> int n; long long ans=1; int main() //Catalan数。 { scanf("%d",&n); for (int a=1;a<=n;a++) ans=ans*(a*4-2)/(a+1); printf("%lld",ans); return 0; } /* 有必要详细地了解一下卡特兰数。 先用一道题来引出卡特兰数: 有10个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问有多少种排列方式。 解析: 我们可以先把这10个人从低到高排列,选择5个人排在第一排,那么剩下的5个人肯定是在第二排。 用0表示对应编号的人排在第一排,用1表示对应编号的人排在第二排,则含有5个0,5个1的序列,就对应一种方案。 比如:0000011111 就对应着: 第一排:0 1 2 3 4 第二排:5 6 7 8 9 比如:0101010101 就对应着: 第一排:0 2 4 6 8 第二排:1 3 5 7 9 所以问题相应的转换为满足条件的01序列有多少个。 观察规律,我们发现每个1的出现,前面必须有个相应的0,所以在从左到右的所有子序列中,0的个数总会大于等于1的个数。 那么这种数列究竟有多少种排列方式呢? 我们从左往右扫描,假设第一次出现1的个数等于0的个数是在第k位,那么在此之前,0的个数是大于1的个数的。在此之后,0的个数也是大于1的个数的,所以同理于进出栈问题。 即:f(n)=f(0)*f(n-1)+f(1)*f(n-2)+···+f(n-1)*f(0) Catalan公式:(令f(0)=0,f(1)=1) (1)f(n)=f(0)*f(n-1)+f(1)*f(n-2)+···+f(n-1)*f(0); (2)f(n)=C(2n,n)/(n+1); (3)f(n)=C(2n,n)-C(2n,n-1); 拓展问题: (1)一个栈的进栈序列为1 2 3 ··· n,询问有多少个不同的出栈序列; (2)在一个凸多边形中,通过作出若干条互不相交的对角线,把这个多边形划分成若干个三角形,询问不同划分的方案数; (3)给定N个节点,询问能构成多少种不同的二叉搜索树。 */