智力题-囚徒问题之一

一、题目

 100 prisoners are lined up and a black or white hat is to be placed on each of their heads. The prisoners cannot see the color of the hat on their own head, but they can see the colors of all the hats in front of them.

 A guard is going to walk down the line, starting in the back, and ask each prisoner what color hat they have on. They can only answer “black” or “white.” If they answer incorrectly, or say anything else, they will be shot dead on the spot. If they answer correctly, they will be set free. Each prisoner can hear all of the other prisoners’ responses, as well as any gunshots that indicate an incorrect response. They can remember all of this information.

 Before the executions begin, the prisoners get to huddle up and make a plan. How can the prisoners ensure that the most people possible survive?

一、中文题目:

  100名囚犯被排成一列,每个人头上都要戴上一顶黑色或白色的帽子。囚犯们看不到自己头上帽子的颜色,但是他们可以看到他们面前所有帽子的颜色。
  一个警卫从后面开始沿着队伍走,问每个囚犯戴着什么颜色的帽子。他们只能回答“黑”或“白”。如果他们回答错了,或者说了别的什么,他们就会被当场击毙。如果他们回答正确,他们将被释放。每个囚犯都能听到其他所有囚犯的反应,以及任何表明错误反应的枪声。他们可以记住所有这些信息。
  在处决开始之前,囚犯们挤在一起制定计划。囚犯们怎样才能确保尽可能多的人存活下来?

二、解题思路

  1. 最后一个人如果看到奇数顶帽子报“黑”;否则报“白”,他可能死;
  2. 从倒数第二人开始,就有两个信息:记住的值与看到的值,相同报“白”,不同报“黑”。
    此方案下,囚犯们的存活率是:99人能100%活,1人50%能活

三、用代码验证结论

1)先创建一个分配方案类,代码如下:

package math_puzzles;

public class solution {
    public int[] indi;
    public boolean[] survive;

	public int[] getIndi() {
		return indi;
	}

	public void setIndi(int[] indi) {
		this.indi = indi;
	}

	public boolean[] getSurvive() {
		return survive;
	}

	public void setSurvive(boolean[] survive) {
		this.survive = survive;
	}

	public solution() {
		// TODO Auto-generated constructor stub
	}

}

2)做100次实验验证提出的方案能否达到以下目标:99人能100%活,1人50%能活

package math_puzzles;
import java.lang.Math; //导入Random类bai
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import math_puzzles.solution;

public class prisoner_problem {
	public static final int LEN = 100;
	
	/*随机初始化一个序列,0与1的概率都为0.5
	 * int[] indi	:	代表囚徒帽子颜色序列
	 * */
	public static void generateChrome(int[] indi) {
		for(int i = 0;i < LEN;i++)
			//此处的0.5是个参数,可以调参;随机数生成方式可以采用动态分布等生成,此处为了方便采用了java中Math提供的随机数生成方式
			if(Math.random() > 0.5)							
				indi[i] = 1;		
	}
	
	/*统计end之前,黑帽子的数量
	 * int[] indi	:	100个囚徒所戴帽子颜色序列
	 * int end		:	要统计end之前黑色帽子的量
	 * */
	public static int getBlackHatNum(int[] indi,int end) {
		//记录下1的数目
		int num = 0;
		for(int i = 0;i < end;i++)
			num += indi[i];
		
		return end - num;
	}	
	
	/*	初始化解:
	 * solution s	:	要生成的解
	 * 为了确保尽可能多的人存活下来,囚犯们制定的计划:
	 * 	1、 最后一名囚犯计算前面所有黑帽子的个数,如果是奇数个,就猜黑,如果是偶数个,就猜白。
		2、其他人记住这个值(实际是黑帽奇偶数),在此之后当再听到黑时,取反一次
		3、从倒数第二人开始,就有两个信息:记住的值与看到的值,相同报“白”,不同报“黑”
			99人能100%活,1人50%能活 
	 * 
	 * */
	
