题目描述:有一个农夫带一只羊、一筐菜和一只狼过河。如果没有农夫看管,则狼要吃羊,羊要吃菜。但是船很小,只够农夫带一样东西过河。问农夫该如何解此难题?
输入描述:
题目没有任何输入。
输出描述:
题目可能有种解决方法,求出步骤最少的解决方法, 按顺序输出农夫想把羊、菜、狼全部运过河需要哪几个步骤。 如果需要将羊带过河去则输出“sheep_go”。 如果需要将羊带回来则输出“sheep_come”。 如果需要将菜带过河去则输出“vegetable_go”。 如果需要将菜带回来则输出“vegetable_come”。 如果需要将狼带过河去则输出“wolf_go”。 如果需要将狼带回来则输出“wolf_come”。 如果需要空手返回则输出“nothing_come”。 如果需要空手过河则输出“nothing_go”。 每输出一种方案,输出一行“succeed”。
本来想找个OJ测下的,无奈找不到,只有这个OJ有这道题(也是,这个题知道答案的话七行打表就出来了,确实没啥意思)
使用DFS做,对狼羊人菜的位置状态pos进行枚举,最初置pos数组全为1,最终pos数组全为1则过河成功,且搜索中不允许出现重复的状态(否则人可以过来,过去,又过来,又过去...这样的搜索不仅没有意义,而且递归是出不来的)。由于pos数组只有4个非0即1的量,可以用四位二进制数表示,于是就有了visited数组来标志状态是否已重复,重复就过了,不继续搜了。以下是代码:
#include<iostream>
#include<vector>
#include<string>
enum object{
MAN, SHEEP, WOLF, VEGETABLE
};
std::string names[4]={"nothing", "sheep", "wolf", "vegetable"};
bool visited[16];
std::vector<std::string> ret;
std::vector<std::string> path;
int make_idx(std::vector<int>& pos){
return pos.at(0)+(pos.at(1)<<1)+(pos.at(2)<<2)+(pos.at(3)<<3);
}
bool check_valid(std::vector<int>& pos){
return pos[MAN]==pos[SHEEP]||(pos[SHEEP]!=pos[WOLF]&&pos[SHEEP]!=pos[VEGETABLE]);
}
bool check_success(std::vector<int>& pos){
return pos[SHEEP]==1&&pos[MAN]==1&&pos[WOLF]==1&&pos[VEGETABLE]==1;
}
template<typename T> void print_vec(std::vector<T>& pos){
for(auto item:pos){
std::cout<<item<<std::endl;
}
}
void dfs(std::vector<int>& pos){
if(!check_valid(pos)) return;
if(check_success(pos)){
if(ret.empty()||ret.size()>path.size()){
ret.assign(path.begin(), path.end());
}
return;
}
std::string direction = pos[MAN]==1?"come":"go";
for(int i=MAN; i<=VEGETABLE;++i){
// man go/come
std::vector<int> new_pos(pos);
new_pos[MAN]=1-new_pos[MAN];
if(i!=MAN){
// take something
if(new_pos[i]!=new_pos[MAN]){
new_pos[i]=new_pos[MAN];
}else continue;
}
int pos_idx=make_idx(new_pos);
if(visited[pos_idx]) continue;
path.push_back(names[i]+"_"+direction);
visited[pos_idx]=true;
dfs(new_pos);
visited[pos_idx]=false;
path.pop_back();
}
}
int main(){
std::vector<int> pos = {0,0,0,0};
dfs(pos);
print_vec(ret);
return 0;
}
理论上来说7次就是最小渡河次数,但应该是有2种7次渡河方法的,这里偷懒没写了~