题目描述
有一个农夫带一只羊、一筐菜和一只狼过河。如果没有农夫看管,则狼要吃羊,羊要吃菜。但是船很小,只够农夫带一样东西过河。问农夫该如何解此难题?
输入描述:
题目没有任何输入。
输出描述:
题目可能有种解决方法,求出步骤最少的解决方法,
按顺序输出农夫想把羊、菜、狼全部运过河需要哪几个步骤。
如果需要将羊带过河去则输出“sheep_go”。
如果需要将羊带回来则输出“sheep_come”。
如果需要将菜带过河去则输出“vegetable_go”。
如果需要将菜带回来则输出“vegetable_come”。
如果需要将狼带过河去则输出“wolf_go”。
如果需要将狼带回来则输出“wolf_come”。
如果需要空手返回则输出“nothing_come”。
如果需要空手过河则输出“nothing_go”。
每输出一种方案,输出一行“succeed”。
代码
#include<iostream>
#include<vector>
using namespace std;
typedef struct Record{
int passage;//0 vegetables ; 1 sheep ; 2 wolf ;3 nothing
int ifgo; //1 go ; 0 come
Record(int a,int b):passage(a),ifgo(b){}
}Record;
vector<vector<Record> > result; //存储可行的乘船经历
vector<Record> rec; //记录当前状态
int goline[3]={1,1,1}; //等待过河的队伍的存在状态,1代表在,0代表不在(即在对面),3代表在渡船,下标0代表蔬菜,1代表羊,2代表狼
void goRiver(int lastPass);
void comeRiver(int lastPass);
bool ifFeasible(){
if(goline[2]==goline[1]||goline[1]==goline[0]) return false;
return true;
}
bool ifEnd(){
for(int i=0;i<3;i++){
if(goline[i]!=0) return false;
}
return true;
}
void goRiver(int lastPass){
for(int i=0;i<3;i++){
if(goline[i]&&i!=lastPass){
goline[i]=3;
if(ifFeasible()){
goline[i]=0;
Record q(i,1);
rec.push_back(q);
comeRiver(i);
goline[i]=1;
rec.pop_back();
}else{
goline[i]=1;
}
}
}
return;
}
void comeRiver(int lastPass){
if(ifEnd()){
result.push_back(rec);
return;
}
if(ifFeasible()){
Record q(3,0);
rec.push_back(q);
goRiver(lastPass);
rec.pop_back();
}else{
for(int i=0;i<3;i++){
if(goline[i]==0&&i!=lastPass){
goline[i]=3;
if(ifFeasible()){
goline[i]=1;
Record q(i,0);
rec.push_back(q);
goRiver(i);
goline[i]=0;
rec.pop_back();
}else{
goline[i]=0;
}
}
}
}
return;
}
int minRecord(){
int minnum=10000;
for(int i=0;i<result.size();i++){
if(result[i].size()<minnum) minnum=result[i].size();
}
return minnum;
}
void printProcess(int n){
for(int i=0;i<result[n].size();i++){
string a,b;
switch(result[n].at(i).passage){
case 0:
a="vegetable_";
break;
case 1:
a="sheep_";
break;
case 2:
a="wolf_";
break;
case 3:
a="nothing_";
break;
}
switch(result[n].at(i).ifgo){
case 0:
b="come";
break;
case 1:
b="go";
break;
}
cout<<a<<b<<endl;
}
}
int main(){
goRiver(-1);
int minnum=minRecord();
for(int i=0;i<result.size();i++){
if(result[i].size()==minnum){
printProcess(i);
cout<<"succeed"<<endl;
}
}
}
小结:
最近因为准备复试,在学算法,这题我觉得我用的是回溯法,步骤大致如下:
1.定义一个数组goline[3]存放菜,羊,狼的状态,1代表未过河,0代表过河了,3代表正在船上
2.用回溯法,依次考虑三者过河,先考虑当它在船上时(状态为3),是否能满足没有被吃的现象,即ifFeasible(),如果满足,就过河,即状态变为0,然后又在河对岸的当前队伍中考虑回来的情况,循环;如果不满足,就又恢复原始状态为1,继续循环。
3.当每次船在河对岸时,用ifEnd()判断是否全部都渡河了
感觉代码有点长,应该还有改进的地方,慢慢看,先记录下来