--------------第1组解如下--------------------
第1户: 挪威人 黄房子 喝水 养猫 抽Dunhill
第2户: 丹麦人 蓝房子 喝茶 养马 抽Blends
第3户: 英国人 红房子 喝牛奶 养鸟 抽Pall Mall
第4户: 德国人 绿房子 喝咖啡 养鱼 抽Prince
第5户: 瑞典人 白房子 喝啤酒 养狗 抽BlueMaster
=============================================
Press any key to continue
这样一来,唯一的结论就是:德国人养鱼。
----------------解决方案--------------------------------------------------------
/*------------------------------
爱因斯坦逻辑推理难题
C语言程序设计完美版
-------------------------------*/
#include<stdio.h>
#include<math.h>
char guoji[]={1/*挪威人住1号房*/,2,3,4,5},
color[]={2/*蓝房子是2号房*/,1,3,4,5},
drink[]={3/*喝牛奶者3号房*/,1,2,4,5},
pads[ ]={1,2,3,4,5},
smoke[]={1,2,3,4,5},
*aa[5]={guoji,color,drink,pads,smoke},
*msg[]={"挪威人", "英国人", "瑞典人", "德国人", "丹麦人",
"蓝房子", "黄房子", "绿房子", "红房子", "白房子",
"喝牛奶", "喝咖啡", "喝啤酒", "喝茶 ", "喝水 ",
"养猫", "养狗", "养马", "养鸟", "养鱼" ,
"抽Blends","抽BlueMaster","抽Dunhill","抽Pall Mall","抽Prince"};
int OK(void)
{
if( (color[1]==smoke[2]) //住黄房者 抽Dunhill
&&(drink[1]==color[2]) //喝咖啡者 住绿房
&&(guoji[1]==color[3]) //英国人 住红房
&&(drink[2]==smoke[1]) //喝啤酒者 抽BlueMaster
&&(pads[3]==smoke[3]) //养鸟者 抽PallMal
&&(guoji[2]==pads[1]) //瑞典人 养狗
&&(guoji[3]==smoke[4]) //德国人 抽Prince
&&(guoji[4]==drink[3]) //丹麦人 喝茶
&&(abs(smoke[0]-pads[0])==1)// 抽Blends者与养猫人邻居
&&(abs(smoke[0]-drink[4])==1)// 抽Blends者与喝水人邻居
&&(abs(smoke[2]-pads[2])==1)// 抽Dunhil者与养马人邻居
&&((color[2]-color[4])== -1)// 绿房是白房的左邻
) return 1;
else
return 0;
}
//全排列(要求n个元素互异,且最初n个元素已按升序排列好)
int rot(char a[],int n)
{ int i,j,k,t;
for(k=n-1;k>0;k--)
if(a[k-1]<a[k])break;
if(k)
{
t=a[k-1];i=k;
for(j=k+1;j<n;j++)
if(t<a[j]&&a[j]<a[i])i=j;
a[k-1]=a[i];a[i]=t;
for(i=k;i<n-1;i++)
for(j=k;j<n-1+k-i;j++)
if(a[j]>a[j+1])
{ t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
else
for(i=0,j=n-1;i<j;i++,j--)
{ t=a[i];
a[i]=a[j];
a[j]=t;
}
return k;
}
int main()
{
int i,j,k,ans=0;
do
{
do
{
do
{
do
{
do
{
if(OK())
{
printf("--------------第%d组解如下--------------------\n",++ans);
for(k=1;k<=5;k++)
{
printf("第%d户: ",k);
for(i=0;i<=4;i++)
for(j=0;j<=4;j++)
if(aa[i][j]==k)printf("%s ",msg[5*i+j]);
printf("\n");
}
}
}while(rot(smoke,5)); //五种香烟全排列
}while(rot(pads,5)); //五种宠物全排列
}while(rot(drink+1,4));//咖啡,啤酒,茶,水全排列
}while(rot(color+1,4));//黄色,绿色,红色,白色全排列
}while(rot(guoji+1,4)); //英国,瑞典,德国,丹麦全排列
printf("=============================================\n");
return 0;
}
/** 运行结果
--------------第1组解如下--------------------
第1户: 挪威人 黄房子 喝水 养猫 抽Dunhill
第2户: 丹麦人 蓝房子 喝茶 养马 抽Blends
第3户: 英国人 红房子 喝牛奶 养鸟 抽Pall Mall
第4户: 德国人 绿房子 喝咖啡 养鱼 抽Prince
第5户: 瑞典人 白房子 喝啤酒 养狗 抽BlueMaster
=============================================
**/
----------------解决方案--------------------------------------------------------
太累脑子了
[此贴子已经被作者于2007-11-12 14:28:30编辑过]
----------------解决方案--------------------------------------------------------
这道题本来的意思就是 绿房为白房的左邻吧。我们上人工智能做过这个题,不过是自己推的,还真没想到可以让电脑推
----------------解决方案--------------------------------------------------------
有难度啊,能否把思路解释下啊,谢了先!!!
----------------解决方案--------------------------------------------------------
有难度啊,能否把思路解释下啊,谢了先!!!
下面我针对发表在12楼的“完美版”程序作些解释。
首先,讲一下总体思路:本题总共有5户人家,每户5个信息(国籍、房子颜色、宠物、饮料、香烟牌子)
因此总共有25样东西需要落实它们的“房号”,房号的取值范围是1、2、3、4、5。然而,依题意,有3样东
西的房号是已知的,即:挪威人住1号房、2号房为蓝色、喝奶的住3号房。因此我们面临的任务就相当于求解
含22个未知数的方程组。下面介绍我给这些未知数起的名字吧。
由于房号是不大于五的整数,所以我定义了一堆字符型数组来表示这25样东西。具体如下:
1。数组char guoji[5]映射户主的国籍。其中guoji[0]代表挪威人,因为他住1号房,所以guoji[0]元素的
初值是1,guoji[1]代表英国人、guoji[2]代表瑞典人、guoji[3]代表德国人、guoji[4]代表丹麦人。
那么我凭什么将它们顺序地赋予2、3、4、5的初值呢?难道2号房真的住着英国人………5号房真的住着
丹麦人?非也!但有一点可以肯定,2、3、4、5号房子里住着除挪威而外的四国人。后面的程序中将要
对这四个房号全排列的24种情况逐一进行测试,看看哪种情况符合题目规定的约束条件。
2。数组char color[5]映射房子的颜色。其中color[0]代表蓝色,因已知2号房涂蓝色,所以color[0]元素
初值是2,color[1]代表黄、color[2]代表绿、color[3]代表红、color[4]代表白色。那么我凭什么将
它们顺序地赋予1、3、4、5的初值呢?难道1号房涂黄色、3号房涂绿色………5号房涂白?非也!但是
可以肯定,1、3、4、5号房的颜色不外乎黄、绿、红、白。后面的程序中将要对这四个房号全排列的24
种情况逐一进行试验,看看哪种情况符合题目规定的约束条件。
3。数组char drink[5]对应五种饮料。其中drink[0]代表牛奶,因为3号房主喝牛奶,所以drink[0]元素的
初值是3,drink[1]代表咖啡、drink[2]代表啤酒、drink[3]代表茶、drink[4]代表水。那么我凭什么
将它们顺序地赋予1、2、4、5的初值呢?难道1号房主喝咖啡………5号房主喝水?非也!但是可以肯定
1、2、4、5号房主喝的不外乎咖啡、啤酒、茶、水。后面的程序中将要对这四个房号全排列的24种情况
逐一进行试验,看看哪种情况符合题目规定的约束条件。
4。数组char pads[5]对应五种宠物。pads[0]代表猫,pads[1]代表狗、pads[2]代表马、pads[3]代表鸟、
pads[4]代表鱼。那么我凭什么将它们顺序地赋予1、2、3、4、5的初值呢?难道1号房主养猫………5号
房主养鱼?非也!但是可以肯定五名房主养的不外乎猫、狗、马、鸟、鱼。后面的程序中将要对这五个
房号全排列的120种情况逐一进行试验,看看哪种情况符合题目规定的约束条件。
5。数组char smoke[5]对应五种香烟。smoke[0]代表Blends牌香烟,smoke[1]代表BlueMaster、smoke[2]
代表Dunhill、smoke[3]代表Pall Mall、smoke[4]代表Prince。那么凭什么将它们顺序地赋予1、2、3、
4、5的初值呢?难道1号房主抽Blends烟………5号房主抽Prince烟?非也!但可以肯定,五名房主抽的
不外乎那五种品牌的香烟。后面的程序中将要对这五个房主全排列的120种可能的抽烟情况逐一试验,
看看哪种情况符合题目规定的约束条件。
由此可见,我设计的程序将要依赖计算机的高速度,疯狂地对24×24×24×120×120种可能情况逐一地
测试它们是否满足全部约束条件。于是我的程序共有3个函数:main( )完成“五重循环”并负责把满足全部
约束条件的合格解在屏幕上显示出来。OK()负责检测每组(22个)数据是否满足约束条件,仅当满足全部约束
条件时才返回1,否则返回0。rot()是全排列生成函数,个人觉得这个程序段是最出彩的。
应当指出,12楼的代码虽然比较短,但运行速度比较慢。如果要提速,最明显的方法就是把OK()判断函
数中开头八个“==”关系直接用起来,从而把未知数从22个降为14个!但代码的短小精悍特性将不复存在。
[此贴子已经被作者于2007-11-12 21:29:00编辑过]
----------------解决方案--------------------------------------------------------
这个题目如果用进制算的话,很简单的
----------------解决方案--------------------------------------------------------
这个题目如果用进制算的话,很简单的
愿闻其详。烦您不吝赐教。
----------------解决方案--------------------------------------------------------
晕掉了啊 在这样下去的话 我就要被程序吓坏了啊
----------------解决方案--------------------------------------------------------
晕,LZ,你也是CUIT的安?我们前一个星期编程比赛就搞了这个题目,我想了6个小时,都没有搞出来
----------------解决方案--------------------------------------------------------