锁定老帖子 主题:以傻子坐飞机问题论新手如何解算法题
精华帖 (0) :: 良好帖 (0) :: 灌水帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-07-15
对模拟现实事件的代码,很多新手会觉得茫然,其实只要把大问题拆成小问题,一切就ok了。 PS:边编码,边思考,前后不超过5分钟。嘻嘻。 不废话,看题: 100个人排队乘坐有100个座位的飞机,正常情况时每个都都会对号入坐,但是,第一个上飞机的是个傻子,他随机坐了一个位子,接下来的人上飞机时,如果自己座位被人坐了就会随机找个座位坐下,否则就坐自己坐位。问题:最后一个上飞机的人坐到自己座位的概率是多少?? 第一步:建一个项目,一个类,废话。 第二步:有几个东西需要表示 a, 100个位子。把他编号为0~99。常量 b, 100个人。把他们编号为0~99。常量 b, 哪个人坐哪个位子。人和位子的编号一一对应。常量 c, 位子上有没有坐人。在程序中定义一个 boolean sited[]=new boolean[100];变量 第三步:有几个动作要表示 a, 坐到某个位子上,写个方法,sit(int sitNum); b, 随便坐个位子,写个方法,randSit(), c, 尝试坐到某个位子上,被坐了就随便坐个位子,写个方法,trySit(int num); PS:我是先写上方法的定义,后面才写代码的,要首先从宏观的角度思考问题,然后再深入细节。 第四步:求解 a, 模拟100个人上飞机的过程,并返回最后一个人是不是坐到他自己的位子 b,计算1000000次,计算成功次数。 把每个方法实现,代码就完成了。把大问题拆解成小问题,问题就可以迎刃而解。就象画画,新手总是直接画鼻子画眼,会画的都是,先勾勒个轮廓。看到很多新手遇到复杂问题会很茫然,希望我的话能对他们有所帮助。 代码: import java.util.Random; /** * 2007-7-15 下午05:36:02 */ /** * @author <a href="mailto:guileen@gmail.com">桂健雄</a> * @since 2007-7-15 */ public class FoolSit { boolean[] sited=new boolean[100]; int emptySitCount = 100; void trySit(int sitNum){ if(sited[sitNum]){ ranSit(); } else{ sit(sitNum); } } /** * * @param sitNum */ void sit(int sitNum){ sited[sitNum]=true;//坐下来 emptySitCount -- ; } /** * 随便坐个位子 * */ void ranSit(){ int x=rand.nextInt(emptySitCount); int c = -1; for(int i=0;i<100;i++){ if(!sited[i]){ c++; if(c==x){ sit(i); break; } } } } /** * * @return 第一百个人是否做到了自己的位子 */ boolean testSit(){ //初始化 for(int i=0;i<100;i++){ sited[i] = false; } emptySitCount = 100; //傻子,随便坐个位置 ranSit(); for(int i=1;i<99;i++){ trySit(i); } return sited[99]; } public static void main(String[] args) { FoolSit f = new FoolSit(); int success = 0; for(int i=0;i<1000000;i++){ if(f.testSit()) success++; } double rate = (double)success/1000000; System.out.println("run:10000 times,success:"+success+" rate:"+rate); } Random rand= new Random(); } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-07-15
这个问题的数学解和概率论有多大关系?我给个数学解吧。
假设从1号开始到100号依次上飞机。1号是傻子,如果1号直接做到1号位置,那么,最后一人肯定能坐自己的座位,如果1号坐在100号,那么最后一个人一定上不了自己的座位。如果1号选中m号,那么到m-1前的人都会坐在自己位置上,如果到底m个人上来的时候,他又面临一次选择。如果到他坐0到1号,ok,后面按顺序,如果他坐到100号,没戏,如果他做到m+n号,那么到m+n-1的人都按顺序的。 好,我们反过来想,最后一个坐不到自己位子的概率是多少呢?他坐不到一定是因为前面某个人坐不到自己的位子导致被人坐了他的位子。我们设fx(m)为第m个人坐不到自己的位子的概率。 从fx(2)开始考虑:fx(2)=0.01。那么fx(3)=0.01+fx(2)*1/99 //被第一人坐了自己的位子+被第二个人坐了 fx(4)=0.01+fx(2)*1/99+fx(3)*1/98; //被第一个+第二个+第三个人坐了。 fx(5)=0.01+fx(2)*1/99+fx(3)*1/98+fx(4)*1/97; 朋友看到这里,应该看出递推关系了吧。fx(2)=0.01,fx(3)=(1+1/99)*fx(2) 也就是说fx(m)=(1+1/(102-m))*fx(m-1)//数学归纳法证明就免了吧。太无聊了。谁有空给证一下好了。 fx(4)=(1+1/98)*fx(3)=(1+1/98)(1+1/99)(1/100) 同理fx(100)=(1+1/2)(1+1/3)(1+1/4)....(1+1/99)(1/100)=3/2*4/3*5/4*....*100/99*1/100 同志们,看到这个式子,是不是很兴奋? 发现fx(100)=0.5,那么我们求什么呢?最后一个坐到自己的位子上。很简单就是1-fx(100)=0.5 |
|
返回顶楼 | |
发表时间:2007-07-15
rocks 写道 如果1号坐在100号,那么最后一个人一定上不了飞机。
这句以后的分析,就不必再看了。 |
|
返回顶楼 | |
发表时间:2007-07-15
庄表伟 写道 rocks 写道 如果1号坐在100号,那么最后一个人一定上不了飞机。
这句以后的分析,就不必再看了。 口误+笔误。。。。。 |
|
返回顶楼 | |
发表时间:2007-07-15
晕,还分析了半天,
只有一个结果,坐到自己座位和没有坐到, 几率对半开! |
|
返回顶楼 | |
发表时间:2007-07-16
yimlin 写道 晕,还分析了半天,
应该这么分析只有一个结果,坐到自己座位和没有坐到, 几率对半开! 1.傻子坐对了 1% 2.傻子坐错了 99% 傻子侍错了: 1.第两人坐了100号 1/99 2.第两人坐了非100号 98/99 第二个人坐了100号 1.第三个人坐了100 1/98 2.第三个人坐了傻子的位置 1/98 3.第三个人坐了其它位置 97/98 。。。。。。。。。。。。 第一百人上了飞机 只可能有两个位置 一个是傻子的位置 另一个是100号的位置 |
|
返回顶楼 | |
发表时间:2007-07-19
我想应该可以这样:
var n0 = 99% * (1/100-1) //傻子直接占上自己的坐位的概率 var n1= n0 //第一个正常人坐位被占的概率 var n2= n0+n1*(1/100-2) var n3= n0+n1*(1/100-2)+n2*(1/100-3) ... var n99=n0+n1*(1/100-2)+n2*(1/100-3)+..... |
|
返回顶楼 | |
发表时间:2007-07-19
var MAX = 99 var rates = [(MAX/(MAX+1)) * (1/MAX)]; for(var i=1;i<=MAX;i++){ var x = rates[0]; for(var j = 1;j<i;j++){ x+=rates[j]*(1/(MAX-j)) } rates[i] = x; } document.write(rates.join('\n')) 不过,结果和jasongreen的差别太大,不知道错在那里。 ..... 0.2475 0.32999999999999996 0.49499999999999994 0.9899999999999999 第99个人的概率倒是挺相近的。 晚上再查查,问题到底出在那里:) |
|
返回顶楼 | |
发表时间:2007-07-19
99%
哪出来的? |
|
返回顶楼 | |
发表时间:2007-07-19
傻子坐到别人的坐位的概率是
(99/100) 坐上某个指定的位置是(99/100)*(1/99)『不就是1/100吗?当时怎么就每转过弯来,倒霉』 |
|
返回顶楼 | |