蒙特霍尔三门问题及其实现1.0

蒙特霍尔三门问题及其实现

一、蒙特霍尔三门问题

三门问题也称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论,出自美国的电视游戏节目Let’s make a deal.来自 Craig F. Whitaker 于1990年寄给《展示杂志》(Parade Magazine)玛丽莲·沃斯·莎凡特(Marilyn vos Savant)专栏的信件: “假设你正在参加一个游戏节目,你被要求在三扇门中选择一扇:其中一扇后面有一辆车;其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后知道门后面有什么的主持人,开启了另一扇后面有山羊的门,假设是三号门。他然后问你:“你想选择二号门吗?”转换你的选择对你来说是一种优势吗?”

二、描述

​ 假设有三个门,选择每个门,门后有车的概率是1/3。

​ 由于主持人知道车所在的门的位置,打开的门后必为羊。

​ 对于选手来说,第一次选择时,门后有车的概率是1/3。而后主持人打开了一扇门,门后没有车。此时事件已经已经发生了改变。

​ 即“你是否换门”

​ 后发生的事情不会影响已经发生的事情的概率,所以门后有车的概率仍然是1/3。无论是否有主持人开门的操作,选手选择换门后能开到有车的门的概率都是2/3

​ 在主持人开门前,有2门共同分享这个概率,故每个门的概率为2/3 * ( 1/ 2 ) = 1/3。主持人开门后,他为你在剩下两个门中排除了一个错误答案,即只有1个门分享这个概率2/3。

​ 所以此时选择剩下的门的概率为2/3。

​ 这样看起来,更像是一个理解的错误。ABC三个门,当你选定一个门A,换门后赢的概率是 2/3 ,只是换门选择的对象有B和C两个,此时

​ P(换门成功) = P(换门到C成功) + P(换门到B成功)= 2/3

​ 主持人打开门C,里面没有车。P© = 0。所以

​ P(换门成功) = 0 + P(换门到B成功)

​ 即

​ P(换门成功) = P(换门到B成功)= 2/3

​ 相似的,当有四个门 A、B、C、D

​ P(换门成功) = 3/4 = P(B) + P© + 0,所以每个门的概率是3/8

​ 总之,理解这件事需要确定一个前提:后发生的事,不会影响先发生的事件的概率

三、程序模拟

class ThreeDoor{
private:
    int correctDoor;
    int doorNum;
    map remainDoors;
    int selectedDoor = -1;
    int deletedDoor = -1;

public:
    ThreeDoor(int n) {
        doorNum = n;
        //随机产生正确的门的数字,填写每个门的概率
        correctDoor = ensureCorrectDoor(n);
        // remainDoors = new int[n];
        for(int i = 0; i < n ; i ++) 
            remainDoors[i] = 1.0 / n;
    }
    void startGame();
    int ensureCorrectDoor(int n);
    void selectDoor();
    void deleteDoor();
    void retryProbability();

    bool isWin = false;
    void displayRemain();
    void displayGameProcess(int a);
};

inline int ThreeDoor::ensureCorrectDoor(int n) {
    //get the correct door
    srand(time(0));
    //获取一个0-n的随机数
    printf("all doors is %d\n",n);
    int res = rand() % n;
    printf("the correct door is %d\n",res);
    return res;
}

开始游戏

inline void ThreeDoor::startGame() {
    for(int i = 0; i < remainDoors.size(); i++){
        //显示进度
        displayGameProcess(i);
        //仅有两个门的时候显示结果
        if(doorNum <= 2)    break;
        //只有前两轮进行换门操作
        if(i < 2) selectDoor();
        //主持人进行排查操作
        deleteDoor();
        retryProbability();
    }
    if(selectedDoor != correctDoor) {
        printf("    you  win!!!!!!!\n");
        isWin =  true;
    }
    else
        printf("    you  lose!!!!!!!\n");
}

在大概率的几个选项中,选择一个门

bool cmp(pair a , pair b) {
    return a.second > b.second;
}

inline void ThreeDoor::selectDoor() {
    printf("\n\n start to select doors........\n");
    //change to vector and sort according probability ASC (from big to small)
    vector> doorVect(remainDoors.begin(),remainDoors.end());
    sort(doorVect.begin(),doorVect.end(),cmp);

    //get all max probability, and selected one
    vector>::iterator iter = doorVect.begin();
    float max = doorVect.begin()->second;
    printf("\t get the max probability \t%f\n",max);
    while (iter != doorVect.end()) {
        // printf("[%d,%f]\t",iter->first,iter->second);
        if(max > iter->second) {
            // printf("\n current probability is %f , max probability is %f\n",iter->second,max);
            iter --;
            break;
        }
        iter++;
    }   
    // cout << endl;
    int num = iter - doorVect.begin();
    
    printf("\t probability  \t num \n");
    printf("\t   %f  \t  %d \n",max,num);
    int tmp;
    do {
        // printf("all door num is %d  doorNum = %d\n",num,doorNum);
        tmp = rand() % num;
        // printf("the selected number is :  %d   all door num is %d  doorNum = %d\n",tmp,num,doorNum);
    } while(remainDoors[doorVect[tmp].first]== 0);
    selectedDoor = doorVect[tmp].first;
    printf("\t get the selected door is \t%d\n",doorVect[tmp].first);
    cout << endl;
}

主持人排除一个门

inline void ThreeDoor::deleteDoor() {
    //这个部分删除操作是随机的,随机选择剩下门中的任何一个
    printf(" start to delete doors........\n");
    printf("\t the num can be deleted \t %d\n",doorNum);
    int tmp;
    printf("\t the  door doors : \t");
    do {
        tmp = rand() % remainDoors.size();
        printf("%d   ",tmp);
    } while(remainDoors[tmp]== 0 || tmp == selectedDoor || tmp == correctDoor);
    printf("\n");
    printf("\t get the deleted door is \t%d\n",tmp);
    
    //此处是手动控制需要排除的门
    // do {
    //     printf("input the door to be deleted : ");
    //     scanf("%d",&tmp);
    //     printf("\n");
    // } while (tmp == selectedDoor || remainDoors[tmp] == 0 || tmp > remainDoors.size() || tmp < 0);
    
    remainDoors[tmp] = 0;
    doorNum -= 1;
    deletedDoor = tmp;
    displayRemain();
}

重新计算概率

inline void ThreeDoor::retryProbability() {
    printf(" start to caculate probability........\n");
    float prob = (1.0 - remainDoors[selectedDoor]) / (doorNum - 1 );
    printf("\t selectedProb \t remainProbe \t remainDoor \t result\n");
    printf("\t   %f  \t   %f  \t   %d  \t  %d  \n",
                remainDoors[selectedDoor],(1.0 - remainDoors[selectedDoor]),doorNum,prob);
    printf("the probability is  %f",prob);
    for(int i = 0; i < remainDoors.size();i++) {
        if(remainDoors[i] == 0 || i == selectedDoor) continue;
        remainDoors[i] = prob;
    }
}

你可能感兴趣的:(用c++玩,算法)