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;
}

posted @ 2025-01-26 16:07  Qian·JXのjoker  阅读(43)  评论(0)    收藏  举报