欢迎挑刺儿!!!
问题描述:从前有一条河,河的左岸有lm个传教士(Missionary)和ls个野人(Cannibal),和一艘最多可乘2人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量少于等于传教士,否则野人会把传教士吃掉。
编程,接收lm和ls,搜索一条可让所有的野人和传教士安全渡到右岸的方案。
当 lm ==l s>3 时无解
lm > ls 时,有解。
#include<iostream> #include <vector> using namespace std; //lm,rm 分别代表左岸右岸的人数 //ls,rs 分别代表左岸右岸的野人数 //ifLeft 1代表船在左岸,0代表船在右岸 struct node { int lm,ls,rm,rs,isLeft; }; int solve(node & n); int isEqual(node & n1,node &n2); int isVisited(node & n); int safe(node & n); vector<node> result; vector<node> visited; int offset1[5][4]={{1,1,-1,-1},{2,0,-2,0},{0,2,0,-2},{1,0,-1,0},{0,1,0,-1}}; int offset2[5][4]={{-1,-1,1,1},{-2,0,2,0},{0,-2,0,2},{-1,0,1,0},{0,-1,0,1}}; int main() { node n; int t1,t2; cin>>t1>>t2; n.lm=t1,n.ls=t2,n.isLeft=1,n.rm=0,n.rs=0; cout<<solve(n)<<endl; for (int i=0;i<result.size();i++) { cout<<result[i].lm<<" "<<result[i].ls<<" "<<result[i].rm <<" "<<result[i].rs<<" "<<result[i].isLeft<<endl; } result.clear(); return 0; } int solve(node & n) { if(n.lm<0 || n.ls<0 || n.rm<0 || n.rs<0) return 0; result.push_back(n); if(n.lm==0 && 0==n.ls) return 1; visited.push_back(n); node newNode; for (int i=0;i<5;i++) { newNode.isLeft=n.isLeft==0 ? 1 : 0; newNode.lm=n.isLeft==1 ? (n.lm + offset2[i][0]) : (n.lm + offset1[i][0]); newNode.ls=n.isLeft==1 ? (n.ls + offset2[i][1]) : (n.ls + offset1[i][1]); newNode.rm=n.isLeft==1 ? (n.rm + offset2[i][2]) : (n.rm + offset1[i][2]); newNode.rs=n.isLeft==1 ? (n.rs + offset2[i][3]) : (n.rs + offset1[i][3]); if(safe(newNode) && isVisited(newNode)==0) if(solve(newNode)) return true; } result.pop_back(); visited.pop_back(); return false; } int isEqual(node & n1,node &n2) { return ( n1.isLeft==n2.isLeft && n1.lm==n2.lm && n1.ls==n2.ls && n1.rm==n2.rm && n1.rs==n2.rs); } int isVisited(node & n) { for (int i=0;i<visited.size();i++) { if(isEqual(n,visited[i])) return true; } return false; } int safe(node & n) { if(n.lm==0 || n.rm==0) return 1; if(n.rm < n.rs || n.lm < n.ls) return 0; return 1; }