爱因斯坦难题C++解法

原文地址:爱因斯坦难题C++解法 作者:虚空使者
 

爱因斯坦难题C++解法

传说下面是爱因斯坦在20世纪初出的一道测试题。他说世界上有99%的人回答不出这道题,
看看你是否属于另外的1%?题目如下:

前提: 
有五栋五种颜色的房子 
每一位房子的主人国籍都不同 
这五个人每人只喝一种饮料,只抽一种牌子的香烟,只养一种宠物 
没有人有相同的宠物,抽相同牌子的香烟,喝相同的饮料 
条件: 
英国人住在红房子里 
瑞典人养了一条狗 
丹麦人喝茶 
绿房子在白房子左边 
绿房子主人喝咖啡 
抽PALL MALL烟的人养了一只鸟 
黄房子主人抽DUNHILL烟 
住在中间那间房子的人喝牛奶 
挪威人住第一间房子 
10 抽BLENDS烟的人住在养猫人的旁边 
11 养马人住在DUNHILL烟的人旁边 
12 抽BLUE MASTER烟的人喝啤酒 
13 德国人抽PRINCE烟 
14 挪威人住在蓝房子旁边 
15 抽BLENDS烟的人的邻居喝矿泉水 
问题:谁养鱼? 

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

房间                                 4

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

取值                                5 ---> 数组元素的取值

条件化简:
英---红 若a[i]=4,则b[i]=4
瑞---狗 若a[i]=3,则e[i]=3
丹---茶 若a[i]=5,则c[i]=5
绿---在白左面若b[i]=1,b[j]=5,则i<j
绿---咖 若b[i]=1,则c[i]=1
鸟---pall 若e[i]=5,则d[i]=5
黄---dunhill 若b[i]=3,则d[i]=3
中间房子---奶 c[2]=3
挪---第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<<"                             程序设计开发:NBn";
cout<<"                                 [3003.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<<"    有五栋五种颜色的房子n";
cout<<"    每一位房子的主人国籍都不同n";
cout<<"    这五个人每人只喝一种饮料,只抽一种牌子的香烟,只养一种宠物 n";
cout<<"    没有人有相同的宠物,抽相同牌子的香烟,喝相同的饮料 n";
cout<<"条件:n";
cout<<"    英国人住在红房子里 n";

cout<<"    瑞典人养了一条狗 n";
cout<<"    丹麦人喝茶n";
cout<<"    绿房子在白房子左边 n";
cout<<"    绿房子主人喝咖啡 n";
cout<<"    抽PALL MALL烟的人养了一只鸟 n";
cout<<"    黄房子主人抽DUNHILL烟n";
cout<<"    住在中间那间房子的人喝牛奶 n";
cout<<"    挪威人住第一间房子 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++;



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

//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————————爱因斯坦难题答案————————nn";
//下面输出所问问题的答案
cout<<"             第"<<k<<"种答案:  ";
for(i=0;i<5;i++) //寻找养鱼的人对应的数组元素
{if(e[i]==1) break;}
switch (a[i])
{
case 1: cout<<"挪威人养鱼nn";
break;
case 2: cout<<"德国人养鱼nn";
break;
case 3: cout<<"瑞士人养鱼nn";
break;
case 4: cout<<"英国人养鱼nn";
break;
case 5: cout<<"丹麦人养鱼nn";
break;
}//问题答案输出完毕
cout<<"                左 <---|---> 右nn";
cout<<"  房间      1      2      3      4      5nn";
//输出答案的所有“国家”属性
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<<"nn"; //换行
//输出答案的所有“颜色”属性
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<<"nn"; //换行
//输出答案的所有“饮品”属性
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<<"nn"; //换行
//输出答案的所有“香烟”属性
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<<"nn"; //换行
//输出答案的所有“宠物”属性
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<<"nn"; //换行
}//通过循环组合“宠物”属性的循环完毕
}//通过循环组合“香烟”属性的循环完毕
}//通过循环组合“饮品”属性的循环完毕
}//通过循环组合“颜色”属性的循环完毕
}//通过循环组合“国家”属性的循环完毕
cout<<endl;
cout<<"====================计算完毕===================nn";
cout<<"             一共有以上 "<<k<<"种正确答案nn";
cout<<"================程序设计:万道濮===============nn";
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()结束

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值