| 网站首页 | 生物 | 医学 | 药学 | 产业 | 健康 | 考试 | 实验 | 图库 | 科普 | 人才 | 服务 | 论坛 | 热点调用 | 
您现在的位置: 生物谷 >> 科普 >> 科普文库 >> 科普频道正文 用户登录 新用户注册

爱因斯坦难题C++解法

作者:佚名    科普频道来源:本站原创    点击数:    更新时间:2005-2-21 我要评论
爱因斯坦难题C++解法
 

爱因斯坦的难题

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

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

解法:
利用数组和循环:
用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()结束

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

我要搜索


热门查询
金字塔之迷 UFO揭密 恐龙
玛雅文明 外星人 史前文明
黑洞 爱因斯坦 暗物质
环保之窗 诺贝尔奖
珍稀动物 google

 

评论】 【进论坛看】【转入博客】【收藏入VIVI】 【收藏到365key

科普频道录入:admin    责任编辑:admin 

  • 上一篇科普频道:

  • 下一篇科普频道:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口

    相关文章

    最新热门

    推荐文章

    德国现存惟一爱因斯坦住过的
    爱因斯坦(Einstein,Hans Alb
    爱因斯坦(Einstein,Albert)(
    爱因斯坦在相对论公开初期所
    《大科技》:爱因斯坦最后的
    抱怨爱因斯坦吧 50周年后你的
    爱因斯坦逝世五十周年:神话
    难以逾越的智慧高峰 今天为何
    爱因斯坦:后人很难逾越的智慧
    爱因斯坦4月19日晚“光”临中
    · 专题:黑洞与霍金
    · 玛雅文明之谜(1)
    · 澄江动物群证实 几乎所有动物并非演
    · 探秘世界7大谜团(图)
    · 神州5号拍摄的中国版图,令人震惊
    · 十大奇异罕见的世界天文奇观(全部为
    · 外星人图片集(模拟)
    · 发现之旅:阿尔泰山荒原通天石人之
    · 澳洲史前岩画留下谜团 地球上疑曾有
    · 科学家发现隐身类星体 宇宙中遍布黑
    · 数学趣闻集粹
    · 100个著名初等数学问题
    · 56个民族的像徽
    · 生物谷2004科技新闻综述:宇宙探索
    · 毁灭的古印度文明
    · 玛雅文明的秘密
    · 最远古的足迹---史前人类?
    · 恐龙美图集锦
    · 目前出现的UFO图片集(1)
    · 月球是外星人制造的?
    文章评论 (只显示最新10条。评论内容只代表网友观点,与本站立场无关!)