`
jsltool
  • 浏览: 23387 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
文章分类
社区版块
存档分类
最新评论

《爱因斯坦的问题》解答

阅读更多

看到这样一个问题,题目就叫《爱因斯坦的问题》,光看题目就很有意思,打开后看了问题内容,第一反应是“晕”,而后在纸上画了画,大体理清了思路,不过实在是懒得算,就准备写个程序来帮忙。

首先把问题的内容贴出来:

爱因斯坦的超级问题
1、在一条街上,有5座房子,喷了5种颜色。
2、每个房里住着不同国籍的人
3、每个人喝不同的饮料,抽不同品牌的香烟,养不同的宠物
问题是:谁养鱼?
提示:
1、英国人住红色房子
2、瑞典人养狗
3、丹麦人喝茶
4、绿色房子在白色房子左面
5、绿色房子主人喝咖啡
6、抽PallMall香烟的人养鸟
7、黄色房子主人抽Dunhill香烟
8、住在中间房子的人喝牛奶
9、挪威人住第一间房
10、抽Blends香烟的人住在养猫的人隔壁
11、养马的人住抽Dunhill香烟的人隔壁
12、抽BlueMaster的人喝啤酒
13、德国人抽Prince香烟
14、挪威人住蓝色房子隔壁
15、抽Blends香烟的人有一个喝水的邻居

 通过程序解这种题,第一个反应是穷举法。现在先算算穷举法有多少种组合。一条街,包含5间有序的房屋,每间房屋有五个互不相同的属性:国籍、颜色、宠物、饮料和香烟。因为5间房屋相同类型的属性都不一样,所以每个属性都有5!=120种组合,5种属性加起来,共有120^5=24883200000种!接近250亿了。

直接穷举这么多种情况,显得很不合适,所以在使用穷举法的时候,不要等把一种组合确定下来之后再去判断是否符合条件,而是在组合中的一部分属性确定下来后马上做判断,这样会快很多。

本来想把房屋和街道抽象成java类,但是感觉有点兴师动众,所以就只写了一个类,以解决问题为主。下面直接上代码。

import java.util.ArrayList;

public class Einstein {
	private static final String[] MEN = { "挪威", "瑞典", "英国", "丹麦", "德国" };
	private static final int NORWAY = 0;
	private static final int SWEDEN = 1;
	private static final int ENGLAND = 2;
	private static final int DENMARK = 3;
	private static final int GERMANY = 4;
	// ================================================================
	private static final String[] PET = { "狗", "鸟", "马", "猫", "鱼" };
	private static final int DOG = 0;
	private static final int BIRD = 1;
	private static final int HORSE = 2;
	private static final int CAT = 3;
	private static final int FISH = 4;
	// ================================================================
	private static final String[] COL = { "蓝色", "红色", "黄色", "白色", "绿色" };
	private static final int BLUE = 0;
	private static final int RED = 1;
	private static final int YELLOW = 2;
	private static final int WHITE = 3;
	private static final int GREEN = 4;
	// ================================================================
	private static final String[] WIN = { "牛奶", "咖啡", "啤酒", "水", "茶" };
	private static final int MILK = 0;
	private static final int COFFE = 1;
	private static final int BEER = 2;
	private static final int WHAT = 3;
	private static final int TEE = 4;

	// ================================================================
	private static final String[] SMO = { "PallMall", "Dunhill", "BlueMaster",
			"Prince", "Blends" };
	private static final int PM = 0;
	private static final int DH = 1;
	private static final int BM = 2;
	private static final int P = 3;
	private static final int B = 4;

	// ================================================================
	private static final ArrayList<int[]> list = new ArrayList<int[]>(120);

	public static void main(String[] args) {
		// 先生成0-4的全排列。算法很笨,但是很有效。
		for (int i1 = 0; i1 < 5; i1++) {
			for (int i2 = 0; i2 < 5; i2++) {
				if (i2 == i1) {
					continue;
				}
				for (int i3 = 0; i3 < 5; i3++) {
					if (i3 == i1 || i2 == i1 || i2 == i3) {
						continue;
					}
					for (int i4 = 0; i4 < 5; i4++) {
						if (i3 == i1 || i2 == i1 || i4 == i1 || i3 == i4
								|| i3 == i2 || i2 == i4) {
							continue;
						}
						int[] arr = new int[] { i1, i2, i3, i4,
								(10 - i1 - i2 - i3 - i4) };
						list.add(arr);
					}
				}
			}
		}
		getM();
	}

	/**
	 * 国籍的全排列
	 */
	private static final void getM() {
		long begin = System.nanoTime();
		// 开始
		for (int[] men : list) {
			if (men[0] != NORWAY) {
				// 9、挪威人住第一间房
				continue;
			}
			getC(men);
		}
		System.out.println("耗时:" + (System.nanoTime() - begin) + "纳秒。");
	}

	/**
	 * 颜色的全排列
	 */
	private static void getC(int[] men) {
		out: for (int[] color : list) {
			if (color[1] != BLUE || color[4] == GREEN) {
				// 14、挪威人住蓝色房子隔壁
				// 所以,左起第二间房屋一定是蓝色色的
				// 4、绿色房子在白色房子左面
				// 所以,最右边的房屋一定不是绿色的
				continue;
			}
			for (int i = 0; i < 4; i++) {
				if (color[i] == GREEN && color[i + 1] != WHITE) {
					// 4、绿色房子在白色房子左面
					continue out;
				}
			}
			for (int i = 0; i < 5; i++) {
				if (men[i] == ENGLAND && color[i] != RED) {
					// 1、英国人住红色房子
					continue out;
				}
			}
			getP(men, color);
		}
	}

	/**
	 * 宠物的全排列
	 */
	private static void getP(int[] men, int[] color) {
		out: for (int[] pet : list) {
			for (int i = 0; i < 5; i++) {
				if (men[i] == SWEDEN && pet[i] != DOG) {
					// 2、瑞典人养狗
					continue out;
				}
			}
			getW(men, color, pet);
		}
	}

	/**
	 * 饮料的全排列
	 */
	private static void getW(int[] men, int[] color, int[] pet) {
		out: for (int[] win : list) {
			if (win[2] != MILK) {
				// 8、住在中间房子的人喝牛奶
				continue;
			}
			for (int i = 0; i < 5; i++) {
				if (men[i] == DENMARK && win[i] != TEE) {
					// /3、丹麦人喝茶
					continue out;
				}
			}
			for (int i = 0; i < 5; i++) {
				if (color[i] == GREEN && win[i] != COFFE) {
					// 5、绿色房子主人喝咖啡
					continue out;
				}
			}
			getS(men, color, pet, win);
		}
	}

	/**
	 * 香烟的全排列
	 */
	private static void getS(int[] men, int[] color, int[] pet, int[] win) {
		out: for (int[] smo : list) {
			for (int i = 0; i < 5; i++) {
				if (pet[i] == BIRD && smo[i] != PM) {
					// 6、抽PallMall香烟的人养鸟
					continue out;
				}
			}
			for (int i = 0; i < 5; i++) {
				if (color[i] == YELLOW && smo[i] != DH) {
					// 7、黄色房子主人抽Dunhill香烟
					continue out;
				}
			}
			for (int i = 0; i < 5; i++) {
				if (win[i] == BEER && smo[i] != BM) {
					// /12、抽BlueMaster的人喝啤酒
					continue out;
				}
			}
			for (int i = 0; i < 5; i++) {
				int man = men[i];
				if (man == GERMANY && smo[i] != P) {
					// 13、德国人抽Prince香烟
					continue out;
				}
			}

			boolean b = true;
			for (int i = 0; i < 4; i++) {
				if ((smo[i] == B && pet[i + 1] == CAT)
						|| (smo[i + 1] == B && pet[i] == CAT)) {
					// 10、抽Blends香烟的人住在养猫的人隔壁
					b = false;
					break;
				}
			}
			if (b) {
				continue;
			}

			b = true;
			for (int i = 0; i < 4; i++) {
				if ((smo[i] == B && win[i + 1] == WHAT)
						|| (smo[i + 1] == B && win[i] == WHAT)) {
					// 15、抽Blends香烟的人有一个喝水的邻居
					b = false;
					break;
				}
			}
			if (b) {
				continue;
			}

			b = true;
			for (int i = 0; i < 4; i++) {
				if ((smo[i] == DH && pet[i + 1] == HORSE)
						|| (smo[i + 1] == DH && pet[i] == HORSE)) {
					// 11、养马的人住抽Dunhill香烟的人隔壁
					b = false;
					break;
				}
			}
			if (b) {
				continue;
			}
			int[][] old = new int[][] { men, color, pet, win, smo };
			print(old);
		}
	}

	/**
	 * 打印结果
	 */
	private static final void print(int[][] old) {
		int[][] arr = new int[5][5];
		// 转置
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				arr[j][i] = old[i][j];
			}
		}
		StringBuilder sb = new StringBuilder("房屋位置\t国籍\t房子颜色\t宠物\t饮料\t香烟");
		for (int i = 0; i < arr.length; i++) {
			sb.append("\n左起").append(i + 1);
			sb.append("\t").append(MEN[arr[i][0]]);
			sb.append("\t").append(COL[arr[i][1]]);
			sb.append("\t").append(PET[arr[i][2]]);
			sb.append("\t").append(WIN[arr[i][3]]);
			sb.append("\t").append(SMO[arr[i][4]]);
		}
		sb.append("\n============================");
		System.out.println(sb);
	}
}

 在MyEclipse中的运行结果:



 

  • 大小: 13 KB
分享到:
评论
1 楼 xlaohe1 2012-03-02  
   
佩服啊

相关推荐

    爱因斯坦谜题解答(三种算法比较).doc

    爱因斯坦谜题解答(三种算法比较).doc

    爱因斯坦难题解析(90%的语句都赋予注释)

    爱因斯坦难题,又被称为“酒吧问题”或“爱因斯坦的五人难题”,涉及到了逻辑推理、概率和条件关系。问题背景设定在一个虚构的小镇上,包含五个关键角色:一个警察、一位医生、一个囚犯、一位间谍和一位酒保,以及...

    【爱因斯坦】思考喜欢的问题

    为了解答这个问题,我们可以尝试填写部分信息: - 根据第9条线索,挪威人住在最左边的房间,那么这个房间既不是绿色也不是白色。 - 根据第4条线索,绿色房间位于白色房间的左边,那么挪威人的房间只能是除了绿白两色...

    爱因斯坦-五色房子-三种解答(python-PyCharm版)

    标题中的“爱因斯坦-...总的来说,通过这个“爱因斯坦五色房子”的问题,我们可以学习到Python编程基础,PyCharm的使用技巧,以及如何用编程思维解决逻辑问题。这不仅有助于提升编程技能,也有助于培养逻辑推理能力。

    [狭义相对论基础问题解答] 光速问题

    ### 狭义相对论中的光速问题解析 #### 光速的概念与测量 光速不仅仅代表光在真空中传播的速度,它还是信息传递速度的极限。这一概念将时间与空间紧密相连,并确保了事件发生的顺序。历史上,人们最初认为光速是...

    爱因斯坦和艺术教(学)案.doc

    巩固训练环节,通过问题解答,让学生深入理解科学与艺术的关联,以及爱因斯坦的独特见解。 【反思与应用】 在深入理解爱因斯坦与艺术的关联后,学生们被引导思考为何我国未能培养出类似爱因斯坦的科学家,这涉及到...

    Solutions_to_Problems_in_Cosmology.pdf

    ### 宇宙学问题解答集概述 文件标题《Solutions_to_Problems_in_Cosmology.pdf》表明这是一个关于宇宙学问题解答的文档。文档描述表明它是第二版《Physical Foundations of Cosmology》由 V. Mukhanov 所著书中第一...

    从爱因斯坦到霍金的宇宙课后习题答案简版.docx

    下面是对每个问题的解答和相关知识点的详细解释: 1.11 相对论是关于()的基本理论,分为狭义相对论和广义相对论。 答案:A 时空和引力 知识点:相对论是阿尔伯特·爱因斯坦于1905年提出的一个物理理论,它分为...

    最终解答.docx

    这个问题的解答涉及到多个知识点: 1. **光速限制**:光速是宇宙中的最大速度,约为每秒300,000公里。这一限制是相对论的一部分,由阿尔伯特·爱因斯坦在1905年的狭义相对论中提出。光没有质量,因此能够达到这个...

    美国物理试题与解答 第7卷 相对论、固体物理及其它

    狭义相对论由爱因斯坦于1905年提出,其核心概念包括: 1. **光速不变原理**:在所有惯性参照系中,光速保持恒定,不受光源运动状态影响。 2. **相对性原理**:物理定律的形式在所有惯性参照系中都是相同的。 3. **...

    洛伦兹一爱因斯坦质量公式的完备化及其验证与应用 (2008年)

    新方程体现了狭义相对论与测不准原理的融合,它揭示质量概念具有更丰富的内涵,有助于深入认识某些物理现象的本质并解答若干疑难问题(例如,超高能宇宙线的GzK截断悖论、哈勃常数的理论计算和狄拉克大数问题等)。...

    周世勋 量子力学习题解答

    这本书旨在帮助学生理解和掌握量子力学的基本概念、原理和计算方法,通过解答习题来巩固理论知识,提升解决问题的能力。 量子力学是20世纪初发展起来的物理学分支,它描述微观粒子如电子、质子、中子以及原子和分子...

    热力学统计物理 第四版 汪志诚 习题解答(很清晰)

    《热力学统计物理》是物理学领域的一本经典教材...这些章节的习题解答有助于学生巩固和深化对热力学和统计物理理论的理解,通过解决实际问题,提高分析和解决问题的能力。这些清晰的解答对于自学或复习都是极好的资源。

    结构化学习题解答3(北大)

    【结构化学习题解答3(北大)】 这篇内容主要涉及了结构化学的基础知识,包括光电子的速度计算、粒子的波粒二象性、量子力学中的本征值问题以及一维势箱中的粒子能量计算。以下是这些知识点的详细解析: 1. **光...

    如何凝练科学问题 如何提升创新能力基础医学院PPT课件.pptx

    科学问题是科学研究的基石,它在已有的科学知识框架内提出了尚待解答的疑点。科学问题不仅是研究的出发点,更是推动科学发展的关键驱动力。重大科学突破往往源于对某一科学问题的精准提炼。正如爱因斯坦曾言,提出新...

    在信息技术教学中培养学生的“问题意识”.doc

    问题意识是指在面对实际或理论问题时,个体能意识到存在的疑问,产生怀疑、困惑、焦虑,并积极寻求解答的心理状态。在信息技术学科中,问题通常不是寻找固定答案,而是需要解决实际问题,这就更加突出了培养问题意识...

    固体物理学习题解答(王矜奉)

    - **平均声子数:**对于频率为\(\omega\)的格波,其平均声子数可以通过玻色-爱因斯坦分布函数计算得出。\(\langle n(\omega) \rangle = \frac{1}{e^{\hbar\omega/(k_BT)} - 1}\),其中\(\hbar\)是约化普朗克常数,\...

    强化问题意识,培养学生创新思维能力.pdf

    教师的角色在于引导学生敢于质疑、善于解疑、乐于分析,使他们在不断的疑问和解答中提升创新能力。 激疑启发是一种有效的教学策略,通过激发学生的疑问,促使他们产生问题意识。陶行知先生和爱因斯坦的名言都强调了...

    福建省泉州东湖中学七年级语文下册 第8课《少年爱因斯坦》同步练习 语文版

    【知识点】 1. 课程内容:此文档是一个针对七年级学生的语文同步练习,...综上所述,这篇练习涵盖了人物传记阅读、词汇学习、问题解答、人物分析和主题探讨等多个语文学习的重要方面,旨在全面锻炼学生的语文素养。

    美国物理试题与解答 第5卷 热力学与统计物理学

    《美国物理试题与解答 第5卷 热力学与统计物理学》是一本专注于这两个核心物理领域的教材或参考资料。热力学是研究能量转换、物质状态变化及其与温度、压力和体积关系的科学,而统计物理学则是从微观粒子行为角度对...

Global site tag (gtag.js) - Google Analytics