关于“三门问题”的有趣模拟

· · 算法·理论

关于“三门问题”的有趣模拟

理论分析

“三门问题”,是美国一档电视节目《Let’s Make a Deal》(让我们做个交易)中出现的一个问题。问题如下:

我想,大多数人都会觉得换不换门都一样,因为概率好像均为 \frac{1}{2}。然而,事实并非如此。让我们通过数学推论来证明。

先从一个与它相近,但结构更为简单的问题开始。

有甲,乙,丙三人,其中两人将会被处死,而第三人将会被释放。现在,狱卒随机选择两人处死,而让第三人释放。甲想知道谁会被处死。

然而,如果他直接问狱卒的话,狱卒显然是不会告诉他的。于是,他问狱卒乙和丙谁会被处死。狱卒回答他,乙将会被处死。现在,假设甲能与丙互换身份,甲想知道自己互换身份后和不换身份被处死的概率各为多少。

如果甲永远都与丙互换身份,那么甲被处死的概率为 \frac{1}{2}。然而,如果甲不互换身份,那么甲被处死的概率为 \frac{1}{3}。这显然是矛盾的,因为甲互换身份后,被处死的概率不可能比不互换身份时更低。

我们看到了一个惊天大问题:

甲互换身份后,被处死的概率为 \frac{2}{3},而不换身份被处死的概率为 \frac{1}{3}

再推回到上一个问题。

如果玩家换门的话,他所能得到汽车的概率为 \frac{2}{3},原因是只要他选择了一扇有羊的门,互换门后必然能得到汽车。反之,则为 \frac{1}{3}

我们可以用代码验证这一点。

代码模拟

#include <bits/stdc++.h>
using namespace std;
string a[3] = {"car", "sheep", "sheep"}, b[3] = {"sheep", "sheep", "car"}, c[3] = {"sheep", "car", "sheep"}, d[3];
int main() {
    int notc = 0, chan = 0;
    int j = 0;
    srand(time(0));
    while (j < 100000) {
        int n = rand() % 3;
        if (n == 0) {
            for (int i = 0; i < 3; i++) {
                d[i] = a[i];
            }
        } else if (n == 1) {
            for (int i = 0; i < 3; i++) {
                d[i] = b[i];
            }
        } else if (n == 2) {
            for (int i = 0; i < 3; i++) {
                d[i] = c[i];
            }
        }
        int select = rand() % 3;
        if (d[select] == "car") notc++;
        else chan++;
        j++;
    }
    printf("%d %d %.3lf\n", notc, chan, (double)chan / (double)notc);
    if (getchar() != '`') main();
    return 0;
}

相信大家运行代码后,都能得到一样的结果。

这告诉我们一个道理:

不要轻信自己的直觉,有时候,直觉甚至是与现实相左的!