修道士和野人问题

题目:

设在河的一岸有三个野人、三个修道士和一条船,修道士想用这条船把所有的人运到河对岸,但受以下条件的约束:

一是修道士和野人都会划船,但每次船上至多可载两个人;
二是在河的任一岸,如果野人数目超过修道士数,修道士会被野人吃掉。

如果野人会服从任何一次过河安排,请规划一个确保修道士和野人都能过河,且没有修道士被野人吃掉的安全过河计划。

代码一(暴力搜索):

#include 
#include 
#include 
#include 

using namespace std;

vector visit;

int numofchurch, numofwild, boatload;     //分别表示传教士总人数,野人总人数,船载客量
int totalanswer = 0;                      //解法数目

bool check(int M, int C, int flag)
{
	if ((flag != 0) && (flag != 1))
		return false;
	if (M<0 || C<0 || numofchurch - M<0 || numofwild - C<0)           //人数不得小于0
		return false;
	if ((M&&M0; i--)          //船本次载了i个人
	{
		for (j = i; j >= 0; j--)        //j为运送的传教士人数
		{
			k = i - j;                 //k为运送的野人数
			if (check(M - j, C - k, flag - 1))
			{
				path(M - j, C - k, flag - 1);
				visit.pop_back();
			}
			else if (check(M + j, C + k, flag + 1))
			{
				path(M + j, C + k, flag + 1);
				visit.pop_back();


			}
		}
	}
}


int main()
{
	int flag = 1;                         //flag=1表示船在左岸
	char s[30];
	cout << "输入传教士数、野人数和船载客量(三个数字以空格间隔):" << endl;
	cin >> numofchurch >> numofwild >> boatload;
	sprintf(s, "M=%d, C=%d, flag=%d", numofchurch, numofwild, flag);
	visit.push_back(s);
	path(numofchurch, numofwild, flag);
	if (totalanswer != 0)
		cout << "Total answer: " << totalanswer << endl;
	else
		cout << "FAIL!" << endl;
	system("pause");
}

代码二(A*算法):

#include  
#include 
#include 

using namespace std;

int X, Y;
int k;

struct node
{
	int q[3];
};

vector s;
int q[500][3];
//用于存放搜索结点,q[][0]是左岸传教士人数
//q[][1]是左岸野蛮人人数,q[][2]是左岸船的数目
//q[][3]用于搜索中的父亲结点序号。
int ans = 0;

int op_num = 0;
int go[500][2];
int fx[500][500];

//安全状态:左岸中,传教士都在or都不在or传教士人数等于野人人数 
int is_safe(int state[3])
{
	if ((state[0] == 0 || state[0] == X || state[0] == state[1]) && (state[1] >= 0) && (state[1] <= Y))
	{
		return 1;
	}
	return 0;
}

//是否到达目标状态 
int is_success(int state[3])
{
	if (state[0] == 0 && state[1] == 0)
		return 1;
	return 0;
}

//该状态是否已经访问过 
int vis(int state[3])
{
	for (vector::iterator it = s.begin(); it != s.end(); it++)
		if ((*it).q[0] == state[0] && (*it).q[1] == state[1] && (*it).q[2] == state[2])
			return 1;
	return 0;
}


int f2(int state[3])
{
	return state[0] + state[1] - k * state[2];
}


int find_min(int cur)
{
	int min = 10000;
	int op = -1;
	for (int j = 0; j < op_num; j++)//分别考虑可能的动作
	{
		if (fx[cur + 1][j] < min)
		{
			min = fx[cur + 1][j];
			op = j;
		}
	}
	if (min == 10000)
		op = -1;
	return op;
}


//过河操作
int search(int cur)
{
	if (is_success(q[cur]))
	{
		ans = cur;
		return 1;
	}
	int state[3];
	int j;
	//cout<<"第"<> n;
	cout << "请输入k:";
	cin >> k;
	X = Y = n;

	int state[3];
	//初始状态 
	node nd;
	nd.q[0] = state[0] = q[0][0] = X;
	nd.q[1] = state[1] = q[0][1] = Y;
	nd.q[2] = state[2] = q[0][2] = 1;

	s.push_back(nd);
	//初始化操作
	cout << "合法的操作组有:" << endl;
	for (int i = 1; i <= k; i++)
		for (int j = 0; j <= i; j++)
		{
			if (j >= i - j || j == 0)
			{
				go[op_num][0] = j;
				go[op_num][1] = i - j;
				cout << go[op_num][0] << ' ' << go[op_num][1] << endl;
				op_num++;
			}
		}
	cout << endl;
	if (!search(0))
	{
		cout << "无解" << endl;
		return 0;
	}
	cout << "找到的解为:" << endl;
	for (int i = 0; i <= ans; i++)
	{
		//cout< 0)
		{
			cout << abs(q[i][0] - q[i - 1][0]) << "个传教士和" << abs(q[i][1] - q[i - 1][1]) << "个野人";
			if (q[i][2])
				cout << "从右岸乘船至左岸" << endl;
			else
				cout << "从左岸乘船至右岸" << endl;
			cout << "左岸有" << q[i][0] << "个传教士和" << q[i][1] << "个野人" << endl;
			cout << "右岸有" << n - q[i][0] << "个传教士和" << n - q[i][1] << "个野人" << endl << endl;
		}
	}

	cout << "本次搜索所花费的费用:" << ans << endl;
	system("pause");
	return 0;
}

你可能感兴趣的:(工作学习收获)