编程之美之4.1金刚坐飞机

来源:互联网 发布:杀破狼 js 原版 编辑:程序博客网 时间:2024/04/28 12:06

问题:

现在有一班飞机将要起飞,乘客们正准备按机票号码(1, 2, 3, …N)依次排队登机。突然来了一只大猩猩(对,他叫金刚)。他也有飞机票,但是他插队第一个登上了飞机,然后随意地选了一个座位坐下了。根据社会的和谐程度,其他的乘客有两种反应:

1.乘客们都义愤填膺,“既然金刚同志不遵守规定,为什么我要遵守?”他们也随意地找位置坐下,并且坚决不让座给其他乘客。

2.乘客们虽然感到愤怒,但还是以“和谐”为重,如果自己的位置没有被占领,就赶紧坐下,如果自己的位置已经被别人(或者金刚同志)占了,就随机地选择另一个位置坐下,并开始闭目养神,不再挪动。

在这两种情况下,第 i 个乘客(除去金刚同志之外)坐到自己原机票位置的概率分别是多少?

 

问题1:

      这个问题其实可以看作是一个抽签问题,金刚第一个抽签,其他乘客按机票号轮流抽签,抽到“位置i”的那个乘客中奖。显然,每一个乘客中奖概率与其抽签的顺序是无关,这是一个很经典的问题,所以大家抽到“位置i”的概率都是1/N,包括第i个乘客。书上的解答从概率计算的角度同样得到了这个结果。

问题2:

      对于这个问题,书上的解答似乎是存在错误的,我看的《编程之美》是2010年9月第10次印刷的版本。特别是对于书上“如果金刚坐在1号位置上,那么第i个乘客坐在自己位置上的概率是1”这句话特别不理解。其实书上的结果(N-i+1)/(N-i+2),很容易用一个反例来推翻。

      反例:

      令N=2, 即有两名乘客,1号是普通乘客,2号是金刚。那么1号乘客能坐到自己位置的概率取决于金刚是如何选的,显然金刚占领1号乘客位置的概率是1/2,而后1号乘客只能坐在金刚(2号)的位置上,所以概率是1/2。而按书上的结论,结果是(N-i+1)/(N-i+2)=2/3。所以书上结果不成立。


    目前在网上看到的其他解法基本也是有些问题的,这里引用两篇个人感觉已经比较好的博文:

1. http://hi.baidu.com/maxint/blog/item/8ac3c49707911f6354fb96e9.html

这篇博文对这个问题的求解比较偏数学,逻辑也比较严谨,其中对于递推公式的推导非常漂亮,对于原问题转换成规模更小的子问题的思想也很巧妙,非常值得学习。但是这个解法中还是存在漏洞,后面会详细的分析到,我们姑且先分析一下其结论。这篇博文的结论是“当座位总数为n时,第 i 个乘客坐到自己原位置的概率为(n-i)/(n-i+1)”。如果用我前面的反例来套这个公式,其结果是1/2,是符合正确结果的。但是,如果我们把反例中的普通乘客与金刚的座位号互换,即普通乘客是2号,金刚是1号。理论上这样修改之后2号乘客坐回自己位置的概率还是1/2,但是根据公式的计算结果是0。所以也是不正确的。

 

2. http://blog.csdn.net/FlyingIceCS/archive/2010/11/14/6007735.aspx

这篇博文以一个退化的命题作为起点开始讨论《编程之美》上的这个问题。同样的,博主也用到了一些数学技巧得到了退化命题的正确解法。对于《编程之美》上的这个问题,博主得到了“个人认为这里要分两种情况讨论,金刚的正确位置在i之前或者之后,如果金刚的正确位置在i之前,则书中的结论完全正确,要是之后的话。。。就是另外一个答案了。”这个结论。这一点和本人的想法完全相同,但是博主并没有深入推敲得到最终答案。

 

为了求解这个问题,我们首先来求解一个退化的命题:假设金刚的位置号大于i,其他条件均和题目中描述的一致,那么第i个乘客坐上自己位置的概率P(i)是多少?

对于这个退化的命题,我们定义f(n)为第n个乘客发现自己的位置被占领(可能是金刚,也可能是其他乘客)的条件下,第i个乘客坐上自己的位置的概率(1 <= n < i)

根据题意,我们知道如果金刚选择的位置大于i,那么第i个乘客肯定能过坐上自己的位置。那么根据条件概率计算有:

P(i)= [f(1) + f(2) + ...+ f(i-1)]/N + (N - i) / N

其中加号左边的部分表示金刚依次占领了1、2、...、i-1号位置条件下的概率加和,加号右边表示金刚占领了i号位置之后的概率加和。

为了求得P(i),我们首先需要对f(n)进行求解。

