野人过河问题(一)

来源:互联网 发布:java线程代码 编辑:程序博客网 时间:2024/05/17 02:58
//--------- 野人过河问题(一) -------------//Missionaries.cpp:Defines the entry point for the console application.//注:去掉#include <stdafx.h>,一般除MFC工程外,都不使用预编译头。//#include "stdafx.h"/*实验原理:假设开始时传教士、野人和船都在右岸,用数组(a,b,c)分别表示右岸传教士个数、右岸野人个数、船的位置,  则可分为三种情况讨论:  A、 n>m/2。此种情况下,先把所有的野人渡过去,每次返回一个野人,当出现(m,0,0)情况时,返回m-n个野人(若m==n,返回1个  野人)。然后渡n个传教士,此时野人==传教士,然后返回一个野人和传教士,再开始最大限度的渡传教士,每次返回一个人,最终知道a==b==c==0;  B、n<=3 && n<=m/2 || n==1,显然此时无解;  C、n>=3 && n<=m/2,此时只能每次传n/2个传教士和野人,每次返回一个野人和传教士,直到最终结果。  初始状态是s(m,m,1)---最终状态是s(0,0,0)*/#include "iostream"using namespace std;bool flag = false; //标记是否有解bool af = false; //标记a是否为0bool bf = false; //当b变为0后赋值为true;bool ef = false; //当a==b后赋值为truebool  f = false; //判断n是否大于m/2int   m; //传教士野人的个数int   n; //船一次能装载的人数void crossing(int a,int b,int c);int main(){cout<<"传教士与野人过河问题。\n假设最初时传教士与野人在河的右岸。\n";cout<<"请输入传教士野人的个数:\n";cin>>m;cout<<"请输入船一次能装载的个数:\n";cin>>n;cout<<"右岸传教士个数\t"<<"右岸野人个数\t"<<"船的位置(1、右岸 0、左岸)"<<endl;if((n<=3 && n<=m/2) || n==1)//此种情况无解{cout<<"No solution!\n";system("pause"); //请按任意键继续return 0;}if(n > m/2){f = true;}//调用函数crossing(m,m,1);if(flag == true){cout<<"Success!\n";}else{cout<<"No solution!\n";}system("pause");return 0;}void crossing(int a,int b,int c){if(flag == true){return;}else{if(c == 1)//船在右岸时:{cout<<"\t"<<a<<"\t\t"<<b<<"\t\t"<<c<<"\t\n";//如果n>m/2if(f == true){if(bf!=true) //b未达到过0 b!=0{if(a+b<=n) //如果a+b<=n,完全渡过{crossing(0,0,1-c); //递归}else{for(int j = n; j >= 0; j--){if(b >= j) //野人数大于或等于船的载量{crossing(a,b-j,1-c); //递归if(flag==true)return;}}}}else if(ef!=true && af == false) //b!=0 && a!=0{for(int i = n; i >= 0; i--){if(a >= i){crossing(a-i,b,1-c); //递归if(flag == true){return;}}}}if(ef == true && af ==false) //a==b && a!=0{if(a>=n){crossing(a-n,b,1-c); //递归}//如果a<n时else if(a+b<n){crossing(0,0,1-c);}else{crossing(0,b-(n-a),1-c);}}if(af == true)//a==0{if(b>=n){crossing(a,b-n,1-c); //递归}else{crossing(a,0,1-c);}}}//n<=m/2else{crossing(a-n/2,b-n/2,1-c); //递归}}//船在左岸时,右岸的情况if( c == 0){cout<<"\t"<<a<<"\t\t"<<b<<"\t\t"<<c<<"\t\n";if(a == b && b == c && a == 0){flag = true;return;}if(f == true) //如果n>m/2{if( b == 0 ){bf = true;if(m <= n)crossing(a,b+1,1-c); //递归elsecrossing(a,b+m-n,1-c);}if(a == b){ef = true;crossing(a+1,b+1,1-c); //递归}if(a == 0){af = true;crossing(a,b+1,1-c); //递归}while(bf!=true){crossing(a,b+1,1-c); //递归}}else //n<=m/2crossing(a+1,b+1,1-c); //递归}}}

0 0
原创粉丝点击