陕西金源集团:爱因斯坦的问题___猜猜谁养鱼?

来源:百度文库 编辑:神马品牌网 时间:2024/05/04 05:30:52
有五个不同国籍的人,分别住五种不同颜色的房子,养五种不同的动物,抽五种不同牌子的烟喝五种不同的饮料.
提示:→
①:英国人住红房子②瑞士人养狗③丹麦人喝茶④绿房子在白房子左边⑤绿房子主人喝咖啡⑥抽DA烟的人养鸟⑦黄房子主人抽DU烟⑧住中间房子的人喝牛奶⑨挪威人住第一间房子⑩抽混合烟的人住在养猫人旁边⑾养马人住在抽DU烟的旁边⑿抽BL烟的人喝啤酒⒀德国人抽PR烟⒁挪威人在蓝房子旁边!问谁养鱼?
这是爱因斯坦出的一题,他说这题世界上只有2%的人能答出有98%人答不出,试试你的智商吧!
请大家把推理的过程写下好吗!

解法:
  利用数组和循环:
  用5个数组(数组名)表示5种属性,用1、2、3、4、5分别代替各种属性的具体取值
  数组的下标表示房间号,数组元素的取值表示某房间某属性的具体取值的代号
  房间号(即数组下标)也表示方位,房间号小的为左,大的为右,下标相邻即房间相邻

  房间 0 1 2 3 4

  国家 挪 德 瑞 英 丹 ---> a[5]
  颜色 绿 蓝 黄 红 白 ---> b[5]
  饮品 咖 水 奶 酒 茶 ---> c[5]
  香烟 blends prince dunhill blue pall ---> d[5]
  宠物 鱼 猫 狗 马 鸟 ---> e[5]

  取值 1 2 3 4 5 ---> 数组元素的取值

  条件化简:
  1 英---红 若a[i]=4,则b[i]=4
  2 瑞---狗 若a[i]=3,则e[i]=3
  3 丹---茶 若a[i]=5,则c[i]=5
  4 绿---在白左面 若b[i]=1,b[j]=5,则i<j
  5 绿---咖 若b[i]=1,则c[i]=1
  6 鸟---pall 若e[i]=5,则d[i]=5
  7 黄---dunhill 若b[i]=3,则d[i]=3
  8 中间房子---奶 c[2]=3
  9 挪---第1间房 a[0]=1
  10 猫---有blends邻居 若e[i]=2,则d[i-1]=1 ¦¦ d[i+1]=1
  11 马---有dunhill邻居 若e[i]=4,则d[i-1]=3 ¦¦ d[i+1]=3
  12 酒---blue 若c[i]=4,则d[i]=4
  13 德---prince 若a[i]=2,则d[i]=2
  14 挪---有蓝邻居 ==〉b[1]=2
  15 水---有blends邻居 若c[i]=2,则d[i-1]=1 ¦¦ d[i+1]=1

  C++源代码:

  //爱因斯坦难题
  //程序设计:万道濮
  //说明:此版本是完美版
  #include<iostream.h>

  int main()
  {
  cout<<endl;
  cout<<" * 爱因斯坦难题 * \n";
  cout<<" 程序设计开发:万道濮\n";
  cout<<" [2005.1.15]\n";
  cout<<"================================================================================";
  int a[5],b[5],c[5],d[5],e[5],t[120][5]; //定义所需数组
  int i,j,c1,c2,c3,c4,p1,p2,p3,p4,p5; //定义所需变量
  char cmd; //cmd用来暂存用户输入的命令
  int k; //k用来计数

  cout<<" 传说下面是爱因斯坦在20世纪初出的一道测试题。他说世界上有99%的人回答不出这道题,看看你是否属于另外的1%?题目如下:\n";
  cout<<"\n前提:\n";
  cout<<" 1 有五栋五种颜色的房子\n";
  cout<<" 2 每一位房子的主人国籍都不同\n";
  cout<<" 3 这五个人每人只喝一种饮料,只抽一种牌子的香烟,只养一种宠物 \n";
  cout<<" 4 没有人有相同的宠物,抽相同牌子的香烟,喝相同的饮料 \n";
  cout<<"条件:\n";
  cout<<" 1 英国人住在红房子里 \n";

  cout<<" 2 瑞典人养了一条狗 \n";
  cout<<" 3 丹麦人喝茶\n";
  cout<<" 4 绿房子在白房子左边 \n";
  cout<<" 5 绿房子主人喝咖啡 \n";
  cout<<" 6 抽PALL MALL烟的人养了一只鸟 \n";
  cout<<" 7 黄房子主人抽DUNHILL烟\n";
  cout<<" 8 住在中间那间房子的人喝牛奶 \n";
  cout<<" 9 挪威人住第一间房子 \n";
  cout<<" 10 抽BLENDS烟的人住在养猫人的旁边\n";
  cout<<" 11 养马人住在DUNHILL烟的人旁边 \n";
  cout<<" 12 抽BLUE MASTER烟的人喝啤酒\n";
  cout<<" 13 德国人抽PRINCE烟 \n";
  cout<<" 14 挪威人住在蓝房子旁边 \n";
  cout<<" 15 抽BLENDS烟的人的邻居喝矿泉水\n";
  cout<<"问题:谁养鱼?\n";
  cout<<"\n";
  sl: cout<<"输入“k”开始解答此难题,输入“q”退出程序:";
  cin>>cmd;
  cout<<endl;
  if(cmd=='q' ¦¦ cmd=='Q')
  return 0; //退出程序
  else if(cmd=='k' ¦¦ cmd=='K')
  goto key; //开始解答难题
  else goto sl;

  //先求1、2、3、4、5五个数字的所有排列情况
  //下面开始用排列组合的方法排列5个数字
  key:k=0; //k记录排列组合的种数
  p1=0; //初始化下面循环所需参数为0
  while(5-p1) //先放置数字1,数字1有5个位置可以选择
  {
  for(i=0;i<5;i++) //每次从下层循环回到此处都要先清空上次的排列
  a[i]=0;
  p1++; //p1记录数字1的当前放置次数
  for(i=0,c1=0;i<5;i++)
  if(a[i]==0) {c1++; if(c1==p1) {a[i]=1; i=5;}} //放置数字1

  p2=0; //初始化下面循环所需参数为0
  while(4-p2) //放置数字2,放置好数字1后,数字2有4个位置可以选择
  {
  for(i=0;i<5;i++) //每次从下层循环回到此处都要先清除上次排列中的2、3、4、5
  if(a[i]!=1) a[i]=0;
  p2++; //p2记录数字2的当前放置次数
  for(i=0,c2=0;i<5;i++)
  if(a[i]==0) {c2++; if(c2==p2) {a[i]=2; i=5;}}

  p3=0; //初始化下面循环所需参数为0
  while(3-p3) //放置数字3,放置好数字2后,数字3有3个位置可以选择
  {
  for(i=0;i<5;i++) //每次从下层循环回到此处都要先清除上次排列中的3、4、5
  if(a[i]==3 ¦¦ a[i]==4 ¦¦ a[i]==5) a[i]=0;
  p3++; //p3记录数字3的当前放置次数
  for(i=0,c3=0;i<5;i++)
  if(a[i]==0) {c3++; if(c3==p3) {a[i]=3;i=5;}}

  p4=0; //初始化下面循环所需参数为0
  while(2-p4) //放置数字4,放置好数字3后,数字4有2个位置可以选择
  {
  for(i=0;i<5;i++) //每次从下层循环回到此处都要先清除上次排列中的4、5
  if(a[i]==4 ¦¦ a[i]==5) a[i]=0;
  p4++; //p4记录数字4的当前放置次数
  for(i=0,c4=0;i<5;i++)
  if(a[i]==0) {c4++; if(c4==p4) {a[i]=4;i=5;}}

  for(i=0;i<5;i++) //放置数字5,放置好数字4后,只剩1个位置来放5,故不用循环
  if(a[i]==0) {a[i]=5;i=5;} //k记录排列组合的种数

  //五个数字的一种排列完成,将此排列记录在数组t[k][5]中
  for(i=0;i<5;i++)
  {t[k][i]=a[i];}
  k++; //k记录排列组合的种数
  }
  }
  }
  }
  //1、2、3、4、5五个数字的所有排列情况算完,都记录在数组t[][]中
  //下面开始用t[][]中的排列组合所有属性,并判断这种组合是否满足题意
  k=0; //k记录正确答案的个数
  p1=0;
  while(120-p1) //通过循环组合“国家”属性
  { //9 挪---第1间房 ==>a[0]=1
  if(t[p1][0]!=1) {p1++; continue;} //9 挪---第1间房 a[0]=1
  for(i=0;i<5;i++) {a[i]=t[p1][i];} //a[]放置上第p1种国家属性的排列
  p1++; //p1指向下一种排列情况

  p2=0;
  while(120-p2) //通过循环组合“颜色”属性
  { //14 挪---有蓝邻居 ==>b[1]=2
  if(t[p2][1]!=2) {p2++; continue;} //14 挪---有蓝邻居 ==〉b[1]=2
  for(i=0;i<5;i++) {b[i]=t[p2][i];} //
  p2++; //p1指向下一种排列情况

  p3=0;
  while(120-p3) //通过循环组合“饮品”属性
  { //8 中间房子---奶 ==>c[2]=3
  if(t[p3][2]!=3) {p3++; continue;} //8 中间房子---奶 c[2]=3
  for(i=0;i<5;i++) {c[i]=t[p3][i];} //
  p3++; //p1指向下一种排列情况

  p4=0;
  while(120-p4) //通过循环组合“香烟”属性
  {
  for(i=0;i<5;i++) {d[i]=t[p4][i];}
  p4++;

  p5=0;
  while(120-p5) //通过循环组合“宠物”属性
  {
  for(i=0;i<5;i++) {e[i]=t[p5][i];}
  p5++;

  /*测试
  cout<<" 房间 国家 颜色 饮品 香烟 宠物\n\n";
  for(i=0;i<5;i++)
  {
  cout<<" "<<i+1<<" "<<a[i]<<" "<<b[i]<<" "<<c[i]<<" "<<d[i]<<" "<<e[i]<<endl;
  }
  //return 0;
  //测试完毕*/

  //所有属性的一种组和完成,下面判断这种组合是否满足题意
  //若有一个条件不满足,就退出本次循环,并继续下次循环,即下一组组合

  //1 英---红 若a[i]=4,则b[i]=4
  for(i=0;i<5;i++)
  {if(a[i]==4) break;}
  if(b[i]!=4) continue; //退出本次循环,并继续下次循环,即下一组组合

  //2 瑞---狗 若a[i]=3,则e[i]=3
  for(i=0;i<5;i++)
  {if(a[i]==3) break;}
  if(e[i]!=3) continue; //退出本次循环,并继续下次循环,即下一组组合

  //3 丹---茶 若a[i]=5,则c[i]=5
  for(i=0;i<5;i++)
  {if(a[i]==5) break;}
  if(c[i]!=5) continue; //退出本次循环,并继续下次循环,即下一组组合

  //4 绿---在白左面 若b[i]=1,b[j]=5,则i<j
  for(i=0;i<5;i++)
  {if(b[i]==1) break;}
  for(j=0;j<5;j++)
  {if(a[j]==5) break;}
  if(i>=j) continue; //退出本次循环,并继续下次循环,即下一组组合

  //5 绿---咖 若b[i]=1,则c[i]=1
  for(i=0;i<5;i++)
  {if(b[i]==1) break;}
  if(c[i]!=1) continue;

  //6 鸟---pall 若e[i]=5,则d[i]=5
  for(i=0;i<5;i++)
  {if(e[i]==5) break;}
  if(d[i]!=5) continue;

  //7 黄---dunhill 若b[i]=3,则d[i]=3
  for(i=0;i<5;i++)
  {if(b[i]==3) break;}
  if(d[i]!=3) continue;

  //10 猫---有blends邻居 若e[i]=2,则d[i-1]=1 ¦¦ d[i+1]=1
  for(i=0;i<5;i++)
  {if(e[i]==2) break;}
  if(i==0) {if(d[i+1]!=1) continue;}
  if(i>0 && i<4) {if(d[i-1]!=1 && d[i+1]!=1) continue;}
  if(i==4) {if(d[i-1]!=1) continue;}

  //11 马---有dunhill邻居 若e[i]=4,则d[i-1]=3 ¦¦ d[i+1]=3
  for(i=0;i<5;i++)
  {if(e[i]==4) break;}
  if(i==0) {if(d[i+1]!=3) continue;}
  if(i>0 && i<4) {if(d[i-1]!=3 && d[i+1]!=3) continue;}
  if(i==4) {if(d[i-1]!=3) continue;}

  //12 酒---blue 若c[i]=4,则d[i]=4
  for(i=0;i<5;i++)
  {if(c[i]==4) break;}
  if(d[i]!=4) continue;

  //13 德---prince 若a[i]=2,则d[i]=2
  for(i=0;i<5;i++)
  {if(a[i]==2) break;}
  if(d[i]!=2) continue;

  //15 水---有blends邻居 若c[i]=2,则d[i-1]=1 ¦¦ d[i+1]=1
  for(i=0;i<5;i++)
  {if(c[i]==2) break;}
  if(i==0) {if(d[i+1]!=1) continue;}
  if(i>0 && i<4) {if(d[i-1]!=1 && d[i+1]!=1) continue;}
  if(i==4) {if(d[i-1]!=1) continue;}

  //所有条件都判断完毕,若程序执行到此而没有退出本次循环
  //说明此组合满足题意,是正确答案,下面就输出这种组合
  //输出答案后,继续判断下一种组合,看是否还有其他答案
  k++; //k记录正确答案的个数
  cout<<"\n————————爱因斯坦难题答案————————\n\n";
  //下面输出所问问题的答案
  cout<<" 第"<<k<<"种答案: ";
  for(i=0;i<5;i++) //寻找养鱼的人对应的数组元素
  {if(e[i]==1) break;}
  switch (a[i])
  {
  case 1: cout<<"挪威人养鱼\n\n";
  break;
  case 2: cout<<"德国人养鱼\n\n";
  break;
  case 3: cout<<"瑞士人养鱼\n\n";
  break;
  case 4: cout<<"英国人养鱼\n\n";
  break;
  case 5: cout<<"丹麦人养鱼\n\n";
  break;
  }//问题答案输出完毕
  cout<<" 左 <---|---> 右\n\n";
  cout<<" 房间 1 2 3 4 5\n\n";
  //输出答案的所有“国家”属性
  cout<<" 国家 ";
  for(i=0;i<5;i++)
  {
  switch (a[i])
  {
  case 1: cout<<"挪威 ";
  break;
  case 2: cout<<"德国 ";
  break;
  case 3: cout<<"瑞士 ";
  break;
  case 4: cout<<"英国 ";
  break;
  case 5: cout<<"丹麦 ";
  break;
  }
  }
  cout<<"\n\n"; //换行
  //输出答案的所有“颜色”属性
  cout<<" 颜色 ";
  for(i=0;i<5;i++)
  {
  switch (b[i])
  {
  case 1: cout<<"绿色 ";
  break;
  case 2: cout<<"蓝色 ";
  break;
  case 3: cout<<"黄色 ";
  break;
  case 4: cout<<"红色 ";
  break;
  case 5: cout<<"白色 ";
  break;
  }
  }
  cout<<"\n\n"; //换行
  //输出答案的所有“饮品”属性
  cout<<" 饮品 ";
  for(i=0;i<5;i++)
  {
  switch (c[i])
  {
  case 1: cout<<"咖啡 ";
  break;
  case 2: cout<<"泉水 ";
  break;
  case 3: cout<<"牛奶 ";
  break;
  case 4: cout<<"啤酒 ";
  break;
  case 5: cout<<"绿茶 ";
  break;
  }
  }
  cout<<"\n\n"; //换行
  //输出答案的所有“香烟”属性
  cout<<" 香烟 ";
  for(i=0;i<5;i++)
  {
  switch (d[i])
  {
  case 1: cout<<"blends ";
  break;
  case 2: cout<<"prince ";
  break;
  case 3: cout<<"dunhill ";
  break;
  case 4: cout<<"blue ";
  break;
  case 5: cout<<"pall ";
  break;
  }
  }
  cout<<"\n\n"; //换行
  //输出答案的所有“宠物”属性
  cout<<" 宠物 ";
  for(i=0;i<5;i++)
  {
  switch (e[i])
  {
  case 1: cout<<"鱼 ";
  break;
  case 2: cout<<"猫 ";
  break;
  case 3: cout<<"狗 ";
  break;
  case 4: cout<<"马 ";
  break;
  case 5: cout<<"鸟 ";
  break;
  }
  }//答案的所有属性输出完毕
  cout<<"\n\n"; //换行
  }//通过循环组合“宠物”属性的循环完毕
  }//通过循环组合“香烟”属性的循环完毕
  }//通过循环组合“饮品”属性的循环完毕
  }//通过循环组合“颜色”属性的循环完毕
  }//通过循环组合“国家”属性的循环完毕
  cout<<endl;
  cout<<"====================计算完毕===================\n\n";
  cout<<" 一共有以上 "<<k<<"种正确答案\n\n";
  cout<<"================程序设计:万道濮===============\n\n";
  s2: cout<<"输入“r”重新解答此难题,输入“q”退出程序:";
  cin>>cmd;
  cout<<endl;
  if(cmd=='q' ¦¦ cmd=='Q')
  return 0; //正常退出程序
  else if(cmd=='r' ¦¦ cmd=='R')
  goto key; //重新解答难题
  else goto s2;
  }//主程序main()结束

  最后答案:
  正确答案一共有六个。

挪威人或德国人养鱼

坦白:自己不会回答,很惊讶楼上的解题思路。渴望答案。

德国人养鱼