锁定老帖子 主题:国王和100个囚犯
精华帖 (0) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (8)
|
|
---|---|
作者 | 正文 |
发表时间:2010-01-14
mountainhunter 写道 得考虑路灯刚开始 是亮 还是灭吧
不然有问题 就是,没说灯一开始是亮的还是灭的。 如果第一天出去的人就是计数员,那么他可以初始化灯的状态。但是他们都不知道时间,因此可能第二天出去的人还以为自己是第一天出去的,那就麻烦了。 如果他们在被关进去时都能看到灯的状态,那么问题就可以解决了。如果灯是灭的用楼上的程序就OK了,灯是亮的就要求所有人对灯的操作反过来。 |
|
返回顶楼 | |
发表时间:2010-01-14
showr 写道
晕 代码看不懂
能说下思路么 ?
第一个出去的人的任务:开灯,且只负责开灯 其他所有人的任务:关灯,且只负责关灯,且只在自己从未关过灯的情况下才可以关灯
这样第一个人经过无数次放风后,一共看到了99次关着的灯,他们就自由了 |
|
返回顶楼 | |
发表时间:2010-01-14
这需要用程序来算吗?应该只能用逻辑推理吧。
随机开门,那就考虑极端情况就可以了。 最快出来的顺序是: 第一天囚犯A出来,第二天计数员出来。第三天囚犯B,第四天计数员,,,,这样99*2=198天就可以了。 最慢的顺序是: 每天都是同一个门被打开,关到老死。 至于灯的初始状态倒是不影响任何东西。 |
|
返回顶楼 | |
发表时间:2010-01-14
楼上说的也有道理
这难道是面试题吗? |
|
返回顶楼 | |
发表时间:2010-01-14
最后修改:2010-01-14
。。。发重复了
|
|
返回顶楼 | |
发表时间:2010-01-14
jy00105276 写道 tedeyang 写道 这需要用程序来算吗?应该只能用逻辑推理吧。
随机开门,那就考虑极端情况就可以了。 最快出来的顺序是: 第一天囚犯A出来,第二天计数员出来。第三天囚犯B,第四天计数员,,,,这样99*2=198天就可以了。 最慢的顺序是: 每天都是同一个门被打开,关到老死。 至于灯的初始状态倒是不影响任何东西。 初始状态影响很大啊 计数员只有在知道初始状态的情况下,看到了非初始状态的情况才能计数一次 如果不知道初始状态的话 计数员有理由认为 每天随即的人都是他 并且状态一直没改变过 当然算时间范围是没关系的 198 ——正无穷 |
|
返回顶楼 | |
发表时间:2010-01-14
这个问题我有几点看法:
1、囚犯不知道时间,也就是说他们不知道自己会是第几个人。根据条件,他们更不知道是第几天。 2、囚犯随机的放风。这里可能出现同一囚犯放风多次的情况。 3、那个路灯是他们唯一交流的工具。 4、现在最大的问题是不知道灯的初始状态。 我的办法: 1、指定计数囚犯。100囚犯中指定一个唯一的计数囚犯。 2、规则: (1)所有囚犯除计数囚犯外,当他是第1次放风的时候,如果灯是关着的则设置灯为开,以后再放风,不干涉灯的状态。但第1次放风时,如果灯是开着的,则自己认为自己没放过风。 (2)计数囚犯统计灯开的次数,统计之后将灯关闭。计数到99时,结束。 细节解释:当计数囚犯第1次出门,如果灯是开着的。会有3种情况:1、灯默认是开着的,他是第1个放风的。2、灯是默认开着的,其他囚犯没有去碰开关。3、灯初始是关着的,一放风囚犯将它改为开。 现在问题出现了,由于不知道灯的初始状态,所以在计数囚犯计第1个数时是有误差的,误差为1人。但如果,计数囚犯放风时看到灯是关着的,那就万事大吉了。 |
|
返回顶楼 | |
发表时间:2010-01-14
public class Prisoner { /** * 犯人数目 */ private static final int PRISONER_COUNT = 100; /** * @param args */ public static void main(String[] args) { Random r = new Random(); boolean lightStartState = r.nextBoolean(); // 被关进去时看到灯的状态(假设被关进去时都经过院子) boolean lightState = lightStartState; // 当前灯的状态 boolean[] prisoner = new boolean[PRISONER_COUNT]; // 犯人,当出来放过风并且按照约定改变灯过的状态时,其值为true final int COUNTER_ID = r.nextInt(PRISONER_COUNT); // 任意指定计数员 int counter = 0; // 计数员记下的出来放过风的犯人数目 int days = 0; // 总共所花的天数 while (counter < PRISONER_COUNT) { days++; int n = r.nextInt(PRISONER_COUNT); // 随机出来放风的犯人 if (n == COUNTER_ID) {// 计数员 if (!prisoner[COUNTER_ID]) { counter++; prisoner[COUNTER_ID] = true; // 计数员放过风 } if (lightState != lightStartState) { // 灯非初始状态 // 是有其他犯人出来放过风了 lightState = lightStartState; // 将灯改回初始状态 counter++; } } else { // 其他犯人 if (!prisoner[n] && lightState == lightStartState) { // 犯人未改过灯的状态,且目前灯的状态和初始状态一致 // 改变灯的状态,以告诉计数员他出来过 lightState = !lightStartState; prisoner[n] = true; } } } // 检查结果 int sum = 0; for (int i = 0; i < PRISONER_COUNT; i++) { if (prisoner[i]) { sum++; } } System.out.println(sum + "个犯人出来放过风"); System.out.println("共花了 " + days + "天(" + days / 365 + "年)"); } } |
|
返回顶楼 | |
发表时间:2010-01-14
关键是,你如何知道自己是第一个出去的?
难道囚犯们给国王提议: 亲爱的陛下,我问有一个小小的要求,让我第一个出去吧。 因为不能确定计数员是那个,就全乱套。都认为自己是计数员,见到开灯就关,不就乱完了 |
|
返回顶楼 | |
发表时间:2010-01-14
pujia12345 写道 关键是,你如何知道自己是第一个出去的?
难道囚犯们给国王提议: 亲爱的陛下,我问有一个小小的要求,让我第一个出去吧。 因为不能确定计数员是那个,就全乱套。都认为自己是计数员,见到开灯就关,不就乱完了 15分钟商量的时候就可以指定计数员啦 |
|
返回顶楼 | |