问题描述:三个传教士和三个野人过河, 只有一条能装下两个人的船,在河的任何一方或者船上,野人的数量不能多于传教士的数量,如果野人的人数大于传教士的人数,那么传教士就会被吃掉。问采用何种渡河方法,可以安全过河,输出渡河的方式;
问题分析:
初始状态:船停靠在左岸
左岸:3个传教士,3个野人;
右岸:0个传教士,0个野人;
结束状态:船停靠在右岸
左岸:0个传教士,0个野人;
右岸:3个传教士,3个野人;
由于任何时刻野人的数量不能多于传教士的数量,所以一次渡河的方式如下:
1、渡一个传教士;
2、渡一个野人;
3、渡一个野人一个传教士;
4、渡两个传教士;
5、渡两个野人。
本算法可以通过状态空间法来求解,将渡河问题抽象成一系列状态的改变问题。
1、定义结构体,并定义结构体数组,用于存储状态结点信息;
2、编写状态空间函数:
1、判断当前状态是否与目标状态一致,若是,打印数组信息;
2、判断是否在遍历的过程中出现重复的渡河方式;
3、控制野人的数量与传教士的数量,使其满足(野人数<=传教士数);
4、写入全部渡河方式;
3、在主函数中给野人和传教士人数赋值,将值传给结构体数组,并调用状态空间函数检索渡河方法。
完整代码:
#include <stdio.h>
#define MAX 100
//状态节点定义
struct status
{
int left_c;
int right_c;
int left_y;
int right_y;
int boat_location;
};
struct status arr[MAX];
int index=0;
int count=0;
int y_num=3,c_num=3;
int judge(status t);
void main()
{
printf("\n...........检索开始..............\n");
arr[index].left_c = y_num;
arr[index].left_y = c_num;
arr[index].right_c = 0;
arr[index].right_y = 0;
arr[index].boat_location = 1;
judge(arr[index]);
printf("已为您找到%d条过河路径!并且已全部加载完毕!\n",count);
}
int judge(status t)
{
if( t.right_c == y_num && t.right_y == c_num)//判断当前状态是否达到目标转态
{
count++;
printf("\n找到第%d条路径!\n",count);
printf("左传\t左野\t右传\t右野\t船\n");
for(int i = 0; i <= index ; i++)
{
printf("%2d\t",arr[i].left_c);
printf("%2d\t",arr[i].left_y);
printf("%2d\t",arr[i].right_c);
printf("%2d\t",arr[i].right_y);
printf("%2d\t",arr[i].boat_location);
printf("\n");
}
return 0;
}
//判断有是否重复操作
for(int i = 0; i < index; i++)
{
if(t.left_c == arr[i].left_c && t.left_y == arr[i].left_y)
{
if(t.boat_location == arr[i].boat_location)
{
return 0;
}
}
}
//人数是否合理吗
if(t.left_c < 0 || t.left_y < 0 || t.right_c < 0 || t.right_y < 0 )
{
return 0;
}
//传教士是否被吃
if((t.left_c < t.left_y && t.left_c != 0) || (t.right_c < t.right_y && t.right_c != 0) )
{
return 0;
}
//定义一个临时节点
struct status tt;
//一个传教士过河
tt.left_c = t.left_c - 1 * t.boat_location;
tt.left_y = t.left_y;
tt.right_c = t.right_c + 1 * t.boat_location;
tt.right_y = t.right_y;
tt.boat_location = ( -t.boat_location);
index = index + 1;
arr[index] = tt;
judge(arr[index]);
index = index-1;
//一个野人过河
tt.left_c = t.left_c;
tt.left_y = t.left_y - 1 * t.boat_location;
tt.right_c = t.right_c;
tt.right_y = t.right_y + 1 * t.boat_location;
tt.boat_location = ( -t.boat_location);
index = index + 1;
arr[index] = tt;
judge(arr[index]);
index = index-1;
//一个野人,一个传教士过河
tt.left_c = t.left_c - 1 * t.boat_location;
tt.left_y = t.left_y - 1 * t.boat_location;
tt.right_c = t.right_c + 1 * t.boat_location;
tt.right_y = t.right_y + 1 * t.boat_location;
tt.boat_location = ( -t.boat_location);
index = index + 1;
arr[index] = tt;
judge(arr[index]);
index = index-1;
//两个传教士过河
tt.left_c = t.left_c - 2 * t.boat_location;
tt.left_y = t.left_y;
tt.right_c = t.right_c + 2 * t.boat_location;
tt.right_y = t.right_y;
tt.boat_location = ( -t.boat_location);
index = index + 1;
arr[index] = tt;
judge(arr[index]);
index = index - 1;
//两个野人过河
tt.left_c = t.left_c;
tt.left_y = t.left_y - 2 * t.boat_location;
tt.right_c = t.right_c ;
tt.right_y = t.right_y + 2 * t.boat_location;
tt.boat_location = ( -t.boat_location);
index = index + 1;
arr[index] = tt;
judge(arr[index]);
index = index-1;
return 0;
}