智力题:有100个囚犯

guang_5678 2010-08-05 09:16:51
智力题:有100个囚犯要被判处死刑,国王说,我把你们关到有100个房间的监狱,每个人一个房间。监狱放风的地方有一盏灯,可以由囚犯控制开关。囚犯关在房间里时不能看见这盏灯。每天随机有一个房间开门,让囚犯出来放风。现在的问题是怎样才能知道所有的囚犯都已出来放过风。如果确定了这个时间,让一个囚犯来告诉他,是对的就全部释放这些囚犯。如果是错的就全部斩首。如果不能确定这个时间就永远关下去。怎样编程实现?
...全文
1945 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
michaelguy 2010-11-10
  • 打赏
  • 举报
回复
想了好久, 如果要有解, 需要下列条件中的一个能得到满足
1, 能确定第一个出来的人 (就是说能够计算时间了)
这种情况下 第一个出来的人负责记数,
2, 能确定灯的初始状态 (不需要计算时间)
这种情况下, 只要开始指定一个人来计数, 灯的初始状态决定了计到100 还是99结束

脑筋急转弯解法
因为所有房间只有一个门, 所以进牢房必须经过院子, 所以只要都进了牢房,就表示都到过院子


期待其他高效解法
Q446512799 2010-08-11
  • 打赏
  • 举报
回复
这个问题只是考虑出去的可行方案,不是让你去管是多久以后的事
首先100人都要出去一次,没人每天出去一次的概率才1/100
100人都出去平均是多久啊。。。。
magic_c 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zmshy2128 的回复:]
第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案
[/Quote]
开灯的99个人连续出去,然后关灯的来了,实际上都放过风了,可还要一直等到关灯的出来100次。。。
lusmiling 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 mudunke775 的回复:]
引用 25 楼 zmshy2128 的回复:
第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案


你的答案根本是错的。如果连续2个人都是第一次出去,第二个人看见灯是开着的,如何处理?

应该是如果这个人没有开过灯,出去的时候灯是关着的,那他开灯!……
[/Quote]

楼上说的方法肯定是可以的,但是这样应该是所消耗时间的最大值吧,应该可以寻找更好的方法吧,正在思考中
Q446512799 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zmshy2128 的回复:]
第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案
[/Quote]
我只是来支持这个哥们的,人家回复两次了
虽然放出去时N年以后的事了
wangbingshan997 2010-08-10
  • 打赏
  • 举报
回复
开关在哪里,是室内还是室外?
wu181671643 2010-08-10
  • 打赏
  • 举报
回复
不是随机的吗 所以答案也是随机的诶
而且问题是“你有办法帮助他们最终获释吗?”
没说是要问多久吧?
mudunke775 2010-08-10
  • 打赏
  • 举报
回复

srand(GetTickCount());//设置随即种子
int person[100] = {0};//0表示此人没开过灯,1表示此人已经开过灯了
long lday=1;//第一天
int personnum =1;//人数为1
int fristman = rand()%100;//第一个人(负责计数)
person[fristman] = 1;//第一个人被计数
bool light = false;//第一个人出去把灯关了,并将人数计数为1
while(1)
{
int temp = rand()%100;//随机一个人
if(person[temp] == 0 && !light)//此人没有开过灯并且灯是关着的
{
person[temp] = 1;//此人已经开过灯了
light = true;//把灯打开
}
if(temp == fristman && light)//轮到第一个人出来,并发现灯是开着的
{
light = false;//关灯
personnum++;//人数加1
}
if(personnum == 100)//如果人数到100表示每个人都开过灯了
{
break;
}
lday++;//日期(日)
}

最后得出的天数不固定,有8000多的,也有11000多的,2,3十年基本上人都死的差不多了吧
mudunke775 2010-08-10
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zmshy2128 的回复:]
第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案
[/Quote]

你的答案根本是错的。如果连续2个人都是第一次出去,第二个人看见灯是开着的,如何处理?

应该是如果这个人没有开过灯,出去的时候灯是关着的,那他开灯!这样每次灯开着,就表示有一个人注册了,灯关了就表示第一个人知道了(因为只有他关灯),直到100次。(如果真的按随机的话,我认为没人能活那么长,不信大家可以做个程序试下)
brookmill 2010-08-07
  • 打赏
  • 举报
