提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
生存概率
原视频讲解见
https://www.bilibili.com/video/BV1kt4y1t75F?spm_id_from=333.999.header_right.fav_list.click&vd_source=3ecd524ad880270e3ceb12ed41e578ed
在这里,我们将通过C 代码编程计算视频中的策略的概率
一道非常著名的“反直觉”智力题:
1、 有100名编号分别为1,2,3…100的囚犯。
2、 每个囚犯的编号都写在一张纸条上。这100张纸条,被随机放入一个房间里的100个外观相同的盒子里。每个盒子里放一张纸条
3、 每个囚犯可以单独进入房间一次,任意查看50个盒子,看完后要将盒子盖上,不留下任何痕迹。如果他能恰好看到“自己的编号”,视为完成任务,需要立刻离开房间。
4、 囚犯们可以在开始之前讨论策略。而一旦第一个囚犯进入房间后,囚犯之间不能有任何交流。
5、 有囚犯全部找到自己的编号,则全员释放;任何有一个囚犯没有找到自己的编号,则全员处决。
那么请问:囚犯们应该制定怎样的策略,尽可能提升被释放的概率呢?
策略
当囚犯进入房间后,打开自己编号的盒子,查看里面的纸条是否是自己的编号,若不是,则去打开 该纸条编号指示的盒子,依次类推,直到找到写有自己编号的纸条或耗尽次数。
C代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(void) {
unsigned char A[100] = {0};
unsigned char tmp_A[100] = {0};
unsigned int loop = 10000;
unsigned char rand_1 = 0, rand_2 = 0;
unsigned char tmp = 0;
unsigned lenth = 0;
unsigned int live = 0;
time_t nowtime = time(NULL);
struct tm *start = localtime(&nowtime);
printf("start: %04d-%02d-%02d %02d:%02d:%02d\n",
start->tm_year+1900, start->tm_mon+1, start->tm_mday,
start->tm_hour, start->tm_min, start->tm_sec);
for(int i = 0; i < sizeof(A); i++)
{
A[i] = i;
}
while(loop--)
{
lenth = 1000000;
//请读者自行思考:当该值小于50时,按上述策略,每个囚犯总能找到写有自己编号的纸条
memcpy(tmp_A, A, sizeof(A));
while(lenth--) //通过俩俩交换的方式将序列打散
{
rand_1 = rand()%sizeof(A);
rand_2 = rand()%sizeof(A);
while(rand_1 == rand_2)
rand_2 = rand()%sizeof(A);
tmp = tmp_A[rand_1];
tmp_A[rand_1] = tmp_A[rand_2];
tmp_A[rand_2] = tmp;
}
unsigned char num = 0; //当前一轮能找到自己编号的人数
for(int i = 0; i < sizeof(A); i++)
{
unsigned count = sizeof(A) / 2;
unsigned index = i;
while(count--)
{
if(i != tmp_A[index])
index = tmp_A[index];
else
{
num++;
break;
}
}
}
if(num == sizeof(A)) live++; //当前一轮所有人都找到了自己的编号,都能存活
}
time_t endtime = time(NULL);
struct tm *end = localtime(&endtime);
printf("end: %04d-%02d-%02d %02d:%02d:%02d\n",
end->tm_year+1900, end->tm_mon+1, end->tm_mday,
end->tm_hour, end->tm_min, end->tm_sec);
printf("live %d\n", live);
return 0;
}
运行结果
start: 2022-07-03 17:13:01
end: 2022-07-03 17:19:13
live 3066
生存概率为 3066/10000