1133-Buy the Ticket
2013-09-11 23:09
232 查看
关于卡特兰数,网上多有博客,讲得也略感详细,可我为人较钻,也写写我的心得和体会,我历时三天,方才写出此题,首先从了解递推,了解了些dp,最后努力理解各公式的推导,最后根据栈出,栈入思考出了这道题。这类问题,没有比百度百科等更详细和专业的了,正因为它专业,倒是让我吃了一番苦头,在这里,我仍然借用百度百科来分析。希望大家耐心的看下去。
说道递推,其实我们高中就学习过,这里我以最简单的递推来让大家知道递推是什么,小明上有十个台阶的楼梯,一次能上一个台阶或二个台阶,问,小明上十阶台阶有几种上法,这是典型的fibonacci数列,fibonacci公式是f(n) = f(n-1) + f(n-2)。假设小明已经上到第十阶台阶了,那么他可能是由第八阶或第九阶来的,同理,第九阶时,有可能是由第八阶和第七阶上来的,逐一递推下去,就能得出结果,而动态规划在于记录状态(关于dp,我了解也不深),这里的每一阶台阶便是一个状态,此状态下记录有几种上楼梯的方法,根据加法原理,上楼总数为各步骤的总和,故有f(n)
= f(n-1) + f(n-2),n为第n阶楼梯,f(n)指有几种算法。
(百度百科)出栈次数:一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?[4-5]
常规分析
首先,我们设f(n)=序列个数为n的出栈序列种数。同时,我们假定,从开始到栈第一次出到空为止,这段过程中第一个出栈的序数是k。特别地,如果栈直到整个过程结束时才空,则k=n
首次出空之前第一个出栈的序数k将1~n的序列分成两个序列,其中一个是1~k-1,序列个数为k-1,另外一个是k+1~n,序列个数是n-k。
此时,我们若把k视为确定一个序数,那么根据乘法原理,f(n)的问题就等价于——序列个数为k-1的出栈序列种数乘以序列个数为n - k的出栈序列种数,即选择k这个序数的f(n)=f(k-1)×f(n-k)。而k可以选1到n,所以再根据加法原理,将k取不同值的序列种数相加,得到的总序列种数为:f(n)=f(0)f(n-1)+f(1)f(n-2)+……+f(n-1)f(0)。
看到此处,再看看卡特兰数的递推式,答案不言而喻,即为f(n)=h(n)= C(2n,n)/(n+1)= c(2n,n)-c(2n,n+1)(n=0,1,2,……)。
最后,令f(0)=1,f(1)=1。
下面是解买票问题的关键
非常规分析
对于每一个数来说,必须进栈一次、出栈一次。我们把进栈设为状态‘1’,出栈设为状态‘0’。n个数的所有状态对应n个1和n个0组成的2n位二进制数。由于等待入栈的操作数按照1‥n的顺序排列(买票中没特定顺序哦)、入栈的操作数b大于等于出栈的操作数a(a≤b),因此输出序列的总数目=由左而右扫描由n个1和n个0组成的2n位二进制数,1的累计数不小于0的累计数的方案种数。
在2n位二进制数中填入n个1的方案数为c(2n,n),不填1的其余n位自动填0。从中减去不符合要求(由左而右扫描,0的累计数大于1的累计数)的方案数即为所求。
不符合要求的数的特征是由左而右扫描时,必然在某一奇数位2m+1位上首先出现m+1个0的累计数和m个1的累计数,此后的2(n-m)-1位上有n-m个 1和n-m-1个0。如若把后面这2(n-m)-1位上的0和1互换,使之成为n-m个0和n-m-1个1,结果得1个由n+1个0和n-1个1组成的2n位数,即一个不合要求的数对应于一个由n+1个0和n-1个1组成的排列。
反过来,任何一个由n+1个0和n-1个1组成的2n位二进制数,由于0的个数多2个,2n为偶数,故必在某一个奇数位上出现0的累计数超过1的累计数。同样在后面部分0和1互换,使之成为由n个0和n个1组成的2n位数,即n+1个0和n-1个1组成的2n位数必对应一个不符合要求的数。
因而不合要求的2n位数与n+1个0,n-1个1组成的排列一一对应。
显然,不符合要求的方案数为c(2n,n+1)。由此得出输出序列的总数目=c(2n,n)-c(2n,n+1)=c(2n,n)/(n+1)=h(n+1)。
如果你耐不下性子看上述言语,那你就放弃治疗吧,如果你看懂了上述,那么稍微提醒,你便能解决问题了,因为推导方法完全一样!!!
类似问题 买票找零
有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)
提醒:当m < n时,输出为0.
#include<stdio.h> #include<string.h> int shu[500]; int big_mul(int b,int a[500],int size) { int jw = 0,t,i; for(i = 0; i < size; i++) { t = a[i] * b + jw; a[i] = t % 10; jw = t / 10; } while(jw) { a[i++] = jw % 10; jw /= 10; size ++; } return size; } int main() { int m,n,text = 0; while(scanf("%d%d",&m,&n)!= EOF && (m || n)) { int size = 1; memset(shu,0,sizeof(shu)); if(m < n) { printf("Test #%d:\n",++text); printf("0"); } else { if(!n) { shu[0] = 1; for(int i = 2; i <= m; i++) size = big_mul(i,shu,size); } else { shu[0] = 1; for(int i = 2; i <= m + n;i ++) { if(i == (m+1)) size = big_mul(m-n+1,shu,size); else size = big_mul(i,shu,size); } } printf("Test #%d:\n",++text); for(int i = size - 1;i >= 0;i--) printf("%d",shu[i]); } printf("\n"); } return 0; }
相关文章推荐
- HDU 1133 Buy the ticket catalan 数
- hdu 1133 Buy the Ticket(卡特兰数+大整数)
- HDOJ/HDU 1133 Buy the Ticket(数论~卡特兰数~大数~)
- HDU-1133 Buy the Ticket (Catalan数)
- ACM--哈利波特电影票--HDOJ 1133--Buy the Ticket--递推
- HDOJ 1133 Buy the Ticket 简单解题报告
- 杭电ACM1133——Buy the Ticket
- 【HDU 1133】 Buy the Ticket (卡特兰数)
- HDU 1267 下沙的沙子有几粒? + HDU 1133 Buy the Ticket 递推 *
- hdu 1133 Buy the Ticket(卡特兰数 + 高精度)
- HDOJ 1133 Buy the Ticket
- HDU 1133 Buy the Ticket
- hdoj 1133 Buy the Ticket 【卡特兰】
- hdu 1133 Buy the Ticket 卡特兰数+递推+java
- 【高精度练习+卡特兰数】【Uva1133】Buy the Ticket
- hdu 1133 Buy the Ticket
- HDU 1133 Buy the Ticket(DP)
- hdu 1133 Buy the Ticket 卡特兰数+递推+java
- 【高精度练习+卡特兰数】【Uva1133】Buy the Ticket
- HDOJ_ 1133 Buy the Ticket