观察f(n)的定义,我们很容易得到以下的公式:

f(n) = [f(n+1) + f(n+2) + ... + f(i - 1)]/(N - n) + (N-i)/ (N-n)

以上公式的思路是这样的:第n个乘客发现自己的位置被占领了,那么他(她)会在剩余的N-n个位置中随机选择,可以证明这N-n个位置一定都是编号大于n的位置(下面有证明)。那么如果第n个乘客选择i之前的位置,则选择每一个位置的概率均为1//(N-n),因此构成了式中加号左边的部分;如果n乘客选择的是i之后的位置,那么后面的乘客将按号入座,i乘客必然能坐上自己的位置,所以构成了式中加号右边的部分。

求解f(n)的通项:

式中两边均乘以(N-n)得:

 (N-n)*f(n) = f(n+1) + f(n+2) + ... + f(i - 1) + (N-i)

取n=n+1,则有

 (N-n-1)*f(n+1) = f(n+2) + ... + f(i - 1) + (N-i)

两式合并有:

(N-n)*f(n) = (N - n)*f(n+1) => f(n)=f(n+1)

因此有:f(1)=f(2)=...=f(i-1)

从新代入f(n)的计算公式式中得到f(n)=(N-i)/(N-i+1)

观察P(i)和f(n)的计算公式,我们发现实际上P(i)=f(0)=(N-i)/(N-i+1)

根据以上的讨论,我们得到了对于该退化命题,第i个乘客坐上自己位置的概率为(N-i)/(N-i+1)。

 

接下来,我们要考虑如何将原命题转换成该退化命题。首先,我们分析一下原名题和退化命题之间的区别在于:退化命题对金刚的位置做了假设。用j表示金刚的位置,那么我们的退化命题得到了j>i时的结论,j不等于i,那么当j<i时情况会怎样?

想象一下乘客们抢位置是怎样的:首先金刚抢了一个位置,然后大家按编号开始逐一抢位置,1, 2,...,j,...,i,... 。这里我们发现一个特殊点,就是j乘客实际上就是金刚,而金刚一开始已经抢完位置了,所以不再参与抢位置。因此当轮到i乘客抢位置的时候,实际上只有i-2个人抢过位置(金刚不是人),而在退化命题中,这个数值是i-1。而金刚的位置,即编号为j的位置发挥着和编号大于i的位置相同的作用,即一旦有i之前的乘客抢了这个位置,那么后面的乘客将按号入座。

通过这个分析,我们初步得到一个结论,那就是当j<i时,P(i)的值等价于当j>i-1时,P(i-1)的值。也就是我们把金刚的位置挪到i后面去了,然后重新进行了编号。所以此时第i乘客坐上自己位置的概率为P(i-1)=(N-i+1)/(N-i+2)

这个结论实际上也可以仿照退化命题的求解过程通过数学方法得到,这里略去。

因此我们可以得到原命题的结论:

如果金刚的位置大于i,那么结果为(N-i)/(N-i+1);如果金刚的位置小于i,那么结果为(N-i+1)/(N-i+2)。

如果把金刚的位置也作为一个随机因素的话,那么最终结果应该是:

(N-i)*(N-i)/[N*(N-i+1)]+(ii-1)*(N-i+1)/[N*(N-i+2)]

 

我们分析一下以上所列出的第一篇博文漏洞在何处:

文中对金刚选择位置的第2种情况的讨论中提到“金刚若挑选的座位在第 i 个座位前,(即 i > j),则第j个乘客除非坐到金刚的座位,不然就会抢其他人的座位,因为他的行为和金刚相似,可以将他当做金刚处理。去除前 j 个座位,剩下的座位和乘客再按原大小排序重新从1开始编号,则先前的第 i 个乘客,其座位号变为 i-j,新的总座位数变为 n-j。所以得 P(i │ K=j) = F(i-j, n-j)。” 。 这里没有考虑到,如果金刚的位置是在j之前,那么到第j个乘客抢位置的时候,实际上只有j-1个座位已被抢走,所以剩下的作为数应该是n-j+1。而对剩下座位进行重排的话,金刚的位置该如何排序还有待考虑。正是这个原因导致了这里的结论其实只适用于金刚的座位在i之后的情况。

 

以下是对文中的一个论点进行证明:

论点:第n个乘客发现自己的位置被占领时了,剩余的N-n个位置定都是编号大于n的位置。

证明:用反证法,假设n之前的位置k是空着的。那么考虑第k个乘客在抢位置时的行为。由于k<n,那么k乘客必然是在n乘客之前抢位置的,而此时k位置必然也是空的,那么根据题意k乘客必然会选择k位置,所以到n乘客抢位置时,k位置必然不是空的。与假设矛盾,得证!

原创粉丝点击