	public static void run(solution s) {
		boolean survive[] = new boolean[LEN];
		
		// TODO Auto-generated method stub
		/*1.生成一个大小为100,内容为1或0的数组,
	    						1	:	白帽;
	    						0	:	黑帽。
		  */		
		int indi[] = new int[LEN];
		int res[] = new int[LEN];
		generateChrome(indi);		

		s.setIndi(indi);
		boolean flag = true;							//看到的值标记,奇数为 true,偶数为 false
		//2. 最后一名囚犯计算前面所有黑帽子的个数,如果是奇数个,就猜黑,如果是偶数个,就猜白。
		int tmp = LEN - 1;
		flag = getBlackHatNum(indi,tmp) % 2 == 1 ? true : false;
		if(flag) 					//如果是奇数个,就猜黑,如果是偶数个,就猜白。
			res[tmp] = 0;
		else
			res[tmp] = 1;	
		survive[tmp] = indi[tmp] != res[tmp] ? false : true;
		
		
		//3.从倒数第二人开始,就有两个信息:记住的值与看到的值,相同报“白”,不同报“黑”
		boolean preFlag = flag;							//记住的值标记
		for(int i = LEN - 2;i >= 0;i--) {
			flag =  getBlackHatNum(indi,i) % 2 == 1 ? true : false;
			if(flag == preFlag)
				res[i] = 1; 						//记住的值与看到的值,相同报“白”
			else
				res[i] = 0;							//不同报“黑”
			preFlag = flag;
		}		
		
		//survive数组记录下哪个囚徒会死
		for(int i = 0;i < LEN - 1;i++) 
			if(indi[i] != res[i])
				survive[i] = false;
			else
				survive[i] = true;
		s.setSurvive(survive);
	}
	

	/*验证run_time(此处为:100)次实验中,囚徒的生还率是不是:99人能100%活,1人50%能活 
	 * */
	public static void main(String[] args) {
		int run_time = 100;
		ArrayList<solution> list = new ArrayList<solution>();
		for(int i = 0;i < run_time;i++) {
			solution s = new solution();
			run(s);
			list.add(s);
		}
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for(int i = 0;i < LEN;i++) {
			int count = 0;
			for(int j = 0;j < run_time;j++) {
				if(list.get(j).survive[i])
					count++;
			}
			
			if(map.containsKey(count)){
				int value = map.get(count);
				value = value + 1;
				map.put(count, value);
			}else{
				map.put(count, 1);
            }			
		}
		
		for(Map.Entry<Integer, Integer> entry : map.entrySet()){
			int key = entry.getKey();
			int value = entry.getValue();      
			System.out.println("此方案下,囚犯们的存活率是:" + value + "人能" + key + "%活");
		}		

	}

}

四、结论

  针对此问题,提出的方案,能够实现“99人能100%活,1人50%能活”的目标。所以,提出的算法是真实的、有效的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来进行一道综合练习。 假设我们正在设计一个游戏,游戏中有多种角色,每种角色都有自己的属性和行为。我们来考虑如何使用Java继承和多态来实现这个游戏。 首先,我们可以定义一个抽象类`Character`,表示所有角色的基类,其中包含角色的基本属性和方法: ```java public abstract class Character { protected String name; // 角色名 protected int level; // 等级 protected int health; // 生命值 protected int mana; // 法力值 public Character(String name, int level, int health, int mana) { this.name = name; this.level = level; this.health = health; this.mana = mana; } public abstract void attack(); // 攻击方法 public abstract void defend(); // 防御方法 // getter和setter方法 // ... } ``` 然后,我们可以定义具体的角色类,例如战士`Warrior`和法师`Mage`,它们分别继承自`Character`类,并实现自己的攻击和防御方法: ```java public class Warrior extends Character { private int strength; // 力量属性 public Warrior(String name, int level, int health, int mana, int strength) { super(name, level, health, mana); this.strength = strength; } @Override public void attack() { System.out.println("战士" + name + "使用大剑攻击敌人!"); } @Override public void defend() { System.out.println("战士" + name + "使用盾牌防御敌人的攻击!"); } // getter和setter方法 // ... } public class Mage extends Character { private int intelligence; // 智力属性 public Mage(String name, int level, int health, int mana, int intelligence) { super(name, level, health, mana); this.intelligence = intelligence; } @Override public void attack() { System.out.println("法师" + name + "释放火球术攻击敌人!"); } @Override public void defend() { System.out.println("法师" + name + "使用魔法盾防御敌人的攻击!"); } // getter和setter方法 // ... } ``` 最后,我们可以在游戏中创建不同的角色对象,并进行攻击和防御操作: ```java public class Game { public static void main(String[] args) { Character warrior = new Warrior("张三", 10, 100, 50, 20); Character mage = new Mage("李四", 10, 80, 100, 30); warrior.attack(); mage.defend(); } } ``` 以上就是一个简单的继承和多态的综合练习,通过这个例子,我们可以发现继承和多态能够很好地实现代码的复用和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值