瑪麗蓮問題是一個十分有趣的概率問題,首先,它是違反人的第一直覺的。為什么會違反直覺?我們直接來看題目吧。
瑪麗蓮問題:
你參加一個電視節目,有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%,其實也就是三分之二。這道題目的正確答案應該是:
- 選擇換獲獎概率:2/3
- 不換的獲獎概率:1/3
我們的測試結果是符合正確答案的。
思考
其實在寫交換函數的時候,寫到判斷的時候就已經知道答案了,因為此時的問題就是剩下的盒子里有無有獎的盒子,有獎的話我們選擇換就必中,無獎的話我們選擇換就不中。而剩下的兩個里面有獎的概率是多少呢?不就是三分之二嘛!所以此時問題就迎刃而解了。我覺得這個問題乍看很摸不著頭腦,自己模擬一遍思路就相當開闊了。
最后附上全部代碼:
#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;
}