农夫、羊、菜和狼的故事
题目描述
有一个农夫带一只羊、一筐菜和一只狼过河。如果没有农夫看管,则狼要吃羊,羊要吃菜。但是船很小,只够农夫带一样东西过河。问农夫该如何解此难题?
输入描述:
题目没有任何输入。
输出描述:
题目可能有种解决方法,求出步骤最少的解决方法,
按顺序输出农夫想把羊、菜、狼全部运过河需要哪几个步骤。
如果需要将羊带过河去则输出“sheep_go”。
如果需要将羊带回来则输出“sheep_come”。
如果需要将菜带过河去则输出“vegetable_go”。
如果需要将菜带回来则输出“vegetable_come”。
如果需要将狼带过河去则输出“wolf_go”。
如果需要将狼带回来则输出“wolf_come”。
如果需要空手返回则输出“nothing_come”。
如果需要空手过河则输出“nothing_go”。
每输出一种方案,输出一行“succeed”。
解题思路
农夫过河问题,用0000的二进制分别代表河的一岸的农夫、羊、菜、狼,假如农夫带狼过河则0000变为1001。
总共有16种状态,每次过河的操作(8种操作)都会变成另外一个状态,直到得到1111,可以得到一个状态树,保存满足条件的路径。
不满足题目要求的状态有1001(9),0110(6),1000(8),1010(10),0101(5),0111(7),即5~10都不合法。
建立一个当前搜索队列,保存遍历的状态,出现重复的状态则不进行这次变化(避免死循环),若队尾出现0,退出搜索。
解决代码
#include<iostream>
#include<queue>
using namespace std;
queue<int> q;
int visit[20];//用来保存当前状态的前一状态,注意不能直接int visit[20]={-1}初始化,初始化成0可以,但其他数字要用循环老老实实一个一个赋值
int a[4]={8,12,10,9};//用来表示4种状态转换操作:8(1000)——nothing;12(1100)——sheep;10(1010)——vegetable;9(1001)——wolf。
bool judge(int x){//用来判断是否为合法状态
if(x>=5&&x<=10) return false;
else if(x>15 || x<0) return false;
else if(visit[x]!=-1) return false;
else return true;
}
void BFS(){ //树的广度搜索,寻找最短路径
int current=q.front();
q.pop();
for(int i=0;i<4;i++ ){ //每次有四种选择,空船,带羊,带菜,带狼
int next=a[i]^current; //异或运算,相同为0,不同为1,即求出当前的运动状态
if(judge(next)){
q.push(next);
visit[next]=current; //visit[当前状态]=当前状态的前一个状态
if(next == 15) return; //15(1111)
}
}
BFS();
}
void print_result(int a,int b){
switch(b-a){
case -8:cout<<"nothing_come"<<endl;break;
case -12:cout<<"sheep_come"<<endl;break;
case -10:cout<<"vegetable_come"<<endl;break;
case -9:cout<<"wolf_come"<<endl;break;
case 8:cout<<"nothing_go"<<endl;break;
case 12:cout<<"sheep_go"<<endl;break;
case 10:cout<<"vegetable_go"<<endl;break;
case 9:cout<<"wolf_go"<<endl;break;
}
}
int main(){
int start=0;
for(int i=0;i<16;i++) visit[i]=-1; //初始化16种状态
q.push(start); //从0000开始
visit[start]=-2; //标记源节点
BFS();
int x=15; //15(1111)
int re[20];//根据visit数组来获得路径顺序,即状态序列
int index=0;
while(x!=-2){
re[index++]=x;
x=visit[x];
}
for(int i=index-1;i>0;i--){//根据a数组即状态序列的变换打印状态转换过程
print_result(re[i],re[i-1]);
}
cout<<"succeed"<<endl;
return 0;
}