农夫过河问题C++递归实现

来源:互联网 发布:大学网络怎么办理 编辑:程序博客网 时间:2024/06/05 01:06
一个农夫带着—只狼、一只羊和—棵白菜,身处河的南岸。他要把这
些东西全部运到北岸。他面前只有一条小船,船只能容下他和—件物
品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能
吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自
己离开,也不能留下狼和羊自己离开,而狼不吃白菜。请求出农夫将
所有的东西运过河的方案。

/* * Farmer cross river with wolf, sheep and cabbage * Depth first search implementation. * Author: ProHanziiee * E-mail: huangnanhan@outlook.com * Date: 2017-11-16 */#include <bits/stdc++.h>using namespace std;enum Item{nothing, wolf, sheep, cabbage};map<Item, Item> foodChain;map<Item, Item> reverseFoodChain;set<Item> sideA, sideB;bool check(set<Item> s) {  for(auto &x : s) {    if(s.find(foodChain[x]) != s.end() || s.find(reverseFoodChain[x]) != s.end()) return false;  }  return true;}vector<Item> v;map<pair<int, pair<int, Item> >, pair<int, pair<int, Item> > > trace;pair<int, pair<int, Item> > endPath;bool dfs(int dir, Item item, pair<int, pair<int, Item> > path) {   if(dir == 0) { // dir = 0 means transfer item(may be nothing) from sideA to sideB    if(item != nothing) sideB.insert(item);        if((int)sideB.size() == 3)  { // Okay, all items have heen transfered from sideA to sideB      endPath = path;      return true;    }    if(check(sideB) == true) {      endPath = make_pair(path.first + 1, make_pair(1, nothing));      trace[endPath] = path;      if(dfs(1, nothing, endPath) == true) return true;    }     for(int i = 0; i < 3; ++i) {      Item tmp = v[i];      if(tmp == item || sideB.find(tmp) == sideB.end()) continue;      sideB.erase(sideB.find(tmp));      if(check(sideB) == true) {        endPath = make_pair(path.first + 1, make_pair(1, tmp));        trace[endPath] = path;        if(dfs(1, tmp, endPath) == true) return true;      }      sideB.insert(tmp);    }    sideB.erase(item);  } else { // dir = 1 means transfer item(may be nothing) from sideB to sideA    if(item != nothing) sideA.insert(item);    if(sideA.size() == 3) return false;    for(int i = 0; i < 3; ++i) {      Item tmp = v[i];      if(tmp == item || sideA.find(tmp) == sideA.end()) continue;      sideA.erase(sideA.find(tmp));      if(check(sideA) == true) {        endPath = make_pair(path.first + 1, make_pair(0, tmp));        trace[endPath] = path;        if(dfs(0, tmp, endPath) == true) return true;      }      sideA.insert(tmp);    }  }  return false;}void init() {  trace.clear();  sideA.clear();  sideB.clear();  foodChain.clear();  reverseFoodChain.clear();  foodChain[wolf] = sheep;  reverseFoodChain[sheep] = wolf;  foodChain[sheep] = cabbage;  reverseFoodChain[cabbage] = sheep;  v.clear();  v.push_back(wolf);  v.push_back(sheep);  v.push_back(cabbage);}void outputItem(Item item) {  switch(item) {    case wolf: puts("Wolf");      break;    case sheep: puts("Sheep");      break;    case cabbage: puts("Cabbage");      break;    default: puts("Nothing");  }}void outputDirection(int dir) {  if(dir == 0) { printf("A -> B with "); }  else { printf("B -> A with "); }}void outputTrace() {   puts("A is the initial side of river while B is the target side!");   while(endPath != make_pair(-1, make_pair(-1, nothing))) {     outputDirection(endPath.second.first);      outputItem(endPath.second.second);     endPath = trace[endPath];   }}int main() {  #ifdef Zonda_R    freopen("data.in", "r", stdin);    freopen("data.out", "w", stdout);  #endif  init();    sideA.insert(wolf);  sideA.insert(sheep);  sideA.insert(cabbage);   bool valid = false;     for(int i = 0; i < 3; ++i) {    Item tmp = v[i];    if(sideA.find(tmp) != sideA.end()) {      sideA.erase(sideA.find(tmp));        if(check(sideA) == true) {         trace.clear();        endPath = make_pair(0, make_pair(0, tmp));         trace[endPath] = make_pair(-1, make_pair(-1, nothing));        if(dfs(0, tmp, endPath) == true) {          valid = true;           break;         }      }      sideA.insert(tmp);    }  }  if(valid == true) {    outputTrace();  } else {    puts("No Solution!");  }  return 0;}


原创粉丝点击