Java经典“羊车门”概率问题解答

简介: Java经典“羊车门”概率问题解答

经典“羊车门”概率问题解答

羊车门问题出自美国《parade》杂志中一个叫作“ask marilyn”的专栏,问题表述如下:

台上有三个门,参赛者需要在三扇门中选择一扇门打开。其中一扇的后面是一辆汽车,选中后面有车的那扇门就可以赢得该汽车,而另外两扇门后面则各藏有一只山羊。当参赛者选定了一扇门,但未去开启它的时候,主持人会开启剩下两扇门中的一扇,露出其中一只山羊主持人提前知道哪扇门后是山羊,且一定打开后面是山羊的门。这时,他给参赛者可以重选机会,也就是可以换选剩下的另一门。

那么,关于换不换问题有人认为应该换,有人认为不应该换,有人认为换不换都一样。此问题在当时引起了很大的争议,时至今日也存在着许多不同的看法。

CarAndSheetAnddoor.png

个人认为应该选择换,选择换门最终能赢得汽车的概率更大一些。

三扇门,两羊一车,从表面上看,在得知第三扇门(假设主持人打开的是第三扇门)后是羊的情况下,1号门与2号门后,有一扇门后是车,一扇门后是羊,选择1号门或2号门,无论换与不换,赢得汽车的可能性是相同的,因为每扇门后面非羊即车,实则不然。

在打开第三扇门是羊的前提下,剩下的两扇门中一羊一车,如果参赛者在第一轮中选择的是后面是羊的门,那么换门后它会看到汽车,如果参赛者在第一轮中选择的是后面是汽车的门,那么换门后它会看到羊。

从概率角度分析,在不换门情况下,赢得汽车的情况是参赛者在第一轮就选到后面是汽车的门,第一轮选到汽车是三选一,概率为1/3。在换门的情况下,赢得汽车的情况是参赛者在第一轮选到的是后面是羊的门,这样才能在第二轮中换门来选到后面是汽车的门,第一轮选到羊是三选二,概率为2/3。

如果是三扇门两羊一车理解起来比较困难的话,可以更改游戏规则,反复体会其中道理。现有100扇门,其中99扇门后面是羊,1扇门后面是汽车。参赛者在第一轮选择完毕后,主持人会打开98扇后面是羊的门,剩下两扇门,问参赛者要不要更换选择。

参赛者肯定希望最终能够打开后面是汽车的门,如果选择不换门,那么意味着参赛者认定自己第一轮选的这扇门后面是汽车,第一轮有100扇门可以选择,因此他在第一轮选到汽车的概率是1/100。如果选择换门,那么意味着参赛者第一轮选的这扇门后面只要是羊就可以,这样才能在换门后选到汽车,而他在第一轮选到羊的概率是99/100。因此换门能赢得汽车的概率更大。

更改规则后的游戏,其中的原理与原问题一致,只不过增大了换门与不换门赢得汽车之间概率的差值,个人觉得更容易理解问题。

参考代码如下:

publicstaticvoidmain(String[] args) {
String[] door=newString[100]; // 新建一个数组,其中每个元素代表1扇门// 初始化100扇门后是羊for (inti=0; i<door.length; i++) {
door[i] ="羊";
    }
Randomr=newRandom();
intnumber=r.nextInt(100); // 生成一个0-99之间的随机数numberdoor[number] ="车"; // 给随机生成的第number个索引位置赋值为汽车,意为将汽车放到第(number + 1)扇门后面// 此时已完成99扇门后是羊,随机1扇门后是汽车// 接收用户数据,第一轮选择第几扇门Scannersc=newScanner(System.in);
System.out.println("请选择1-100中的第几道门:");
intchoose=sc.nextInt();
System.out.print("第");
intline=0; // 定义变量line,展示数据时换行用if (door[choose-1] =="车") { // 如果第一次选择的门后面是车,则在剩下99扇后面是羊的门中输出随机的98扇intrandom=r.nextInt(100); // 随机生成不输出的1扇门// 若随机生成的门恰好是第一次选择的门,则重新生成while (random==choose-1) {
random=r.nextInt(100);
        }
// 在剩下99扇后面是羊的门中输出随机的98扇for (inti=0; i<door.length; i++) {
// 如果是刚刚随机生成的1扇门或后面是汽车的门,则跳过,不输出if (i==random|i== (choose-1)) {
continue;
            }
