// test.cpp : Defines the entry point for the console application.
//
#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>=4&&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是否为0
bool bf = false; //当b变为0后赋值为true;
bool ef = false; //当a==b后赋值为true
bool f = false; //判断n是否大于m/2
int 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/2
if(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/2
else
{
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); //递归
else
crossing(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/2
crossing(a+1,b+1,1-c); //递归
}
}
}