经典“羊车门”概率问题解答
羊车门问题出自美国《parade》杂志中一个叫作“ask marilyn”的专栏,问题表述如下:
台上有三个门,参赛者需要在三扇门中选择一扇门打开。其中一扇的后面是一辆汽车,选中后面有车的那扇门就可以赢得该汽车,而另外两扇门后面则各藏有一只山羊。当参赛者选定了一扇门,但未去开启它的时候,主持人会开启剩下两扇门中的一扇,露出其中一只山羊(主持人提前知道哪扇门后是山羊,且一定打开后面是山羊的门)。这时,他给参赛者可以重选的机会,也就是可以换选剩下的另一扇门。
那么,关于换不换的问题,有人认为应该换,有人认为不应该换,也有人认为换不换都一样。此问题在当时引起了很大的争议,时至今日也存在着许多不同的看法。
我个人认为应该选择换,选择换门最终能赢得汽车的概率更大一些。
三扇门,两羊一车,从表面上看,在得知第三扇门(假设主持人打开的是第三扇门)后是羊的情况下,1号门与2号门后,有一扇门后是车,一扇门后是羊,选择1号门或2号门,无论换与不换,赢得汽车的可能性是相同的,因为每扇门后面非羊即车,实则不然。
在打开第三扇门是羊的前提下,剩下的两扇门中一羊一车,如果参赛者在第一轮中选择的是后面是羊的门,那么换门后它会看到汽车,如果参赛者在第一轮中选择的是后面是汽车的门,那么换门后它会看到羊。
从概率角度分析,在不换门情况下,赢得汽车的情况是参赛者在第一轮就选到后面是汽车的门,第一轮选到汽车是三选一,概率为1/3。在换门的情况下,赢得汽车的情况是参赛者在第一轮选到的是后面是羊的门,这样才能在第二轮中换门来选到后面是汽车的门,第一轮选到羊是三选二,概率为2/3。
如果是三扇门两羊一车理解起来比较困难的话,可以更改游戏规则,反复体会其中道理。现有100扇门,其中99扇门后面是羊,1扇门后面是汽车。参赛者在第一轮选择完毕后,主持人会打开98扇后面是羊的门,剩下两扇门,问参赛者要不要更换选择。
参赛者肯定希望最终能够打开后面是汽车的门,如果选择不换门,那么意味着参赛者认定自己第一轮选的这扇门后面是汽车,第一轮有100扇门可以选择,因此他在第一轮选到汽车的概率是1/100。如果选择换门,那么意味着参赛者第一轮选的这扇门后面只要是羊就可以,这样才能在换门后选到汽车,而他在第一轮选到羊的概率是99/100。因此换门能赢得汽车的概率更大。
更改规则后的游戏,其中的原理与原问题一致,只不过增大了换门与不换门赢得汽车之间概率的差值,个人觉得更容易理解问题。
参考代码如下:
public static void main(String[] args) {
String[] door = new String[100]; // 新建一个数组,其中每个元素代表1扇门
// 初始化100扇门后是羊
for (int i = 0; i < door.length; i++) {
door[i] = "羊";
}
Random r = new Random();
int number = r.nextInt(100); // 生成一个0-99之间的随机数number
door[number] = "车"; // 给随机生成的第number个索引位置赋值为汽车,意为将汽车放到第(number + 1)扇门后面
// 此时已完成99扇门后是羊,随机1扇门后是汽车
// 接收用户数据,第一轮选择第几扇门
Scanner sc = new Scanner(System.in);
System.out.println("请选择1-100中的第几道门:");
int choose = sc.nextInt();
System.out.print("第");
int line = 0; // 定义变量line,展示数据时换行用
if (door[choose - 1] == "车") { // 如果第一次选择的门后面是车,则在剩下99扇后面是羊的门中输出随机的98扇
int random = r.nextInt(100); // 随机生成不输出的1扇门
// 若随机生成的门恰好是第一次选择的门,则重新生成
while (random == choose - 1) {
random = r.nextInt(100);
}
// 在剩下99扇后面是羊的门中输出随机的98扇
for (int i = 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 (int i = 0; i < door.length; i++) {
String sheetDoor = 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不换");
// 接收用户数据,第二轮的选择
int choose2 = 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 (int i = 0; i < door.length; i++) {
// 如果第i+1扇门后是车,则输出结果并结束循环,否则继续遍历
if (door[i] == "车") {
System.out.println("第" + (i + 1) + "道门后是车");
break;
}
}
}
选择不换门,基本上不会赢得汽车(1/100)。
注:并不是说换门的情况下,一定能赢得汽车,只是讲在不知道其他条件的情况下,换门的情况有较大几率赢得汽车。
参考资料
[1] Antineutrino 蒙提霍尔悖论(三门问题)终极分析 [J/OL] 蒙提霍尔悖论(三门问题)终极分析 - Antineutrino - 博客园
[2] 田晨景 胡雄等.再谈“羊车门”问题 [J] .教育教学论坛, 2016,(42)



