owenzhang的博客

三门问题

字数统计: 802阅读时长: 3 min
2018/08/03
loading
1
2
3
4
5
一个游戏:有3扇关闭着的门,其中2扇门后面各有一只羊,另一扇门后面有一辆车。
参与者:一个游戏者和一个主持人。主持人事先知道各扇门后的物品,而游戏者不知道。
游戏目的:游戏者选择到车。
游戏过程:1、游戏者随机选定一扇门;2、在不打开此扇门的情况下,主持人打开另一扇有羊的门。3、此时面对剩下2扇门,游戏者有一次更改上次选择的机会。
问题:游戏者是否应该改变上次的选择,以使选到车的概率较大?

问题的学名叫《蒙提霍尔问题》,阅读原文有来龙去脉。

答案有换和不换两种,有的认为是换概率是2/3,有的认为是不换和换都一样,概率是50%,因为后面剩两个概率是相同的。

正确答案是应该换,几种解释:

  1. 游戏者坚持每次都换,开始选中羊的概率是2/3, 在第一次选中羊的情况下,换了就能够得到车,所以换能得到车的概率是2/3。
  2. 假设有1000个门,只有一个后面有车,如果主持人帮游戏者打开选后的998个门,要不要换?当然换,排除了错误答案的情况,换的概率会高很多。

除了思考的方式,还可以写个程序,用实验的方式验证。(在一些不容易想的问题上,可以用程序模拟多次独立事件,直观查看结果,但不一定和理论完全一样)

代码和结果如下,如果在主持人提示后换的话,也是2/3的概率选中车。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"

#define DOOR_COUNT 3
int getrand( int max )
{
double max_rand = RAND_MAX * 1.0;
return (rand() /max_rand) * max;
}
int choose( int changed )
{
char door[ DOOR_COUNT ] = { 0 };
int moto_index = getrand( DOOR_COUNT );//车子所在的门序号
door[ moto_index ] = 1;
int choose_index = getrand( DOOR_COUNT );//游戏者第一次选的门序号
int left_index = -1;
int display_index = -1;
int i;
for (i = 0; i < DOOR_COUNT; i++) {
if( i == choose_index )
continue;
if( i == moto_index )
continue;
display_index = i;//主持人打开的门序号
break;
}
for( i=0; i < DOOR_COUNT; ++i )
{
if( i == choose_index )
continue;
if( i == display_index )
continue;
left_index = i;//最后没打开的门序号
}
printf("moto_index = %d first_choose_index = %d display_index = %d left_index = %d\n",
moto_index, choose_index, display_index, left_index);
if( changed == 1)
choose_index = left_index;
if( choose_index == moto_index )
return 1;
return 0;
}
int main(int argc, const char *argv[])
{
srand( ( unsigned )time( NULL ) );
int count = 10000;
int changed = 1;//交换
int motocount = 0;
int i;
for (i = 0; i < count; i++) {
int iRet = choose( changed );
motocount += iRet;
}
printf( "changed = %d count = %d motocount = %d, rate = %0.2f\n",
changed, count, motocount, motocount*1.0/count);
system( "pause" );
return 0;
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
moto_index = 0 first_choose_index = 1 display_index = 2 left_index = 0
moto_index = 2 first_choose_index = 2 display_index = 0 left_index = 1
moto_index = 1 first_choose_index = 2 display_index = 0 left_index = 1
......
moto_index = 2 first_choose_index = 0 display_index = 1 left_index = 2
moto_index = 2 first_choose_index = 0 display_index = 1 left_index = 2
moto_index = 0 first_choose_index = 0 display_index = 1 left_index = 2
moto_index = 1 first_choose_index = 0 display_index = 2 left_index = 1
moto_index = 2 first_choose_index = 0 display_index = 1 left_index = 2
moto_index = 0 first_choose_index = 1 display_index = 2 left_index = 0
moto_index = 1 first_choose_index = 0 display_index = 2 left_index = 1
moto_index = 0 first_choose_index = 2 display_index = 1 left_index = 0
moto_index = 2 first_choose_index = 1 display_index = 0 left_index = 2
moto_index = 0 first_choose_index = 2 display_index = 1 left_index = 0
changed = 1 count = 10000 motocount = 6692, rate = 0.67
CATALOG
  1. 1. 运行结果