回复
举个极端的例子:如果严格按照1-100编号的顺序依次放风,那么100天大家就都出去过了。但是倒霉的100号兄弟前99次出去灯都是开着的,要等10000天他才有机会亲自动手过一下开灯的瘾,1号兄弟才能第100次关灯
brookmill 2010-08-07
  • 打赏
  • 举报
回复
......
counter = rand() % 100;
bool flag = false;
prisoner.set(counter);

bitset<100> prisoner_out(0);
prisoner_out.set(counter);

while (true)
{
++day;
i = rand() % 100;
if (!prisoner_out[i])
{
prisoner_out.set(i);
if (prisoner_out.count() == prisoner_out.size())
{
cout << "All Out :" << day << "days\t\t" << day/365 << "years" << endl;
cout << "But they don't know! until ..." << endl;
}
}
if (flag && i == counter)
......

我把9楼的代码稍微修改了一下,加了一个bitset来记录每个人有没有出去过(原来那个bitset纪录的是每个人有没有开过灯)。
运行几次看结果,基本上两三年之内就会达到“每个人都出去过”的条件了,但是真正要全部释放要等二三十年。
原因是:很多人第一次甚至前几次出去放风的时候灯都是开着的,所以一直没机会开灯。
嘎文 2010-08-07
  • 打赏
  • 举报
回复
囚犯不能随意出门来开关灯, 某一囚犯开关灯的状态其他囚犯最多有一个知道,所以,楼上貌似还没出现正解
hu0097 2010-08-07
  • 打赏
  • 举报
回复
应该还有更好的算法吧
cswuyg 2010-08-06
  • 打赏
  • 举报
回复 1
网上可以搜索到详细的题目和思路,不过题目要求可以改变。。不觉得跟2进制有啥关系。
/*参考资料:http://www.javaeye.com/topic/569275*/
////////////////////////////////////////////////////////////
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
////////////////////////////////////////////////////////////
int main()
{
bitset<100> prisoner(0);
int day = 1;//已过了的天数
int counter;//统计者
int close_count = 0;//已经关灯次数
int i;//随机放风的囚犯

srand((unsigned)time(NULL));

counter = rand() % 100;//第一天的那个囚犯为统计者
bool flag = false;//灯的状态
prisoner.set(counter);//统计囚犯设置为已经统计过

while (true)
{
++day;
i = rand() % 100;
if (flag && i == counter)
{//灯是开的,且是统计囚犯
flag = false;
++close_count;
}
else if (!flag && !prisoner[i])
{//灯是关的,且是未统计过的囚犯
flag = true;
prisoner.set(i);
}
if (close_count == 99)
{
break;
}
}
cout << "Out of prison:" << day << "days\t\t" << day/365 << "years" << endl;
system("pause");
return 0;
}
zmshy2128 2010-08-06
  • 打赏
  • 举报
回复
第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。
AAA20090987 2010-08-06
  • 打赏
  • 举报
回复
第三种方法提示如下: 
  
   分为一个基本记数者和N个2级记数者,基本记数者的独立记数上限Cp和2级记数的独立计数上限Cs,时间由长度为S1和S2的两段交替组成.在S1阶段,计数者计数直到达到其独立计数上限,在S2阶段,达到计数上限的2级计数者将通过开灯方法告诉基本计数者直到基本计数者得到所有2级计数者完成任务并加上自己计数为100时宣布自由。
   此方法通过计算机模拟优化可在10年左右完成 。


这个方法没看懂,请高手解释一下吧。
谢谢啦。


cranium 2010-08-06
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zmshy2128 的回复:]

第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案
[/Quote]

听说这样是27年。

看看贴吧的回答吧
http://tieba.baidu.com/f?kz=69558066
linsen_519 2010-08-06
  • 打赏
  • 举报
回复
哎呀 ~ 我脑袋疼。。。。
alandingking 2010-08-06
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zmshy2128 的回复:]

第一天出去放风的囚犯只负责关灯。其他囚犯第一次出去就开灯,第二次以后就不用管。

直到那个负责关灯的囚犯关了 100 次灯 (包括自己第一天出去的那次)。

我只是想重复下我的答案
[/Quote]
嗯,这样行得通,也只有第一个人知道完成的时间,上面贴的代码也就是这个意思
wryse 2010-08-06
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 xiaopei1982 的回复:]
1个囚犯负责关灯,其他囚犯第一次出去就开灯,第二次向后就不管。直到那个负责关灯的囚犯连续两次出去看见关是开着的
[/Quote]
根据题的说法,囚犯之间无法商量谁是负责关灯的吧……
加载更多回复(23)

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