论坛首页 Java企业应用论坛

国王和100个囚犯

浏览 36150 次
精华帖 (0) :: 良好帖 (10) :: 新手帖 (0) :: 隐藏帖 (8)
作者 正文
   发表时间:2010-01-14  
mountainhunter 写道
得考虑路灯刚开始 是亮 还是灭吧
不然有问题


就是,没说灯一开始是亮的还是灭的。

如果第一天出去的人就是计数员,那么他可以初始化灯的状态。但是他们都不知道时间,因此可能第二天出去的人还以为自己是第一天出去的,那就麻烦了。

如果他们在被关进去时都能看到灯的状态,那么问题就可以解决了。如果灯是灭的用楼上的程序就OK了,灯是亮的就要求所有人对灯的操作反过来。
0 请登录后投票
   发表时间:2010-01-14  
showr 写道
晕 代码看不懂

能说下思路么 ?

 

         第一个出去的人的任务:开灯,且只负责开灯

         其他所有人的任务:关灯,且只负责关灯,且只在自己从未关过灯的情况下才可以关灯

 

         这样第一个人经过无数次放风后,一共看到了99次关着的灯,他们就自由了

0 请登录后投票
   发表时间:2010-01-14  
这需要用程序来算吗?应该只能用逻辑推理吧。

随机开门,那就考虑极端情况就可以了。
最快出来的顺序是:
   第一天囚犯A出来,第二天计数员出来。第三天囚犯B,第四天计数员,,,,这样99*2=198天就可以了。
最慢的顺序是:
    每天都是同一个门被打开,关到老死。
至于灯的初始状态倒是不影响任何东西。
0 请登录后投票
   发表时间:2010-01-14  
楼上说的也有道理
这难道是面试题吗?
0 请登录后投票
   发表时间:2010-01-14   最后修改:2010-01-14
。。。发重复了
0 请登录后投票
   发表时间:2010-01-14  
jy00105276 写道
tedeyang 写道
这需要用程序来算吗?应该只能用逻辑推理吧。

随机开门,那就考虑极端情况就可以了。
最快出来的顺序是:
   第一天囚犯A出来,第二天计数员出来。第三天囚犯B,第四天计数员,,,,这样99*2=198天就可以了。
最慢的顺序是:
    每天都是同一个门被打开,关到老死。
至于灯的初始状态倒是不影响任何东西。



初始状态影响很大啊 

计数员只有在知道初始状态的情况下,看到了非初始状态的情况才能计数一次

如果不知道初始状态的话

计数员有理由认为  每天随即的人都是他  并且状态一直没改变过

当然算时间范围是没关系的 198 ——正无穷


0 请登录后投票
   发表时间:2010-01-14  
这个问题我有几点看法:
1、囚犯不知道时间,也就是说他们不知道自己会是第几个人。根据条件,他们更不知道是第几天。
2、囚犯随机的放风。这里可能出现同一囚犯放风多次的情况。
3、那个路灯是他们唯一交流的工具。
4、现在最大的问题是不知道灯的初始状态。

我的办法:
1、指定计数囚犯。100囚犯中指定一个唯一的计数囚犯。
2、规则:
(1)所有囚犯除计数囚犯外,当他是第1次放风的时候,如果灯是关着的则设置灯为开,以后再放风,不干涉灯的状态。但第1次放风时,如果灯是开着的,则自己认为自己没放过风。
(2)计数囚犯统计灯开的次数,统计之后将灯关闭。计数到99时,结束。

细节解释:当计数囚犯第1次出门,如果灯是开着的。会有3种情况:1、灯默认是开着的,他是第1个放风的。2、灯是默认开着的,其他囚犯没有去碰开关。3、灯初始是关着的,一放风囚犯将它改为开。
现在问题出现了,由于不知道灯的初始状态,所以在计数囚犯计第1个数时是有误差的,误差为1人。但如果,计数囚犯放风时看到灯是关着的,那就万事大吉了。
0 请登录后投票
   发表时间: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 + "年)");
	}
}
0 请登录后投票
   发表时间:2010-01-14  
关键是,你如何知道自己是第一个出去的?
难道囚犯们给国王提议:
亲爱的陛下,我问有一个小小的要求,让我第一个出去吧。

因为不能确定计数员是那个,就全乱套。都认为自己是计数员,见到开灯就关,不就乱完了
0 请登录后投票
   发表时间:2010-01-14  
pujia12345 写道
关键是,你如何知道自己是第一个出去的?
难道囚犯们给国王提议:
亲爱的陛下,我问有一个小小的要求,让我第一个出去吧。

因为不能确定计数员是那个,就全乱套。都认为自己是计数员,见到开灯就关,不就乱完了


15分钟商量的时候就可以指定计数员啦
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics