The Locker Puzzle
The Locker Puzzle
今天刷到一个很有趣的著名概率题,如果有和我一样闲的人可以一起看看。
Philippe Flajolet 和 Robert Sedgewick 在 2009 年提出了“百囚犯问题(The Locker Puzzle)”。
问题描述
在监狱中有 \(100\) 名囚犯,被编号为 \(1\) - \(100\) 号。典狱长决定给囚犯们一次特赦的机会,条件是通过一项挑战。在一个房间中放着一个有100个抽屉的橱柜,里面随机放着与囚犯编号对应的 \(1\) - \(100\) 的号码牌。挑战开始后,每个囚犯依次进入该房间,打开不超过半数的抽屉,并从中找到与自己对应的号码则为成功,每名囚犯出去时该橱柜恢复原样。从第一名囚犯进入直至最后一名囚犯出来期间不允许有任何交流,任何一名囚犯挑战失败都会导致所有囚犯死亡,只有全部成功才能够特赦该 \(100\) 名囚犯。如果囚犯们都随机打开 \(50\) 个抽屉,他们的生存几率为 \(1/{2^{100}}\) ,约等于 \(0.0000000000000000000000000000008\) 。所以囚犯们需要找到一个最佳策略,来提高生存率。
变态的思路
1.先打开自己的号码的抽屉。
2.如果这个抽屉里有他的号码,他就成功了。
3.否则,抽屉里会有另一个号码,然后他打开这个号码的抽屉。
4.不断重复第 \(2\) 步和第 \(3\) 步,直到他找到自己的号码或已经打开了 \(50\) 个抽屉(那就全体失败了)。
证明
太长了,懒得抄,自己看论文吧。
https://www.cl.cam.ac.uk/~gw104/Locker_Puzzle.pdf
好吧,其实这个论文我看不懂,上抖音学下证明吧。
Last
最后是C++的小模拟(百万次测试),rt;可见,结果基本就是标准计算概率:0.3118了。
#include<bits/stdc++.h>
using namespace std;
const int N=105;
int box[N];
int pep[N];
int vb[N],vp[N];
const int n=100;
int suc;
const int tot=1e6;
int main(){
srand(time(0));
for(int i=1;i<=tot;i++){
memset(vb,0,sizeof vb);
memset(vp,0,sizeof vp);
for(int i=1;i<=n;i++){
int x=rand()%n+1;
while(vb[x]){
x=rand()%n+1;
}
vb[x]=1;
box[i]=x;
}
for(int i=1;i<=n;i++){
int x=rand()%n+1;
while(vp[x]){
x=rand()%n+1;
}
vp[x]=1;
pep[i]=x;
}
int fin=0;
for(int i=1;i<=n;i++){
int x=pep[i];
int k=50;
while(k--){
if(box[x]==pep[i]){
fin++;
break;
}
x=box[x];
}
}
printf("Test %d : The number of the successful people: %d\n",i,fin);
if(fin==n) suc++;
}
cout<<"------------------"<<endl;
cout<<"The number of ALL_PEOPLE_OUT:"<<" "<<suc<<endl<<endl;
double ans=suc*1.0/tot;
printf("The odds is %0.8lf",ans*100);cout<<"%"<<endl;
return 0;
}


浙公网安备 33010602011771号