我看到一道题,大致说是岛上有100个囚犯,全是蓝眼睛,后来有个医生一语道破天机,囚犯知道自己眼睛的颜色,找到守卫获得自由。
这个问题的关键点在于递归推理,我把这个问题变了一下,然后写了一个程序,核心代码是reasoning方法。
如果你有更好的写法,欢迎分享~
package zms;
import java.util.ArrayList;
import java.util.List;
/**
* 岛上有 M 个囚犯,
* 但是他们都只能看到别人眼睛的颜色,并不能知道自己的眼睛颜色,
* 而且他们之间不能去谈论眼睛颜色的话题,规定每天晚上都可以有一个人去找守卫说出自己的眼睛颜色,如果错了被杀死,如果对了被释放。
* 但是大家在没有十足的把握前都不敢去找守卫,
* 有一天,一个医生对他们说:"你们之中至少有一个蓝眼睛,其他的都是红眼睛”
* 然后 N 天,这些人都获救了,为什么?这句话对他们有什么影响?
*/
public class BlueEye {
//囚犯Prisoner类
static class Prisoner{
int id; //编号
String eyeColor; //眼睛颜色
int day; //医生点破秘密的第几天
boolean isFree = false; //是否被释放
public Prisoner(int id, String eyeColor){
this.id = id;
this.eyeColor = eyeColor;
}
/**
* 蓝眼囚犯开始推理
* @param array 线索 {knowLestBN,blueNum,day}
* @return array 递归函数,经过推理,更新knowLestBN
*/
private int[] reasoning(int[] array){
int knowLestBN = array[0]; //知道 所有人都知道 至少有knowLestBN个蓝眼睛
int blueNum = array[1]; //岛上蓝眼人数量
//不知道至少有几个蓝眼人 ==> 陷入死循环
if(knowLestBN == 0) {
array[0] = knowLestBN;
return reasoning(array);
}
//过一天后,了解到所有人都不知道蓝眼人数量 ==> 推断所有人知道至少有knowLestBN+1个蓝眼人
if(knowLestBN != blueNum) {
array[0]++;
array[2]++;
return reasoning(array);
}
//剩下的情况就是蓝眼人知道自己是蓝眼人了,然后就求释放
if(this.eyeColor == "蓝眼") {
release(array[2]);
return array;
}
//次日,红眼人看见蓝眼人不见了,就知道自己是红眼人了,也去求释放
array[2]++;
release(array[2]);
return array;
}
/**
* 囚犯被释放
*/
private void release(int day) {
// System.out.println("第" + day + "天," + this.eyeColor + "的" + this.id + "号囚犯找到守卫求释放" );
}
}
//运行程序,描述整个故事的过程
public static void main(String[] args) {
//总共有100个囚犯
int num = 100;
//岛上蓝眼人数量
int blueNum = 100;
//把囚犯关押在一座小岛上
List<Prisoner> island = new ArrayList<>();
for(int i=0; i<blueNum; i++) {
island.add(new Prisoner(i+1,"蓝眼"));
}
for(int i=blueNum; i<num; i++) {
island.add(new Prisoner(i+1, "红眼"));
}
//医生告诉囚犯们至少有一个蓝眼人
int knowLestBN = 1;
//共识线索{已知至少有多少蓝眼人,实际蓝眼人数,获得线索的第几天}
int[] array = {knowLestBN,blueNum,1};
// 岛上的蓝眼囚犯开始推断
for(int i=0; i<island.size(); i++) {
island.get(i).reasoning(array);
if(i != island.size()-1) {
array = new int[] {knowLestBN,blueNum,1};
}
}
System.out.println(array[2] + "天后,所有的囚犯都被释放了");
}
}