一道非常著名的“反直觉”智力题--生存概率

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


生存概率

原视频讲解见
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值