您的位置:首页 > 其它

农夫过河问题(一个有趣的问题-位运算)

2013-10-07 21:58 633 查看
一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。问题是他面前只有一条小船,船小到只能容下他和一件物品,另外只有农夫能撑船。另外,因为狼能吃羊,而羊爱吃白菜,所以农夫不能留下羊和白菜或者狼和羊单独在河的一边,自己离开。请问农夫该采取什么方案才能将所有的东西运过河呢?

解答:

要模拟农夫过河问题,首先需要选择一个对问题中每个角色的位置进行描述的方法。一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。例如用0表示农夫或者某东西在河的南岸,1表示在河的北岸。因此整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。在这个问题中就是要找出一个从0000->1111的迁徙序列,并满足上述的约束要求。用vis[]记录每个状态是否被访问过,并记下访问此点的前驱节点。

#include <cstdio>
#include <queue>
using namespace std;

queue<int> Q;
int vis[16];
char nb[16][6]={"0000","0001","0010","0011","0100","0101",
"0110","0111","1000","1001","1010","1011",
"1100","1101","1110","1111"};

bool farmer(int s)
{
return s&(1<<3);
}

bool wolf(int s)
{
return s&(1<<2);
}

bool cabbage(int s)
{
return s&(1<<1);
}

bool goat(int s)
{
return s&1;
}

bool check(int s)
{
if((wolf(s)==goat(s)) && (wolf(s)!=farmer(s)))
return false;
else if((cabbage(s)==goat(s)) && (goat(s)!=farmer(s)))
return false;
return true;
}

void print(int u)
{
if(u!=vis[u])
{
print(vis[u]);
printf("->%s",nb[u]);
//printf("->%d",u);
}
else
printf("%s",nb[u]);
//printf("%d",u);
}

int main()
{
int s, ns;

printf("此题使用位运算:\n四位如:0000-从左到右依次为:\n");
printf("农夫、狼、白菜、羊..\n");

for(int i=0;i<16;i++) vis[i]=-1;
vis[0]=0;
Q.push(0);
while(!Q.empty())
{
s=Q.front(); Q.pop();
for(int i=1;i<=8;i=i<<1)
{
if(farmer(s) == (bool)(s&i))   //把每一位与最高位比较
{
ns=s^((1<<3)|i);
if(check(ns) && vis[ns]==-1)
{
vis[ns]=s;
Q.push(ns);
}
}
}
if(vis[15]>=0) break;
}

printf("\n问题的解决方案为:\n");
print(15);
printf("\n");

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: