前面有人给出了这道出自1981年柏林的德国逻辑思考学院据说就连大名鼎鼎的爱因斯坦也成为此题大伤脑筋的迷题的七种答案和java实现
过程。
我这里有十六种答案和C++实现过程,我觉得代码写得还可以,如果有兴趣可与我交流。
///////////////////////////////////////////////////////////////////
原题为:
2.每一位房子的主人国籍都不同
3.这五个人每人只喝一个牌子的饮料,只抽一个牌子的香烟,只养一种宠物
4.没有人有相同的宠物,抽相同牌子的烟,喝相同牌子的饮料
已知条件:
1.英国人住在红房子里
2.瑞典人养了一条狗
3.丹麦人喝茶
4.绿房子在白房子的左边
5.绿房子主人喝咖啡
6.抽pallmall烟的人养了一只鸟
7.黄房子主人抽dunhill烟
8.住在中间房子的人喝牛奶
9.挪威人住在第一间房子
10.抽混合烟的人住在养猫人的旁边
11.养马人住在抽dunhill烟人的旁边
12.抽bluemaster烟的人喝啤酒
13.德国人抽prince烟
14.挪威人住在蓝房子旁边
15.抽混合烟的人的邻居喝矿泉水
问题:谁养鱼?
///////////////////////////////////////////////////////////////////
公布答案如下:
----------------“1”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 FISH 狗 猫 马
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“2”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 猫 狗 FISH 马
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“3”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 黄房子 白房子 红房子
鸟 FISH 狗 马 猫
咖啡 矿泉 牛奶 茶水 啤酒
pall prin dunh mixe blue
----------------“4”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 黄房子 白房子 红房子
鸟 马 狗 FISH 猫
咖啡 矿泉 牛奶 茶水 啤酒
pall prin dunh mixe blue
----------------“5”----------------
挪威人 德国人 英国人 丹麦人 瑞典人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 FISH 马 猫 狗
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“6”----------------
挪威人 德国人 英国人 丹麦人 瑞典人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 猫 马 FISH 狗
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“7”----------------
挪威人 瑞典人 德国人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 狗 猫 FISH 马
咖啡 矿泉 牛奶 茶水 啤酒
pall mixe prin dunh blue
----------------“8”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 猫 狗 马 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall prin mixe blue dunh
----------------“9”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 黄房子 红房子 白房子
鸟 马 狗 猫 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall prin dunh blue mixe
----------------“10”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 黄房子 红房子 白房子
FISH 猫 狗 马 鸟
咖啡 矿泉 牛奶 啤酒 茶水
mixe prin dunh blue pall
----------------“11”----------------
挪威人 瑞典人 德国人 英国人 丹麦人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 狗 猫 马 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall mixe prin blue dunh
----------------“12”----------------
挪威人 丹麦人 德国人 瑞典人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 FISH 猫 狗 马
咖啡 茶水 牛奶 矿泉 啤酒
pall mixe prin dunh blue
----------------“13”----------------
挪威人 丹麦人 德国人 英国人 瑞典人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 FISH 猫 马 狗
咖啡 茶水 牛奶 啤酒 矿泉
pall mixe prin blue dunh
----------------“14”----------------
挪威人 瑞典人 英国人 丹麦人 德国人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 狗 FISH 猫 马
咖啡 啤酒 牛奶 茶水 矿泉
pall blue mixe dunh prin
----------------“15”----------------
挪威人 瑞典人 英国人 丹麦人 德国人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 狗 马 猫 FISH
咖啡 啤酒 牛奶 茶水 矿泉
pall blue mixe dunh prin
----------------“16”----------------
挪威人 丹麦人 英国人 德国人 瑞典人
黄房子 蓝房子 红房子 绿房子 白房子
猫 马 鸟 FISH 狗
矿泉 茶水 牛奶 咖啡 啤酒
dunh mixe pall prin blue
所有答案都已经输出,我的服务已经完成。 GOOD LUCK!
Press any key to continue
///////////////////////////////////////////////////////////////////
源代码如下:
/*2005-11-28
*作者:贺志明,西南科技大学,Email: me.trace@gmail.com.QQ:279287903
*
*程序基于单链表数据结构.
*共有三个文件:"ListNode.h","Linlist.h","WhoFeedsFish.cpp"
//---------------------ListNode.h--------------------------------
/*链表结点类,模板为T,两个属性,两个构造函数
*/
template <class T> class Linlist;
template <class T>
class ListNode
{
friend class Linlist<T>;
private:
ListNode<T>* next; //指针
public:
T data; //数据“国家”,“烟”,,等
int pos; //在链表中的位置--->编号
ListNode(ListNode<T>* nextptr = NULL);
//构造头结点
ListNode(const T& da=NULL,const int p=0,ListNode<T>* nextPtr = NULL); //构造其他结点
~ListNode(){};
};
template <class T>
ListNode<T>::ListNode(ListNode<T>* nextptr)
{
next = nextptr;
}
template <class T>
ListNode<T>::ListNode(const T& da,const int p,ListNode<T>* nextPtr)
{
data = da;
pos = p;
//movable = true;
next = nextPtr;
}
//---------------------Linlist.h--------------------------------
/*因为是5个结点,因此不用size属性
*
*
*/
#include "ListNode.h"
template <class T>
class Linlist
{
private:
ListNode<T> *head; //头结点
ListNode<T> *currPtr; //当前结点
public:
Linlist(void); //初始化头结点
~Linlist(); //析构函数
ListNode<T> *Index(int pos); //索引pos结点
T& GetData(const int pos); //取得数据
int GetPos(T& data);
void Exchange(int p1,int p2); //交换两个位置上的数据
void Insert(const T& item,int pos); //在pos结点前插入
void Clear(void); //清空
};
template <class T>
Linlist<T>::Linlist() //构造函数,建立一个只有头结点的链表...
{
head = new ListNode<T>(NULL);
}
template <class T>
Linlist<T>::~Linlist() //析构函数,清空链表
{
Clear();
delete head;
}
template <class T>
ListNode<T>* Linlist<T>::Index(int pos) //索引pos处的结点
{
if( pos<0 || pos>5)
{
cout<<"pos is out of the limit!!"<<endl;
exit(0);
}
else if(pos == 0)
{
currPtr = head;
return currPtr;
}
else{
currPtr = head;
for(int i=0;i<pos;i++) //pos = 1,2,3,4,5五个值
{
currPtr = currPtr->next;
}
return currPtr;
}
}
template <class T>
T& Linlist<T>::GetData(const int pos) //取得pos处的值
{
return Index(pos)->data;
}
template <class T>
int Linlist<T>::GetPos(T& dataa)
{
currPtr = head;
for(int i=0;i<5;i++) //pos = 1,2,3,4,5五个值
{
currPtr = currPtr->next;
if(currPtr->data == dataa)
break;
}
return currPtr->pos;
}
template <class T>
void Linlist<T>::Exchange(int p1,int p2) //交换两个位置处的值
{
T temp1 = Index(p1)->data; //数据改变
T temp3 = Index(p2)->data;
Index(p1)->data = temp3;
Index(p2)->data = temp1;
cout<<Index(p1)->data<<" "<<Index(p2)->data<<endl;
int temp2 = Index(p1)->pos; //编号改变
int temp4 = Index(p2)->pos;
Index(p1)->pos = temp4;
Index(p2)->pos = temp2;
cout<<Index(p1)->pos<<" "<<Index(p2)->pos<<endl;
}
template <class T>
void Linlist<T>::Insert(const T& item,int pos) //在位置pos处插入值
{
ListNode<T>* p= Index(pos-1);
ListNode<T>* newnode= new ListNode<T>(item,pos,p->next);
p->next = newnode;
//size++;
}
template <class T>
void Linlist<T>::Clear(void) //清空
{
ListNode<T>* p = head->next,*p1;
while(p != NULL)
{
p1=p;
p=p->next;
delete p1;
}
//size = 0;
}
//---------------------End OF Linlist.h--------------------------------
//---------------------WhoFeedsFish.cpp--------------------------------
//主执行文件,
#include <iostream>
#include <string>
using namespace std;
#include "Linlist.h"
void print(); //提前声明函数
const string Nation1alities[5] ={"挪威人","德国人","瑞典人","丹麦人","英国人"};
const string Color1s[5] ={"绿房子","蓝房子","白房子","黄房子","红房子"};
const string Pet1s[5] ={"鸟" ,"FISH" ,"狗" ,"猫" ,"马" };
const string Drink1s[5] ={"咖啡" ,"矿泉" ,"牛奶" ,"茶水" ,"啤酒" };
const string Tocacco1es[5] ={"pall" ,"prin" ,"mixe" ,"dunh" ,"blue" };
Linlist<string> Nation1,Color1,Pet1,Drink1,Tocacco1;
Linlist<string> Nation2,Color2,Pet2,Drink2,Tocacco2;
int m=0,arr[120][5],num=1;
void Bechange(int x=0,int* arr=0) //按照序列变换链表中结点之间的位置
{ //(共有120种序列,每种是1,2,3,4,5的一个全排列)
for(int i=0; i<5; i++)
{
switch(x)
{
case 1:
Drink2.Insert(Drink1.GetData(arr[i]),i+1); //arr接收的是一个二维数组的列数组,arr[i]是一个二维数组
case 2:
Nation2.Insert(Nation1.GetData(arr[i]),i+1);
case 3:
Color2.Insert(Color1.GetData(arr[i]),i+1);
case 4:
Pet2.Insert(Pet1.GetData(arr[i]),i+1);
case 5:
Tocacco2.Insert(Tocacco1.GetData(arr[i]),i+1);
}
}
}
///////////////以下代码是检查是否满足前提条件的函数///////////////////
bool check1(){ // 条件1:英国人住在红房子里 1
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "英国人")
{
if(Color2.GetData(i+1) != "红房子")
{
ret = false;
}
break;
}
}
return ret;
}
bool check2() // 条件2:瑞典人养了一条狗 2
{
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "瑞典人")
{
if(Pet2.GetData(i+1) != "狗")
{
ret = false;
}
break;
}
}
return ret;
}
bool check3() // 条件3:丹麦人喝茶 3
{
for(int i = 0; i < 5; i ++){
if(Nation2.GetData(i+1) == "丹麦人")
{
if(Drink2.GetData(i+1) != "茶水")
{
return false;
}
else{
return true;
}
}
}
return false;
}
bool check4() // 条件4:绿房子在白房子的左边 4
{
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Color2.GetData(i+1) == "绿房子")
{
for(int j = 0; j < 5; j ++)
{
if(Color2.GetData(j+1) == "白房子")
{
if(i > j)
{
ret = false;
}
break;
}
}
}
}
return ret;
}
// 条件5:绿房子主人喝咖啡 5
bool check5(){
for(int i = 0; i < 5; i ++){
if(Color2.GetData(i+1) == "绿房子"){
if(Drink2.GetData(i+1) != "咖啡"){
return false;
}
else{
return true;
}
}
}
return false;
}
// 条件6:抽pallmall烟的人养了一只鸟 6
bool check6(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "pall"){
if(Pet2.GetData(i+1) != "鸟"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check7(){ // 条件7:黄房子主人抽dunhill烟 7
for(int i = 0; i <5; i ++){
if(Color2.GetData(i+1) == "黄房子"){
if(Tocacco2.GetData(i+1) != "dunh"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check8() // 条件8:住在中间房子的人喝牛奶 8
{
return Drink2.GetData(3) == "牛奶"?true:false;
}
bool check9(){ // 条件9:挪威人住在第一间房子 9
if(Nation2.GetData(1) != "挪威人")
{
return false;
}
return true;
}
// 条件10:抽混合烟的人住在养猫人的旁边 10
bool check10(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "mixe"){
for(int j = 0; j < 5; j ++){
if(Pet2.GetData(j+1) == "猫"){
if(i - j != 1 && i - j != -1){
return false;
}
else
return true;
}
}
}
}
return false;
}
// 条件11:养马人住在抽dunhill烟人的旁边 11
bool check11(){
for(int i = 0; i < 5; i ++){
if(Pet2.GetData(i+1) == "马"){
for(int j = 0; j < 5; j ++){
if(Tocacco2.GetData(j+1) == "dunh"){
if(i - j != 1 && i - j != -1){
return false;
}
else{
return true;
}
}
}
}
}
return false;
}
// 条件12:抽bluemaster烟的人喝啤酒 12
bool check12(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "blue"){
if(Drink2.GetData(i+1) != "啤酒"){
return false;
}
else{
return true;
}
}
}
return false;
}
// 13.德国人抽prince烟 13
bool check13(){
for(int i = 0; i < 5; i ++){
if(Nation2.GetData(i+1) == "德国人"){
if(Tocacco2.GetData(i+1) != "prin"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check14() // 14.挪威人住在蓝房子旁边 14
{
bool ret = false;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "挪威人")
{
for(int j = 0; j < 5; j ++){
if(Color2.GetData(j+1) == "蓝房子"){
if( ( i-j != 1 )&&( j-i != 1) ){
return false;
}else{
return true;
}
}
}
}
}
return ret;
}
bool check15(){ // 15.抽混合烟的人的邻居喝矿泉水 15
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1)=="mixe"){
for(int j = 0; j < 5; j ++){
if(Drink2.GetData(i+1) == "矿泉"){
if((i - j != 1) && (i - j != -1)){
return false;
}
else{
break;
}
}
}
}
}
return true;
}
///////////////以上代码是检查是否满足前提条件的函数///////////////////
void main()
{
for(int i=0; i<5;i++) //先将链表1初始化赋值
{
Nation1.Insert(Nation1alities[i],i+1);
Color1.Insert(Color1s[i],i+1);
Pet1.Insert(Pet1s[i],i+1);
Drink1.Insert(Drink1s[i],i+1);
Tocacco1.Insert(Tocacco1es[i],i+1);
}
//这个五重for循环生成由1,2,3,4,5组成的全排列的二维数组arr[120][5].共五行一百二十列。
//它用于指定每次链表中各结点的排列顺序.
for(int a=0; a<5; a++)
{
for(int b=0; b<5; b++)
{
for(int c=0; c<5; c++)
{
for(int d=0; d<5; d++)
{
for(int e=0; e<5; e++)
{
if( a!=b && a!=c && a!=d && a!=e && b!=c && b!=d && b!=e && c!=d && c!=e && d!=e )
{
int array2[5]={a+1,b+1,c+1,d+1,e+1};
for(int i=0;i<5;i++)
{
arr[m][i] = array2[i];
}
m++;
}
}
}
}
}
}
//for(int i=0;i<m;i++) //打印二维数组arr[i][j].
//{
// for(int j=0;j<5;j++)
// {
// cout<<arr[i][j]<<" ";
// }
// cout<<endl;
//}
//生成所有情况下的矩阵
for(int a=0; a<120; a++)
{
Bechange(1,arr[a]);//Drink
if( !check8() ) // 条件8:住在中间房子的人喝牛奶 8
continue;
else
for(int b=0; b<120; b++)
{
Bechange(2,arr[b]);//Nation
if( !check9() ) // 条件9:挪威人住在第一间房子 9
continue;
if( !check3() ) // 条件3:丹麦人喝茶 3
continue;
else
for(int c=0; c<120; c++)
{
Bechange(3,arr[c]);//Color
if( !check4()) // 条件4:绿房子在白房子的左边 4
continue;
else if( !check1()) // 条件1:英国人住在红房子里 1
continue;
else if( !check14()) // 条件14:挪威人住在蓝房子旁边 14
continue;
else if( !check5() ) // 条件5:绿房子主人喝咖啡 5
continue;
else
for(int d=0; d<120; d++)
{
Bechange(4,arr[d]);//Pet
if( !check2() ) // 条件2:瑞典人养了一条狗 2
continue;
else
for(int e=0; e<120; e++)
{
Bechange(5,arr[e]);//Tocacco
if( !check6() ) // 条件6:抽pallmall烟的人养了一只鸟 6
continue;
if( !check7() ) // 条件7:黄房子主人抽dunhill烟 7
continue;
if( !check10() ) // 条件10:抽混合烟的人住在养猫人的旁边 10
continue;
if( !check11() ) // 条件11:养马人住在抽dunhill烟人的旁边 11
continue;
if( !check12() ) // 条件12:抽bluemaster烟的人喝啤酒 12
continue;
if( !check13() ) // 13.德国人抽prince烟 13
continue;
else if( check15() ) // 15.抽混合烟的人的邻居喝矿泉水 15
{
cout<<endl;
cout<<"----------------“"<<num<<"”----------------"<<endl;;
print(); //如果所有的条件都已满足,则输出结果.
num++;
}
}
}
}
}
}
cout<<endl<<"所有答案都已经输出,我的服务已经完成。 GOOD LUCK!"<<endl;
}
void print() //输出结果函数
{
for(int i=0;i<5;i++)
{
cout<<" "<<Nation2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Color2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Pet2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Drink2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Tocacco2.GetData(i+1)<<" ";
}
cout<<endl;
}
过程。
我这里有十六种答案和C++实现过程,我觉得代码写得还可以,如果有兴趣可与我交流。
///////////////////////////////////////////////////////////////////
原题为:
2.每一位房子的主人国籍都不同
3.这五个人每人只喝一个牌子的饮料,只抽一个牌子的香烟,只养一种宠物
4.没有人有相同的宠物,抽相同牌子的烟,喝相同牌子的饮料
已知条件:
1.英国人住在红房子里
2.瑞典人养了一条狗
3.丹麦人喝茶
4.绿房子在白房子的左边
5.绿房子主人喝咖啡
6.抽pallmall烟的人养了一只鸟
7.黄房子主人抽dunhill烟
8.住在中间房子的人喝牛奶
9.挪威人住在第一间房子
10.抽混合烟的人住在养猫人的旁边
11.养马人住在抽dunhill烟人的旁边
12.抽bluemaster烟的人喝啤酒
13.德国人抽prince烟
14.挪威人住在蓝房子旁边
15.抽混合烟的人的邻居喝矿泉水
问题:谁养鱼?
///////////////////////////////////////////////////////////////////
公布答案如下:
----------------“1”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 FISH 狗 猫 马
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“2”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 猫 狗 FISH 马
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“3”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 黄房子 白房子 红房子
鸟 FISH 狗 马 猫
咖啡 矿泉 牛奶 茶水 啤酒
pall prin dunh mixe blue
----------------“4”----------------
挪威人 德国人 瑞典人 丹麦人 英国人
绿房子 蓝房子 黄房子 白房子 红房子
鸟 马 狗 FISH 猫
咖啡 矿泉 牛奶 茶水 啤酒
pall prin dunh mixe blue
----------------“5”----------------
挪威人 德国人 英国人 丹麦人 瑞典人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 FISH 马 猫 狗
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“6”----------------
挪威人 德国人 英国人 丹麦人 瑞典人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 猫 马 FISH 狗
咖啡 矿泉 牛奶 茶水 啤酒
pall prin mixe dunh blue
----------------“7”----------------
挪威人 瑞典人 德国人 丹麦人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 狗 猫 FISH 马
咖啡 矿泉 牛奶 茶水 啤酒
pall mixe prin dunh blue
----------------“8”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 猫 狗 马 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall prin mixe blue dunh
----------------“9”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 黄房子 红房子 白房子
鸟 马 狗 猫 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall prin dunh blue mixe
----------------“10”----------------
挪威人 德国人 瑞典人 英国人 丹麦人
绿房子 蓝房子 黄房子 红房子 白房子
FISH 猫 狗 马 鸟
咖啡 矿泉 牛奶 啤酒 茶水
mixe prin dunh blue pall
----------------“11”----------------
挪威人 瑞典人 德国人 英国人 丹麦人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 狗 猫 马 FISH
咖啡 矿泉 牛奶 啤酒 茶水
pall mixe prin blue dunh
----------------“12”----------------
挪威人 丹麦人 德国人 瑞典人 英国人
绿房子 蓝房子 白房子 黄房子 红房子
鸟 FISH 猫 狗 马
咖啡 茶水 牛奶 矿泉 啤酒
pall mixe prin dunh blue
----------------“13”----------------
挪威人 丹麦人 德国人 英国人 瑞典人
绿房子 蓝房子 白房子 红房子 黄房子
鸟 FISH 猫 马 狗
咖啡 茶水 牛奶 啤酒 矿泉
pall mixe prin blue dunh
----------------“14”----------------
挪威人 瑞典人 英国人 丹麦人 德国人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 狗 FISH 猫 马
咖啡 啤酒 牛奶 茶水 矿泉
pall blue mixe dunh prin
----------------“15”----------------
挪威人 瑞典人 英国人 丹麦人 德国人
绿房子 蓝房子 红房子 黄房子 白房子
鸟 狗 马 猫 FISH
咖啡 啤酒 牛奶 茶水 矿泉
pall blue mixe dunh prin
----------------“16”----------------
挪威人 丹麦人 英国人 德国人 瑞典人
黄房子 蓝房子 红房子 绿房子 白房子
猫 马 鸟 FISH 狗
矿泉 茶水 牛奶 咖啡 啤酒
dunh mixe pall prin blue
所有答案都已经输出,我的服务已经完成。 GOOD LUCK!
Press any key to continue
///////////////////////////////////////////////////////////////////
源代码如下:
/*2005-11-28
*作者:贺志明,西南科技大学,Email: me.trace@gmail.com.QQ:279287903
*
*程序基于单链表数据结构.
*共有三个文件:"ListNode.h","Linlist.h","WhoFeedsFish.cpp"
//---------------------ListNode.h--------------------------------
/*链表结点类,模板为T,两个属性,两个构造函数
*/
template <class T> class Linlist;
template <class T>
class ListNode
{
friend class Linlist<T>;
private:
ListNode<T>* next; //指针
public:
T data; //数据“国家”,“烟”,,等
int pos; //在链表中的位置--->编号
ListNode(ListNode<T>* nextptr = NULL);
//构造头结点
ListNode(const T& da=NULL,const int p=0,ListNode<T>* nextPtr = NULL); //构造其他结点
~ListNode(){};
};
template <class T>
ListNode<T>::ListNode(ListNode<T>* nextptr)
{
next = nextptr;
}
template <class T>
ListNode<T>::ListNode(const T& da,const int p,ListNode<T>* nextPtr)
{
data = da;
pos = p;
//movable = true;
next = nextPtr;
}
//---------------------Linlist.h--------------------------------
/*因为是5个结点,因此不用size属性
*
*
*/
#include "ListNode.h"
template <class T>
class Linlist
{
private:
ListNode<T> *head; //头结点
ListNode<T> *currPtr; //当前结点
public:
Linlist(void); //初始化头结点
~Linlist(); //析构函数
ListNode<T> *Index(int pos); //索引pos结点
T& GetData(const int pos); //取得数据
int GetPos(T& data);
void Exchange(int p1,int p2); //交换两个位置上的数据
void Insert(const T& item,int pos); //在pos结点前插入
void Clear(void); //清空
};
template <class T>
Linlist<T>::Linlist() //构造函数,建立一个只有头结点的链表...
{
head = new ListNode<T>(NULL);
}
template <class T>
Linlist<T>::~Linlist() //析构函数,清空链表
{
Clear();
delete head;
}
template <class T>
ListNode<T>* Linlist<T>::Index(int pos) //索引pos处的结点
{
if( pos<0 || pos>5)
{
cout<<"pos is out of the limit!!"<<endl;
exit(0);
}
else if(pos == 0)
{
currPtr = head;
return currPtr;
}
else{
currPtr = head;
for(int i=0;i<pos;i++) //pos = 1,2,3,4,5五个值
{
currPtr = currPtr->next;
}
return currPtr;
}
}
template <class T>
T& Linlist<T>::GetData(const int pos) //取得pos处的值
{
return Index(pos)->data;
}
template <class T>
int Linlist<T>::GetPos(T& dataa)
{
currPtr = head;
for(int i=0;i<5;i++) //pos = 1,2,3,4,5五个值
{
currPtr = currPtr->next;
if(currPtr->data == dataa)
break;
}
return currPtr->pos;
}
template <class T>
void Linlist<T>::Exchange(int p1,int p2) //交换两个位置处的值
{
T temp1 = Index(p1)->data; //数据改变
T temp3 = Index(p2)->data;
Index(p1)->data = temp3;
Index(p2)->data = temp1;
cout<<Index(p1)->data<<" "<<Index(p2)->data<<endl;
int temp2 = Index(p1)->pos; //编号改变
int temp4 = Index(p2)->pos;
Index(p1)->pos = temp4;
Index(p2)->pos = temp2;
cout<<Index(p1)->pos<<" "<<Index(p2)->pos<<endl;
}
template <class T>
void Linlist<T>::Insert(const T& item,int pos) //在位置pos处插入值
{
ListNode<T>* p= Index(pos-1);
ListNode<T>* newnode= new ListNode<T>(item,pos,p->next);
p->next = newnode;
//size++;
}
template <class T>
void Linlist<T>::Clear(void) //清空
{
ListNode<T>* p = head->next,*p1;
while(p != NULL)
{
p1=p;
p=p->next;
delete p1;
}
//size = 0;
}
//---------------------End OF Linlist.h--------------------------------
//---------------------WhoFeedsFish.cpp--------------------------------
//主执行文件,
#include <iostream>
#include <string>
using namespace std;
#include "Linlist.h"
void print(); //提前声明函数
const string Nation1alities[5] ={"挪威人","德国人","瑞典人","丹麦人","英国人"};
const string Color1s[5] ={"绿房子","蓝房子","白房子","黄房子","红房子"};
const string Pet1s[5] ={"鸟" ,"FISH" ,"狗" ,"猫" ,"马" };
const string Drink1s[5] ={"咖啡" ,"矿泉" ,"牛奶" ,"茶水" ,"啤酒" };
const string Tocacco1es[5] ={"pall" ,"prin" ,"mixe" ,"dunh" ,"blue" };
Linlist<string> Nation1,Color1,Pet1,Drink1,Tocacco1;
Linlist<string> Nation2,Color2,Pet2,Drink2,Tocacco2;
int m=0,arr[120][5],num=1;
void Bechange(int x=0,int* arr=0) //按照序列变换链表中结点之间的位置
{ //(共有120种序列,每种是1,2,3,4,5的一个全排列)
for(int i=0; i<5; i++)
{
switch(x)
{
case 1:
Drink2.Insert(Drink1.GetData(arr[i]),i+1); //arr接收的是一个二维数组的列数组,arr[i]是一个二维数组
case 2:
Nation2.Insert(Nation1.GetData(arr[i]),i+1);
case 3:
Color2.Insert(Color1.GetData(arr[i]),i+1);
case 4:
Pet2.Insert(Pet1.GetData(arr[i]),i+1);
case 5:
Tocacco2.Insert(Tocacco1.GetData(arr[i]),i+1);
}
}
}
///////////////以下代码是检查是否满足前提条件的函数///////////////////
bool check1(){ // 条件1:英国人住在红房子里 1
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "英国人")
{
if(Color2.GetData(i+1) != "红房子")
{
ret = false;
}
break;
}
}
return ret;
}
bool check2() // 条件2:瑞典人养了一条狗 2
{
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "瑞典人")
{
if(Pet2.GetData(i+1) != "狗")
{
ret = false;
}
break;
}
}
return ret;
}
bool check3() // 条件3:丹麦人喝茶 3
{
for(int i = 0; i < 5; i ++){
if(Nation2.GetData(i+1) == "丹麦人")
{
if(Drink2.GetData(i+1) != "茶水")
{
return false;
}
else{
return true;
}
}
}
return false;
}
bool check4() // 条件4:绿房子在白房子的左边 4
{
bool ret = true;
for(int i = 0; i < 5; i ++)
{
if(Color2.GetData(i+1) == "绿房子")
{
for(int j = 0; j < 5; j ++)
{
if(Color2.GetData(j+1) == "白房子")
{
if(i > j)
{
ret = false;
}
break;
}
}
}
}
return ret;
}
// 条件5:绿房子主人喝咖啡 5
bool check5(){
for(int i = 0; i < 5; i ++){
if(Color2.GetData(i+1) == "绿房子"){
if(Drink2.GetData(i+1) != "咖啡"){
return false;
}
else{
return true;
}
}
}
return false;
}
// 条件6:抽pallmall烟的人养了一只鸟 6
bool check6(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "pall"){
if(Pet2.GetData(i+1) != "鸟"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check7(){ // 条件7:黄房子主人抽dunhill烟 7
for(int i = 0; i <5; i ++){
if(Color2.GetData(i+1) == "黄房子"){
if(Tocacco2.GetData(i+1) != "dunh"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check8() // 条件8:住在中间房子的人喝牛奶 8
{
return Drink2.GetData(3) == "牛奶"?true:false;
}
bool check9(){ // 条件9:挪威人住在第一间房子 9
if(Nation2.GetData(1) != "挪威人")
{
return false;
}
return true;
}
// 条件10:抽混合烟的人住在养猫人的旁边 10
bool check10(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "mixe"){
for(int j = 0; j < 5; j ++){
if(Pet2.GetData(j+1) == "猫"){
if(i - j != 1 && i - j != -1){
return false;
}
else
return true;
}
}
}
}
return false;
}
// 条件11:养马人住在抽dunhill烟人的旁边 11
bool check11(){
for(int i = 0; i < 5; i ++){
if(Pet2.GetData(i+1) == "马"){
for(int j = 0; j < 5; j ++){
if(Tocacco2.GetData(j+1) == "dunh"){
if(i - j != 1 && i - j != -1){
return false;
}
else{
return true;
}
}
}
}
}
return false;
}
// 条件12:抽bluemaster烟的人喝啤酒 12
bool check12(){
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1) == "blue"){
if(Drink2.GetData(i+1) != "啤酒"){
return false;
}
else{
return true;
}
}
}
return false;
}
// 13.德国人抽prince烟 13
bool check13(){
for(int i = 0; i < 5; i ++){
if(Nation2.GetData(i+1) == "德国人"){
if(Tocacco2.GetData(i+1) != "prin"){
return false;
}
else{
return true;
}
}
}
return false;
}
bool check14() // 14.挪威人住在蓝房子旁边 14
{
bool ret = false;
for(int i = 0; i < 5; i ++)
{
if(Nation2.GetData(i+1) == "挪威人")
{
for(int j = 0; j < 5; j ++){
if(Color2.GetData(j+1) == "蓝房子"){
if( ( i-j != 1 )&&( j-i != 1) ){
return false;
}else{
return true;
}
}
}
}
}
return ret;
}
bool check15(){ // 15.抽混合烟的人的邻居喝矿泉水 15
for(int i = 0; i < 5; i ++){
if(Tocacco2.GetData(i+1)=="mixe"){
for(int j = 0; j < 5; j ++){
if(Drink2.GetData(i+1) == "矿泉"){
if((i - j != 1) && (i - j != -1)){
return false;
}
else{
break;
}
}
}
}
}
return true;
}
///////////////以上代码是检查是否满足前提条件的函数///////////////////
void main()
{
for(int i=0; i<5;i++) //先将链表1初始化赋值
{
Nation1.Insert(Nation1alities[i],i+1);
Color1.Insert(Color1s[i],i+1);
Pet1.Insert(Pet1s[i],i+1);
Drink1.Insert(Drink1s[i],i+1);
Tocacco1.Insert(Tocacco1es[i],i+1);
}
//这个五重for循环生成由1,2,3,4,5组成的全排列的二维数组arr[120][5].共五行一百二十列。
//它用于指定每次链表中各结点的排列顺序.
for(int a=0; a<5; a++)
{
for(int b=0; b<5; b++)
{
for(int c=0; c<5; c++)
{
for(int d=0; d<5; d++)
{
for(int e=0; e<5; e++)
{
if( a!=b && a!=c && a!=d && a!=e && b!=c && b!=d && b!=e && c!=d && c!=e && d!=e )
{
int array2[5]={a+1,b+1,c+1,d+1,e+1};
for(int i=0;i<5;i++)
{
arr[m][i] = array2[i];
}
m++;
}
}
}
}
}
}
//for(int i=0;i<m;i++) //打印二维数组arr[i][j].
//{
// for(int j=0;j<5;j++)
// {
// cout<<arr[i][j]<<" ";
// }
// cout<<endl;
//}
//生成所有情况下的矩阵
for(int a=0; a<120; a++)
{
Bechange(1,arr[a]);//Drink
if( !check8() ) // 条件8:住在中间房子的人喝牛奶 8
continue;
else
for(int b=0; b<120; b++)
{
Bechange(2,arr[b]);//Nation
if( !check9() ) // 条件9:挪威人住在第一间房子 9
continue;
if( !check3() ) // 条件3:丹麦人喝茶 3
continue;
else
for(int c=0; c<120; c++)
{
Bechange(3,arr[c]);//Color
if( !check4()) // 条件4:绿房子在白房子的左边 4
continue;
else if( !check1()) // 条件1:英国人住在红房子里 1
continue;
else if( !check14()) // 条件14:挪威人住在蓝房子旁边 14
continue;
else if( !check5() ) // 条件5:绿房子主人喝咖啡 5
continue;
else
for(int d=0; d<120; d++)
{
Bechange(4,arr[d]);//Pet
if( !check2() ) // 条件2:瑞典人养了一条狗 2
continue;
else
for(int e=0; e<120; e++)
{
Bechange(5,arr[e]);//Tocacco
if( !check6() ) // 条件6:抽pallmall烟的人养了一只鸟 6
continue;
if( !check7() ) // 条件7:黄房子主人抽dunhill烟 7
continue;
if( !check10() ) // 条件10:抽混合烟的人住在养猫人的旁边 10
continue;
if( !check11() ) // 条件11:养马人住在抽dunhill烟人的旁边 11
continue;
if( !check12() ) // 条件12:抽bluemaster烟的人喝啤酒 12
continue;
if( !check13() ) // 13.德国人抽prince烟 13
continue;
else if( check15() ) // 15.抽混合烟的人的邻居喝矿泉水 15
{
cout<<endl;
cout<<"----------------“"<<num<<"”----------------"<<endl;;
print(); //如果所有的条件都已满足,则输出结果.
num++;
}
}
}
}
}
}
cout<<endl<<"所有答案都已经输出,我的服务已经完成。 GOOD LUCK!"<<endl;
}
void print() //输出结果函数
{
for(int i=0;i<5;i++)
{
cout<<" "<<Nation2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Color2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Pet2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Drink2.GetData(i+1)<<" ";
}
cout<<endl;
for(int i=0;i<5;i++)
{
cout<<" "<<Tocacco2.GetData(i+1)<<" ";
}
cout<<endl;
}