最近看到一篇文章讲三门问题。
三门问题简单叙述如下:
假设你正在参加一个游戏节目,你被要求在三扇门中选择一扇:其中一扇后面有一辆车;其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后知道门后面有什么的主持人,开启了另一扇后面有山羊的门,假设是三号门。他然后问你:“你想选择二号门吗?”
文章结论说的是如果选择换的话成功概率为2/3,如果选择不换的话成功概率为1/3。
觉得作者就是一傻子在瞎扯,换不换应该是一样的,于是就写了个小程序模拟了一下。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SHEEP 0
#define CAR 1
#define DOOR_COUNT 3
#define RAND_DOOR_INDEX rand()%DOOR_COUNT
int main()
{
int total_count = 0, win_count = 0;
srand((unsigned int)time(0));
printf("please input test times\n");
scanf("%d", &total_count);
getchar();
printf("do you want to change?, intput 'y' to change, other not\n");
char c;
c = getchar();
printf("simulation start, door count:%d, test times:%d, startegy : %s \n", DOOR_COUNT, total_count, c=='y' ? "change" : "not change");
for(int i = 0; i < total_count; ++i)
{
int car_door_index = RAND_DOOR_INDEX;//随机模拟背后有车的门
int guest_first_selected_index = RAND_DOOR_INDEX;//第一次嘉宾选择的门
int host_selected_index = RAND_DOOR_INDEX;
while(host_selected_index == guest_first_selected_index || host_selected_index == car_door_index) //主持人选择的门,和嘉宾选择的门不能相等,不能选择有车的门,不符合条件就重新选
host_selected_index = RAND_DOOR_INDEX;
if(c == 'y')
{
int guest_second_selected_index = RAND_DOOR_INDEX;
while(guest_second_selected_index == host_selected_index || guest_second_selected_index == guest_first_selected_index) //嘉宾选择的门,和第一次选择的门不能相等,不能和主持人的选择相等,不符合条件就重新选
guest_second_selected_index = RAND_DOOR_INDEX;
if(guest_second_selected_index == car_door_index)
win_count += 1;
//printf("first select : %d, host_select : %d, second select : %d, car index : %d\n", guest_first_selected_index, host_selected_index , guest_second_selected_index, car_door_index);
}
else
{
if(guest_first_selected_index == car_door_index)
win_count += 1;
}
}
printf("simulation finish, win times:%d \n", win_count);
return(0);
}
执行结果:
可以看到模拟10000次,选择换的成功次数大约是666**次,的确是2/3左右。
好吧,作者说的没错,我承认自己是个傻子。
代码也考虑到了多门,例如如果想要尝试5个门,将DOOR_COUNT定义为5即可。
五个门的模拟结果如下:
15个门的模拟结果如下:
45个门的模拟结果如下:
可以看到如果门越多,选择“换”与“不换”赢的概率差距越来越小。但是选择“换”的成功率的确比“不换”要高。
果然,还是不能够单靠直觉来预测概率,太不靠谱了。