编程之美 4.3买票找零

问题:在一场球赛开始前,售票工作进行着,每张球票为50元。现在有2n个人排队购票,其中有n人手持50元,另外n人手持100元,假设开始售票是售票处没有零钱,问这2n个人有多少种排列方式,不至于售票出出现没钱找的情况?

解法一:

只要保证从队首开始往后数,任何时候,手持100的都比手持50的少,就肯定有钱找。

这里可以看出此问题类似括号匹配问题,用一个栈遍历排列看栈最后是否为空来检验排列是否合法。

设f(x)为求合法序列之个数的函数

若第一个左括号(位置为0)与第k(k=2i+1)个符号匹配,那么剩余括号的合法序列为:f(2i)*f(2n-2i-2)

clip_image002

f(0) = 1,可以用递归的方式求解,不过可以进一步推导出通项公式:

clip_image002[5]又称为Catalan数。

解法二:

设n-1个1和n+1个0组成的序列称为Sigma序列,这样的序列共有C(2n,n-1)个。

总序列数为C(2n,n),即合法序列和非法序列的总和。

假设存在某个(些)k,使前k项1的个数比0少一个,那么后面2n-k项中的1就比0出一个。

将后面2n-k项的数01互换,那么整个序列就变成一个n-1个1和n+1个0的序列(即Sigma序列)

|--1:4 0:5--||--1:10 0:9--|  =>01互换 |--1:4 0:5--||--1:9 0:10--|  (这是我例举的一个例子,冒号后为相应的个数)

10的总个数变化为:1:14 0:14 =>1:13 0:15

这样就将非法序列对应到唯一一个Sigma序列。

下面的问题是Sigma序列能否唯一对应一个非法序列?

假设存在某个(些)k,使前k项1的个数比0少一个,那么后面2n-k项中的1就比0出一个。(注意这里是少)

|--1:4 0:5--||--1:9 0:10--| =>01互换 |--1:4 0:5--||--1:10 0:9—|

10的总个数变化为:1:13 0:15 =>1:14 0:14

这样就将一个Sigma序列对应到唯一一个非法序列。

从而得出非法序列与Sigma序列一一对应,即非法序列的个数=Sigma序列的个数。

合法序列个数=C(2n,n)-C(2n,n-1)=C(2n,n)/(n+1)

下面说明一下容易误解的几个地方:

①Sigma序列是通过局部01互换转化成非法序列的,而不是非法序列==Sigma序列。它们之间只是对应关系不是相等的关系。

②Sigma序列只是假设由n-1个1和n+1个0组成的序列,至于叫什么序列自己喜欢。

总结:

此题是Catalan数典型的应用,类似的应用还有下面这些:

1.在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?

2.一位大城市的律师在她住所以北n个街区和以东n个街区处工作。每天她走2n个街区去上班。如果他

从不穿越(但可以碰到)从家到办公室的对角线,那么有多少条可能的道路?

3.一个栈(足够大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?

4.用n个长方形填充一个高度为n的阶梯状的方法个数?

Catalan number 4x4 grid example.svg

Catalan stairsteps 4.svg

posted @ 2013-10-08 18:55  Linka  阅读(480)  评论(0编辑  收藏  举报