【随笔】关于玛丽莲问题的一些思考(附c++代码证明)

2018-08-19  本文已影响0人  Sheep98

玛丽莲问题是一个十分有趣的概率问题,首先,它是违反人的第一直觉的。为什么会违反直觉?我们直接来看题目吧。

玛丽莲问题:

你参加一个电视节目,有3个门,其中2个门后是山羊,一个门后是汽车。节目过程是你先挑选一个门,然后主持人会从剩下的两个门中推开一扇藏有山羊的门,然后问你,如果为了赢得汽车,这个时候你是否改变原来的选择。

这个问题也有另一个版本:

有A,B,C三个盒子,已知其中一个装有礼物,另两个是空的,由你随便挑选其中一个而不打开。然后有个知道礼物放在哪个盒子中的人,把另两个盒子中没有礼物的那个打开,现在给你一个换选盒子的机会,即选择另一个剩下的。那么为了使您得到礼物的机会大一些,你选择换还是不换,为什么?

思考

为了方便说明,我选择了第二个对于我来说更方便解释的问题进行说明。首先为了选择,我们需要思考换还是不换的概率是多少。第一次看到这个问题,我直觉上来说是觉得都是二分之一的概率,应该没有差别。但是看到正确答案是选择换的话获奖概率为2/3,不换为1/3以后,我觉得很神奇,同时也产生了想用代码验证的想法。

代码构思

构造模型

首先构造三个盒子的类,我选择用一个长度为三的bool数组模拟三个盒子,利用随机数选择让其中一个为true,其它两个为false

class threeBox {
public:
    bool box[3] = {false,false,false};            //先初始三个false
    threeBox() { box[rand() % 3] = true;}     //随机选择一个box为true
};

好了,构造好了三个box模型,接下来模拟一下第一次选择,利用一个int,保存我们在0-2里面随机的一个数,当作是我们第一次选中的,也就是box的数组下标。完成这些只需要在threeBox类上加上一点点:

class threeBox {
public:
    bool box[3] = {false,false,false};            //先初始三个false
    int firstSelect;                              //第一次选择
    /*随机一个box为true,然后随机选择一个box当作我们的第一次选择*/
    threeBox() { box[rand() % 3] = true; firstSelect = rand() % 3;  }    
};

到这里其实模型已经构建好了,接下来就是主持人进行选择。为了方便最后的结果显示够直白,我们选择用一个bool函数,返回主持人打开一个空盒子以后剩下的盒子里是有奖还是无奖的(其实机智的朋友这时可能已经反应过来这里才是关键的所在),构造的函数如下:

bool threeBox::change() {
    int a[2];            //用来保存剩下的两个盒子的情况
    int cnt = 0;       //下标
    for (int i = 0; i < 3;i++) {
        if (i == firstSelect)continue;  //如果i等于第一次选择的,则跳过
        else a[cnt++] = box[i];          //保存未选择的盒子的状态
    }
/*如果两个盒子都为空,则主持人开盒子以后另一个也为空
 *则假如我们选择交换,结果是空盒子,所以返回false
 */
    if (a[0] == false && a[1] == false) {
        return false;
    }
/*如果其中一个盒子有奖,则拆另一个盒子
 *则我们交换的话就获奖了,返回true
 */
    else {
        return true;
    }
}

测试

测试代码十分简单,直接上代码吧:

int main() {
    int cnt = 0;      //保存获奖的次数
    for (int i = 0; i < 100000; i++) {
        threeBox b;
        if (b.change() == 1) {
            cnt++;
        }
        else continue;
    }
    cout << "the probability: " << cnt/1000 << "%" << endl;
    system("pause");
    return 0;
}

结果

测试结果

结果显示结果为66%,其实也就是三分之二。这道题目的正确答案应该是:

我们的测试结果是符合正确答案的。

思考

其实在写交换函数的时候,写到判断的时候就已经知道答案了,因为此时的问题就是剩下的盒子里有无有奖的盒子,有奖的话我们选择换就必中,无奖的话我们选择换就不中。而剩下的两个里面有奖的概率是多少呢?不就是三分之二嘛!所以此时问题就迎刃而解了。我觉得这个问题乍看很摸不着头脑,自己模拟一遍思路就相当开阔了。

最后附上全部代码:

#include<iostream>
#include<random>
using namespace std;

class threeBox {
public:
    bool box[3] = {false,false,false};
    int firstSelect;
    threeBox() { box[rand() % 3] = true; firstSelect = rand() % 3;  }
    bool change();
};

bool threeBox::change() {
    int a[2];
    int cnt = 0;
    for (int i = 0; i < 3;i++) {
        if (i == firstSelect)continue;
        else a[cnt++] = box[i];
    }
    if (a[0] == false && a[1] == false) {
        return false;
    }
    else {
        return true;
    }

}

int main() {
    int cnt = 0;
    for (int i = 0; i < 100000; i++) {
        threeBox b;
        if (b.change() == 1) {
            cnt++;
        }
        else continue;
    }
    cout << "the probability: " << cnt/1000 << "%" << endl;

    system("pause");
    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读