最近迷上一些有趣的数学问题了~~~请往下看~~~~

傻子坐飞机的问题:100个人排队乘坐有100个座位的飞机,正常情况时每个都都会对号入坐,但是,第一个上飞机的是个傻子,他随机坐了一个位子,接下来的人上飞机时,如果自己座位被人坐了就会随机找个座位坐下,否则就坐自己坐位。问题:最后一个上飞机的人坐到自己座位的概率是多少?

解题思路:

      其实这道题目可以归类到递归中,说到这里,可能好多人不太理解,怎么和递归扯上关系了。递归思路的关键就是一句话"傻子是可以传递的",只要能想明白这句话,题目就迎刃而解。设n个傻子坐飞机的概率是F(n),那么题目的解就是求F(100)的值。

      首先假设有题目中的不是100个人,而是n个人,第一个上飞机的是个傻子,他坐到自己座位上的概率是1/n,这是剩下的n-1个都是正常人,他们的座位都没有被占,所以他们100%会全部坐到自己的座位,即在这种情况下最后一个坐到自己座位的概率是1/n.

      另外一种情况是这个傻子坐到了最后一个人的位置,那么剩下的人无论怎么坐最后一个人都不会坐到自己的位置,这种情况的概率是0;

      第三种情况是傻子坐到了其余n-2个人的座位上,例如他坐到了第m个人的位置(1 < m < 100,概率都是1/n),那么2---m-1号的人都会坐到自己的位置上,因为自己的位置没有人坐。而第m个人由于自己的座位被第一个傻子坐了,所以他要随即坐,这是我们可以他第m个人看做是一个傻子,因为这种情况下他的表现和傻子是一样的,因此这种情况下的概率是1/n*F(n-m+1),即把剩下的n-m+1个人看做是一个n-m+1个人规模的傻子坐飞机的问题。

      综上三种情况:这个问题的解就是 F(n)=1/n+0+(F(n-1)+F(n-2)+...+F(2))/n;

看到上述的递推公式出来了,那么题目也就可以解决了。可是等等,我们要求的结果是F(100),而F(100)=1/100+

(F(99)+F(98)+...+F(2))/100,如果按照这个递归公式展开,而F(99)=1/99+(F(98)+F(97)+...+F(2)/99,而且F(98),F(97)每个展开都会产生很多个函数调用,这样的话你的内存马上就有可能耗空。那么如何解决这个问题呢,难道眼睁睁的看着到手的鸭子就让它飞了。当然不行了。

      如果你对算法理解稍微深点,主要是循环,也许你马上就能提出一个解决的方法。对了,就是从F(2)开始计算,依次计算F(2),F(3)。。。F(100),每次把求得的结果存到一个数组里,那么比如知道了F(2)到F(9)的值,他们依次存在一个数组f[2],f[3]...,f[9],那么在求F(10)= 1/10+(F(9)+F(8)+...+F(2))/10的时候就不用依次递归来调用求F(9),F(8)的值了,只要依次查找数组f[2],f[3]....f[9]的值代替就好了。

      相信看到上面一步好多人已经感觉很不错了,至少内存的问题解决了,那么能不能进一步化简呢?当然能了,只要仔细观察下表达式就能发现问题所在了,每次求F(n)其实最麻烦的就是求后面括号里几项和,刚才我们用数组存储结果来表达上述的值简化了循环调用的麻烦,可是我们发现后几项的和总是从F(2)加起,一直加到F(n-1),所以我们不用每次都计算f[2]+f[3]+...+f[n-1],主要用一个变量例如temp来保存当前的f[2]+f[3]+...f[n-1]即可,那么在计算F(n+1)的时候,我们只要在temp的基础上加上f(n)的值就可以得到f[2]+f[3]+...+f[n]即可。    

      题目到此为止了吗?也许你说只要写个小的程序就可以很快知道结果了,可是我可以直接和你说出答案来,不用运行程序,你随便给我一个大一些的,比如1000个人坐飞机,我也可以马上告诉你答案,呵呵。你知道为什么吗?也许有的人已经猜出来了,不是我比较牛,而是答案比较特殊。答案就是1/2!

      为什么呢?学过数学归纳法吗?对了,就是用数学归纳法,对于很多的问题,如果我们已经能推出问题的表达式,但是无法证明的时候,我们很多时候用的都是数学归纳法。    

证明过程:

      1.n=2时,傻子坐到自己位置的概率是1/2,剩下一个人坐到自己的位置,概率1/2.傻子坐到第二个人的位置的时候,最后一个人总不能坐到自己的座位,概率0.因此F(2)=1/2;

      2.假设F(2)=F(3)=。。。=F(n-1)=1/2,那么F(n)=1/n+(F(n-1)+F(n-2)+...+F(2))/n.由于F(2)=F(3)=。。。=F(n-1)=1/2,所以F(n)=1/n+(1/2+1/2+...+1/2)/n;(注:括号中共有n-2个1/2),因此可以得到F(n)=1/n+(1/2*(n-2))/n=1/2;

      3.所以F(n)=1/2 (当n >= 2时)成立

      证明结束! 

题目总结:

     1.回顾下该题目,首先把这道题能够分解成很多小的问题,找到递归的思路。

     2.然后涉及到了一个将递归的程序转换成非递归的问题,这种思路我们平时解题的时候也经常根据具体条件来使用。

     3.剩下对于题目的简化就完全是观察的结果,根据题目的特殊表达式进行优化,这个是很有必要的。有的时候,好的

        优化可以大大减少计算的复杂度,提高算法的效率。

     4.最后数学归纳法也是以前证明问题常用的解法。 

      所以,好多很复杂的问题都有非常简单美观的输出,这正是算法的魅力!

感谢原作者这么清晰地把解题思路写出来,附原文地址:http://celebration.javaeye.com/blog/212517

其实这个题目是一个典型的概率题,可以从反方向来考虑,即求第N个人无法坐下来的几率~~~

另外附问题的源码:http://blog.csdn.net/alex197963/archive/2007/05/11/1604459.aspx

 

posted on 2008-10-12 19:43  魔之左眼  阅读(900)  评论(0编辑  收藏  举报