System.out.println((i+1) +"、");
// 每40条数据换行if (line%40==0) {
System.out.println();
            }
        }
    } else { // 如果第一次选择的门后面是羊,则输出剩下的后面是羊的98扇门// 打开98扇后面是羊的门,剩下2扇门未打开(参赛者第一轮选择的门和后面是汽车的门)for (inti=0; i<door.length; i++) {
StringsheetDoor=door[i]; // 遍历每扇门,查看门后是什么// 输出除第一轮选择的门之外的后面是羊的98扇门if (sheetDoor=="羊"& (i+1) !=choose) {
System.out.print((i+1) +"、");
line++;
            }
// 每40条数据换行if (line%40==0) {
System.out.println();
            }
        }
    }
System.out.println("道门后面是羊");
System.out.println("请选择要不要换门,1换,2不换");
// 接收用户数据,第二轮的选择intchoose2=sc.nextInt();
// 若选择不换,则输出该扇门后的东西,并给出相应提示if (choose2==2) {
System.out.println("你选择不换,第"+choose+"道门后是"+door[(choose-1)]);
if (door[(choose-1)] =="车") {
System.out.println("恭喜你,选中了车");
        } else {
System.out.println("很遗憾,你选中了羊");
        }
    } else { // 否则说明换,输出该扇门后的东西,并给出相应提示System.out.println("你选择换,第"+choose+"道门后是"+door[(choose-1)]);
if (door[(choose-1)] =="羊") {
System.out.println("恭喜你,选中了车");
        } else {
System.out.println("很遗憾,你选中了羊");
        }
    }
// 输出第几扇门后面是车,验证结果正确性for (inti=0; i<door.length; i++) {
// 如果第i+1扇门后是车,则输出结果并结束循环,否则继续遍历if (door[i] =="车") {
System.out.println("第"+ (i+1) +"道门后是车");
break;
        }
    }
}


选择不换门,基本上不会赢得汽车(1/100)。

注:并不是说换门的情况下,一定能赢得汽车,只是讲在不知道其他条件的情况下,换门的情况有较大几率赢得汽车。

参考资料

[1] Antineutrino 蒙提霍尔悖论(三门问题)终极分析 [J/OL] https://www.cnblogs.com/antineutrino/p/4821580.html

[2] 田晨景 胡雄等.再谈“羊车门”问题 [J] .教育教学论坛, 2016,(42)

相关文章
|
5天前
|
存储 监控 前端开发
Java实现根据概率中奖率怎么算
【4月更文挑战第24天】本文介绍了如何使用Java实现基于概率的中奖率计算,涵盖权重分配法和轮盘法。通过实例代码展示了使用Java的权重分配法进行计算,并讨论了常见问题和解决办法,如概率设置错误、浮点数比较误差和随机数生成。此外,还探讨了性能优化、动态调整概率、支持多种抽奖模式以及确保公平性与监管合规的方法。最后,提到了构建一个完整的抽奖系统涉及的奖品管理、抽奖服务、用户接口、日志记录与审计等核心组件。
34 0
Java实现根据概率中奖率怎么算
|
5天前
|
机器学习/深度学习 算法 Java
Java代码统计列表元素的概率
Java代码统计列表元素的概率
22 0
|
9月前
java202303java学习笔记第三十三天带有概率的随机点名2
java202303java学习笔记第三十三天带有概率的随机点名2
29 0
|
12月前
java202303java学习笔记第三十三天带有概率的随机点名
java202303java学习笔记第三十三天带有概率的随机点名
32 0
|
12月前
java202303java学习笔记第三十三天带有概率的随机点名3
java202303java学习笔记第三十三天带有概率的随机点名3
34 0
|
12月前
java202303java学习笔记第三十三天带有概率的随机点名4
java202303java学习笔记第三十三天带有概率的随机点名4
31 0
|
算法 Java 索引
|
3天前
|
Java 测试技术
Java多线程的一些基本例子
【5月更文挑战第17天】Java多线程允许并发执行任务。示例1展示创建并启动两个`MyThread`对象,各自独立打印&quot;Hello World&quot;。示例2的`CounterExample`中,两个线程(IncrementThread和DecrementThread)同步地增加和减少共享计数器,确保最终计数为零。这些例子展示了Java线程的基本用法,包括线程同步,还有如Executor框架和线程池等更复杂的用例。
10 0
|
1天前
|
Java
Java一分钟之-并发编程:线程间通信(Phaser, CyclicBarrier, Semaphore)
【5月更文挑战第19天】Java并发编程中,Phaser、CyclicBarrier和Semaphore是三种强大的同步工具。Phaser用于阶段性任务协调,支持动态注册;CyclicBarrier允许线程同步执行,适合循环任务;Semaphore控制资源访问线程数,常用于限流和资源池管理。了解其使用场景、常见问题及避免策略,结合代码示例,能有效提升并发程序效率。注意异常处理和资源管理,以防止并发问题。
22 2
http://www.vxiaotou.com