传教士和野人问题实验报告
求解野人与传教士问题1
题目分析:
定义节点的结构:以取般的一个来回作为一步搜索,这样节点可由下面几个量进行描述:两岸的传教士人数和野人人数、本节点距离起始节点的距离,即由初始节点搜索几步后到达本节点。需要注意的是并不是所有节点都是可达的,题目中对可达节点作出了限制,只有两大 岸上的人数必须不能为负。
void goon(); //判断是否继续搜索
void main()
{
int flag; //标记扩展是否成功
for(;;)
{
initiate();
flag=search()
if(flag==1)
releasemem();
goon();
}
}
}
void initiate()
{
int x;
char choice;
uend=unopened=(struc SPQ*)malloc(sizeof(spq));
void releasemem(); //释放占用内存
void showresult(); //显示解
void addtoopened(struc SPQ *ntx); //将节点ntx从UNOPENED链表移至OPRNENED
//链表中
newnode -> sst = sst;
newnode -> spt = spt;
newnode -> ssr = 0
newnode -> spr = 0
修道士和野人问题
修道⼠和野⼈问题 休闲时刻看看神经⽹络⽅⾯的书,发现了修道⼠和野⼈的问题,不禁勾引起我写算法的欲望,曾经的三只⼤⽼虎三只⼩⽼虎过河问题、⼈狼⽺⽩菜过河问题、汉诺塔、哈夫曼等等各种算法瞬间在脑海中约隐约现,修道⼠和野⼈问题我以前好像没有解开,中午吃饭的时候在脑海中重新构造思路,下午耗了点时间把它⼲掉。
(算法不在代码⾥,⽽在思想中;所以尽量不要看我的代码,⽽要仔细分析我写的思路) 题⽬: 设有3个修道⼠和3个野⼈来到河边,打算⽤⼀条船从河的左岸渡到河的右岸。
但该船每次只能装载两个⼈,在任何岸边野⼈的数⽬都不得超过修道⼠的⼈数,否则修道⼠就会被野⼈吃掉。
假设野⼈服从任何⼀种过河安排,请问如何规划过河计划才能把所有⼈都安全地渡过河去。
⾸先考虑总共有(3+1)*(3+1)= 16 种不同的状态(因为左岸可以有0,1,2,3个传教⼠,左岸可以有0,1,2,3个野⼈),所以可以考虑使⽤穷举法。
使⽤如下C#程序语⾔:int MaxNum = 3;for (int monk = MaxNum; monk >= 0; monk--){for (int savage = MaxNum; savage >= 0; savage--){Console.Write("{{" + monk + "," + savage + "},{" + (MaxNum - monk) + "," + (MaxNum - savage) + "}} ");}Console.Write("\n");}⽣成16种状态图↓↓↓↓↓↓↓↓↓↓↓状态图含义:{a,b}:a,左岸修道⼠数量;b,左岸野⼈数量。
--------仅考虑左岸传教⼠和野蛮⼈数量(所有状态图)------------------------{3,3} {3,2} {3,1} {3,0}{2,3} {2,2} {2,1} {2,0}{1,3} {1,2} {1,1} {1,0}{0,3} {0,2} {0,1} {0,0}其中{3,3}是起始状态图;{0,0}是终⽌状态图。
传教士(牧师)与野人问题-模拟人工智能实验_CSDN博客_传教士与野人问题
传教士(牧师)与野人问题-模拟人工智能实验_结缘缘的博客-CSDN博客_传教士与野人问题题目有n个牧师和n个野人准备渡河但只有一条能容纳c个人的小船为了防止野人侵犯牧师要求无论在何处牧师的人数不得少于野人的人数(除非牧师人数为0) 且假定野人与牧师都会划船试设计一个算法确定他们能否渡过河去若能则给出小船来回次数最少的最佳方案。
实验步骤输入牧师人数(即野人人数) n 小船一次最多载人量c。
输出若问题无解则显示Failed 否则显示Successed输出所有可行方案并标注哪一组是最佳方案。
用三元组(X1, X2, X3)表示渡河过程中的状态。
并用箭头连接相邻状态以表示迁移过程初始状态- 中间状态- 目标状态。
例当输入n 2 c 2时输出221- 200- 211- 010- 021- 000 其中X1表示起始岸上的牧师人数X2表示起始岸上的野人人数X3表示小船现在位置(1表示起始岸0表示目的岸)。
要求写出算法的设计思想和源程序并有用户界面实现人机交互控制台或者窗口都可以进行输入和输出结果如Please input n: 2 Please input c: 2 Optimal Procedure: 221- 200- 211- 010- 021- 000Successed or Failed?: Successed实现代码#include stdio.h #include iostream #include stdlib.h using namespace std;struct State { int Lsavage; int Lgodfather; int Rsavage; int Rgodfather; int boat; //boat at left 0 ; boat at right struct State *States new State[150];struct routesave { int savage; int godfather;struct routesave* routesaves new routesave[150];int godfather, savage, boatnum;void init(State m) { cout 请输入野人和牧师的人数n 以及船的最大载量c endl; int n, c; cin n c; m.Rgodfather n; m.Rsavage n; godfather n, savage n; boatnum c; m.Lgodfather m.Lsavage 0; m.boat 1;void boaloading(int i, int s, int g) { //s个野人和g个传教士if (States[i].boat 0) { routesaves[i].savage s*-1; //左边到右边是负数个野人routesaves[i].godfather g * -1; //左边到右边负数个传教士States[i 1].LsavageStates[i].Lsavage - s; States[i 1].Lgodfather States[i].Lgodfather - g; States[i 1].Rsavage States[i].Rsavage s; States[i 1].Rgodfather States[i].Rgodfather g; States[i 1].boat 1; else{ routesaves[i].savage s; //右边到左边是正数个野人routesaves[i].godfather g; //右边到左边正数个传教士States[i 1].Rsavage States[i].Rsavage-s; States[i 1].RgodfatherStates[i].Rgodfather - g; States[i 1].Lsavage States[i].Lsavage s; States[i 1].Lgodfather States[i].Lgodfather g; States[i 1].boat0;bool checkState(State m) { if (m.Rgodfather 0 m.Rgodfather m.Rsavage) return false; if (m.Lgodfather 0 m.Lgodfatherm.Lsavage) return false; else return true;void showSolution(int i) { cout 问题解决解决路径为endl; for (int c 0; c i; c ) { if (routesaves[c].savage 0) cout 第c 1 步routesaves[c].savage 个野人和routesaves[c].godfather 个传教士乘船去左边endl; else cout 第c 1 步routesaves[c].savage * -1 个野人和routesaves[c].godfather * -1 个传教士乘船去有右边endl; void nextstep(int i) { int c; if (i 150) cout 试探路径过大无法计算; exit(0); for (c 0; c i; c ) /*if the current state is same to previous,retrospect*/ if (States[c].Lsavage States[i].Lsavage States[c].Lgodfather States[i].Lgodfather States[c].Rsavage States[i].Rsavage States[c].Rgodfather States[i].Rgodfather States[c].boat States[i].boat) goto a; if (States[i].Rsavage 0 States[i].Rgodfather 0 States[i].boat 0) { showSolution(i); exit(0); if (States[i].boat 1) { //船在右边for (int s 1; s boatnum s States[i].Rsavage; s ) {//g 0 int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Rgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Rsavage s g; s ) { boaloading(i, s, g); if(checkState(States[i 1])) { nextstep(i 1); if (States[i].boat 0) { //船在左边for (int s 1; s boatnum s States[i].Lsavage; s ) {//g 0int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Lgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Lsavage s g; s ) { boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1);a:return;void main() { init(States[0]); nextstep(0);实验结果展示。
传教士和野人渡河
传教士和野人渡河问题作品报告有5个传教士和5个野人过河,只有一条能装下3个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会有危险。
请设计合适的摆渡方案,并使得所需的摆渡次数最少。
源代码:#include "stdio.h"#include "string.h"#define STEP_MAX 20 //来回过河的最大次数#define NO 5 //野人和传教士各有的人数#define HEAVY 3 //船的最大载重量typedef struct{int wild; //右岸上的野人数int man; //右岸上的传教士数int boat_state; //0表示在左岸,1表示在右岸}state;typedef struct{int wild; //船上的野人数int man; //船上的传教士数int boat_run; //0表示去左岸,1表示去右岸}boat;state now[STEP_MAX]={0}; //保存过河过程中对岸的状态boat path[STEP_MAX]={0}; //保存过河的路径int suit_NO=STEP_MAX; //最合适的过河次数,初始值为一足够的数boat suit_path[STEP_MAX]; //最合适的过河方式//是否全部过河bool All(state c){//右岸的最终状态const state cs={NO,NO,1};if(memcmp(&cs,&c,sizeof(state))==0){return true;}return false;}//传教士是否有危险bool Danger(state ca){if ((ca.wild>ca.man&&ca.man>0)||(NO-ca.wild>NO-ca.man&&NO-ca.man>0)) {return true;}elsereturn false;}//判断该状态是否与前面的一样bool Same(state cs,int n){for (int i=0;i<n;i++){if (memcmp(&cs,&now[i],sizeof(state))==0){return true;}}return false;}//将最短路径保存到suit_path中void Min(int n,boat path[]){if (n<suit_NO){suit_NO=n;memcpy(&suit_path[0],&path[0],n*sizeof(boat));}}//查找过河方案void Cross(int n){int i,j;if (All(now[n])){Min(n,path);return;}if (Danger(now[n])){return;}if (Same(now[n],n)){return;}if(now[n].boat_state==0)//船在左岸时{for(i=0;i<=HEAVY && i<=NO-now[n].wild;i++){for(j=0;j<=HEAVY-i && j<=NO-now[n].man;j++){if (i==0 && j==0){continue;}path[n].wild=i;path[n].man=j;path[n].boat_run=1;memcpy(&now[n+1],&now[n],sizeof(state));now[n+1].wild+=i;now[n+1].man+=j;now[n+1].boat_state=1;Cross(n+1);}}}else//船在右岸时{for(i=0;i<=HEAVY && i<=now[n].wild;i++){for(j=0;j<=HEAVY-i && j<=now[n].man;j++){if (i==0 && j==0){continue;}path[n].wild=i;path[n].man=j;path[n].boat_run=0;memcpy(&now[n+1],&now[n],sizeof(state));now[n+1].wild-=i;now[n+1].man-=j;now[n+1].boat_state=0;Cross(n+1);}}}}void main(){Cross(0);for(int i=0;i<suit_NO;i++){if(path[i].boat_run==0)printf("第%d次过河,从右岸到左岸,船上野人数为%d,传教士数为%d.\n",i+1,suit_path[i].wild,suit_path[i].man);elseprintf("第%d次过河,从左岸到右岸,船上野人数为%d,传教士数为%d.\n",i+1,suit_path[i].wild,suit_path[i].man);}}使用方法:上述程序主要采用了递归调用和近似于枚举的方法。
人工智能:野人与修道士问题
野人与修道士问题(Missionaries-and-Cannibals Problem )[修道士与野人问题]:三个野人与三个传教士来到河边,打算乘一只船从右岸渡到左岸去,该船的最大负载能力为两个人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
用状态空间法表示修道士与野人问题并设计编写计算机程序求问题的解。
问题分析:从上图可知,修道士、野人和船一共有六种可能,M L 、C L 、B L 、M R 、C R 、B R 。
可以表示为q =(M ,C ,B ),其中m 表示修道士的数目(0、1、2、3)、c 表示野人的数目(0、1、2、3)、b 表示船在左岸(1)或右岸(0)。
1、定义状态的描述形式:(m ,c ,b )2、表示所有可能的状态,并确定初始状态集和目标状态集:s0(3,3,1) s8(1,3,1) s16(3,3,0) s24(1,3,0)s1(3,2,1) s9(1,2,1) s17(3,2,0) s25(1,2,0)s2(3,1,1) s10(1,1,1) s18(3,1,0) s26(1,1,0)s3(3,0,1) s11(1,0,1) s19(3,0,0) s27(1,0,0)s4(2,3,1) s12(0,3,1) s20(2,3,0) s28(0,3,0)s5(2,2,1) s13(0,2,1) s21(2,2,0) s29(0,2,0)s6(2,1,1) s14(0,1,1) s22(2,1,0) s30(0,1,0)s7(2,0,1) s15(0,0,1) s23(2,0,0) s31(0,0,0)初始状态:(3,3,1)目标状态:(0,0,0)3、定义算符:L ij :把i 个修道士,j 个野人从河的左岸送到右岸R ij :把i 个修道士,j 个野人从河的右岸送到左岸整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问修道士M野 人C 左L 右R题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师即:L01或R01,L10或R10,L11或R11,L02或R02,L20或R204、状态空间图:5、设计编写计算机程序求问题的解:算法:在应用状态空间表示和搜索方法时,用(M,C,B)来表示状态描述,其中M和C分别表示在左岸的传教士与野人数。
传教士和野人过河
实验报告一、实验名称:传教士和野人过河二、实验目的:这是经典的过河方案规划问题,通过本实验的设计与编程实现让学生掌握基于状态空间知识表示方法的一般搜索策略。
三、实验内容:设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一岸上,也认的数量超过传教士,野人就要吃掉传教士,要求设计算法,用船将3个传教士和3个野人安全的从左岸移到右岸。
四、实验设计(一)所用的语言:c++语言(二)数据结构节点状态用列表(m,c,b)表示,其中m表示传教士在左岸的人数; c表示野人在左岸的人数;b表示船是否在左岸,当b=1时,表示船在左岸,当b=0时,表式船在右岸。
初始状态:(3,3,1)目标状态: (0,0,0)操作算子:船上人数组合(m,c)共5种(1,0),(1,1),(2,0),(0,1),(0,2)因此算法有10种1)从右岸向左岸过1个传教士,0个野人2)从右岸向左岸过1个传教士,1个野人3)从右岸向左岸过2个传教士,0个野人4)从右岸向左岸过0个传教士,1个野人5)从右岸向左岸过0个传教士,2个野人6)从左岸向右岸过1个传教士,0个野人7)从左岸向右岸过1个传教士,1个野人8)从左岸向右岸过2个传教士,0个野人9)从左岸向右岸过0个传教士,1个野人10)从左岸向右岸过0个传教士,2个野人状态节点: typedef struct st{int m;//传教士int c;//野人int b;//船左}state;//状态将有效的节点存储在树中Tree 中的节点typedef struct hnode{state s;struct hnode *left;struct hnode *right;}node;Open表,closed表用队列存储//定义队列中的节点typedef struct Queuenode{node * np;struct Queuenode* next;}Qnode;//队列中节点//定义队列typedef struct Queue{Qnode *front;Qnode *rear;}queue;(三)算法流程1.用起始节点(3,3,1) 初始化tree,初始化open表,closed表。
传教士和野人问题
传教士和野人问题(Missionaries and Cannibals)传教士和野人问题是一个经典的智力游戏问题。
在这个问题中,实际上隐含了这样一个条件:如果在河的某一岸只有野人,而没有传教士,也同样被认为是合法状态。
在具体书写某些条件时,为了简便,这一点有时并没有考虑,但我们默认这个条件是被考虑了的。
有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡。
问传教士为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过传教士的数目。
即求解传教士和野人从左岸全部摆渡到右岸的过程中,任何时刻满足M(传教士数)≥C (野人数)和M+C≤k的摆渡方案。
设N=3,k=2,则给定的问题可用图1.2表示,图中L和R表示左岸和右岸,B=1或0分别表示有船或无船。
约束条件是:两岸上M≥C,船上M+C≤2。
图1.2 M-C问题实例由于传教士和野人数是一个常数,所以知道了一岸的情况,另一岸的情况也就知道了。
因此为了简便起见,在描述问题时,只描述一岸--如左岸--的情况就可以了。
另外,该问题我们最关心的是在摆渡过程中,两岸状态的变化情况,因此船上的情况并不需要直接表达出来。
在一次摆渡过程中,船上究竟有几个传教士和野人,可以通过两个相连的状态简单得到。
这样表达更简练,突出了问题的重点。
(1)综合数据库:用三元组表示左岸的情况,即(,,),其中0≤,≤3,∈{0,1},其中表示在左岸的传教士人数,表示在左岸的野人数,=1表示船在左岸,=0表示船在右岸。
则此时问题描述可以简化为:(3,3,1)→(0,0,0)N=3的M-C问题,状态空间的总状态数为4×4×2=32,根据约束条件的要求,可以看出只有20个合法状态。
再进一步分析后,又发现有4个合法状态实际上是不可能达到的。
因此实际的问题空间仅由16个状态构成。
下表列出分析的结果:()(001)达不到(传教士()(000)均在右,船在左)(011)(021)(031)(101)不合法(右岸野人多)(111)(121)不合法(左岸野人多)(131)不合法(左岸野人多)(201)不合法(右岸野人多)(211)不合法(右岸野人多)(221)(231)不合法(左岸野人多)(301)达不到(311)(321)(331)(010)(020)(030)达不到(100)不合法(右岸野人多)(110)(120)不合法(左岸野人多)(130)不合法(左岸野人多)(200)不合法(右岸野人多)(210)不合法(右岸野人多)(230)不合法(右岸野人多)(300)(220)(310)(320)(330)达不到规则集可以划分为两组:一组是从左岸到右岸,称为p 操作,另一组是从右岸到左岸,称为q操作。
修道士与野人问题
6.修道士与野人问题这是一个古典问题。
假设有n个修道士和n个野人准备渡河,但只有一条能容纳c人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。
如果两种人都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
要求:(1)用一个三元组(x1,x2,x3)表示渡河过程中各个状态。
其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。
例如(2,1,1)表示起始岸上有两个修道士,一个野人,小船在起始岸一边。
采用邻接表做为存储结构,将各种状态之间的迁移图保存下来。
(2)采用广度搜索法,得到首先搜索到的边数最少的一条通路。
(3)输出数据若问题有解(能渡过河去),则输出一个最佳方案。
用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:目的状态←…中间状态←…初始状态。
若问题无解,则给出“渡河失败”的信息。
(4)求出所有的解。
1.需求分析有n个修道士和n个野人准备渡河,但只有一条能容纳c人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数,否则修道士就会有危险,设计一个算法,确定他们能否渡过河去,若能,则给出一个小船来回次数最少的最佳方案。
用三元组(x1,x2,x3)来表示渡河过程中各个状态,其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。
若问题有解(能渡过河去),则输出一个最佳方案。
用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:目的状态←…中间状态←…初始状态,若问题无解,则给出“渡河失败”的信息。
2.设计2.1 设计思想(1)数据结构设计逻辑结构设计: 图型结构存储结构设计: 链式存储结构采用这种数据结构的好处:便于采用广度搜索法,得到首先搜索到的边数最少的一条通路,输出一个最佳方案,采用图的邻接表存储结构搜索效率较高。
有N个传教士和N个野人来到河边渡河
有N个传教士和N个野人来到河边渡河, 河岸有一条船, 每次至多可供k人乘渡。
问传教士为了安全起见, 应如何规划摆渡方案, 使得任何时刻, 河两岸以及船上的野人数目总是不超过传教士的数目(否则不安全, 传教士有可能被野人吃掉)。
即求解传教士和野人从左岸全部摆渡到右岸的过程中, 任何时刻满足M(传教士数)≥C(野人数)和M+C≤k的摆渡方案。
我们此处举例, 只讨论N为3、k为2的乘渡问题, 这样传教士和野人问题的描述就具体为如下:三个传教士与三个野人来到河边, 有一条船可供一人或两人乘渡, 问题是如何用这条船渡河才能使得河的任一岸上野人的数目总不超过传教士的数目(当然, 如果某一岸上只有野人而没有传教士是允许的)?我们用一个三元组(m c b)来表示河岸上的状态, 其中m、c分别代表某一岸上传教士与野人的数目, b=1表示船在这一岸, b=0则表示船不在。
设N=3, k=2, 则给定的问题可用下图表示, 图中L和R表示左岸和右岸, B=1或0分别表示有船或无船。
约束条件是: 两岸上M≥C, 船上M+C≤2。
我们采用产生式系统来解决这一问题。
由于传教士与野人的总数目是一常数, 所以只要表示出河的某一岸上的情况就可以了, 为方便起见, 我们选择传教士与野人开始所在的岸为所要表示的岸, 并称其为左岸, 另一岸称为右岸。
但显然仅用描述左岸的三元组描述就足以表示出整个情况, 因此必须十分重视选择较好的问题表示法。
以后的讨论还可以看到高效率的问题求解过程与控制策略有关, 合适的控制策略可缩小状态空间的搜索范围, 提高求解的效率。
因而问题的初始状态是(3 3 1), 目标状态是(0 0 0)。
(1) 综合数据库: 用三元组表示, 即(ML, CL, BL), 其中0≤ML, CL≤3, BL∈{0, 1}此时问题述简化为(3, 3, 1)® (0, 0, 0)N=3的M-C问题, 状态空间的总状态数为4×4×2=32, 根据约束条件的要求, 可以看出只有20个合法状态。
传教士野人过河问题两种解法思路
第6次:右岸到左岸,传教士过去1人,野人过去1人
第7次:左岸到右岸,传教士过去2人,野人过去0人
第8次:右岸到左岸,传教士过去0人,野人过去1人
第9次:左岸到右岸,传教士过去0人,野人过去2人
第10次:右岸到左岸,传教士过去1人,野人过去0人
第11次:左岸到右岸,传教士过去1人,野人过去1人
F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}
P10ﻩif (ML,CL,BL=1)then(ML–1 , CL,BL–1)
P01ﻩif ( ML,CL , BL=1)then ( ML ,CL–1 , BL–1)
P11ﻩif (ML,CL,BL=1) then ( ML–1 , CL–1,BL–1)
二、解答步骤
(1)设置状态变量并确定值域
M为传教士人数,C为野人人数,B为船数,要求M>=C且M+C<=3,L表示左岸,R表示右岸。
初始状态ﻩﻩ目标状态
LﻩRﻩﻩﻩLR
Mﻩ30ﻩﻩﻩM03
Cﻩ30ﻩﻩﻩﻩﻩC03
B1ﻩ0ﻩﻩﻩﻩB0ﻩ1
(2)确定状态组,分别列出初始状态集和目标状态集
用三元组来表示 :(ML,CL,BL)(均为左岸状态)
图1状态空间图
箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
三、算法设计
方法一:树的遍历
根据规则由根(初始状态)扩展出整颗树,检测每个结点的“可扩展标记”,为“-1”的即目标结点。由目标结点上溯出路径。
见源程序1。
方法二:启发式搜索
构造启发式函数为:
选择较大值的结点先扩展。
数据结构 第7章 修道士 实验报告
数据结构实验报告第七章实验名称:修道士野人问题实验类型:综合性实验班级:学号:姓名:实验日期:2014年5月21日1.问题描述河的左岸有N个野人和N个修道士以及一条小船,修道士们想用这条小船把所有的人都运到河的右岸,但又受到以下限制:●修道士和野人都会划船,但船一次只能载C人。
●在任何岸边,为了防止野人侵犯修道士,野人数不能超过修道士数,否则修道士将会被野人吃掉。
假定野人愿意服从任何一种过河的安排,本设计的主要任务是规划出一种确保修道士安全的过河方案。
2.数据结构设计用一个三元组(num1,num2,an)表示渡河过程中的各个状态。
num1表示左岸上修道士的个数,num2表示左岸上野人的个数,an表示小船位置(0-在右岸上,1-在左岸上)。
定义一个结构体,用于存放各个时刻的状态:typedef struct{int num1;//修道士人数int num2;//野蛮人人数int an;//表示两岸,0在右岸,1在左岸}DataType;用邻接表存储结构实现图的操作,其存储结构为:typedef struct Node{int dest; //邻接表的弧头结点序号struct Node *next;}Edge; //邻接表单链表的结点结构体typedef struct{DataType data; //结点数据元素int sorce; //邻接表的弧尾结点序号Edge *adj; //邻接边的头指针int pre; //指向此点的点的序号}AdjLHeight; //数组的数据元素类型结构体typedef struct{AdjLHeight a[10000]; //邻接表数组int numOfVerts; /结点个数int numOfEdges; //边个数}AdjLGraph; //邻接表结构体3.算法设计一侧的野人数目和修道士数目以及船在哪一岸共同构成一种状态,分析一会发现合法的状态是有限且固定的。
C++实现传教士与野人过河问题实验报告
else operation.push_back(" 0
2 | 右岸->左岸");
currentState.churchL = lastcurrentState.churchL;
currentState.wildL = lastcurrentState.wildL - 2 * lastcurrentState.boat;
currentState.boat = -lastcurrentState.boat;
lastParameters.push_back(currentState);
CvsWdfs(currentState, lastParameters,operation, 0);
operation.pop_back();
lastParameters.pop_back(); return 0; }
int main(){ int churchL = 3, wildL = 3, churchR = 0, wildR = 0;//分别用来计算左岸和右岸的传教士
和野人 vector <riverSides> lastParameters;//保存每一步移动操作的两岸传教士、野人人数 vector <string> operation;//保存当前操作的描述
if (lastcurrentState.boat == lastParameters[i].boat) return 0;
} } //检验人数数据合法性 if (lastcurrentState.churchL < 0 || lastcurrentState.wildL < 0 || lastcurrentState.churchR < 0 || lastcurrentState.wildR < 0)
实验二 传教士与野人过河问题
实验二 传教士与野人过河问题一、实验目的理解并熟悉掌握深度优先搜索和广度优先搜索算法。
二、实验内容设有3个传教士和3个野人来到河边,打算乘一只船从左岸到右岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,野人就会把传教士吃掉。
他们怎样才能用这条船安全的把所有人都渡过河去?三、实验内容(1)设置状态变量并确定值域设M 为传教士人数,C 为野人人数,B 为船数,要求M>=C 且M+C <= 3, L 表示左岸,R 表示右岸。
初始状态目标状态 L RL R M 3 0M 0 3 C 3 0C 0 3 B 1 0B 0 1(2)确定状态组,分别列出初始状态集和目标状态集用三元组来表示f S :(ML , CL , BL )(均为左岸状态) 其中,03,03ML CL ≤≤≤≤,BL ∈{ 0 , 1}0S :(3 , 3 , 1) g S : (0 , 0 , 0)初始状态0S :表示全部成员在河的的左岸;目标状态g S :表示全部成员从河的左岸全部渡河到河的右岸。
(3)定义并确定规则集合 以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij 操作。
其 中,第一下标i 表示船载的传教士数,第二下标j 表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij操作,下标的定义同前。
则共有10种操作,操作集为: F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 ) P10Pif ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 ) 01if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 ) P11Pif ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 ) 20if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 ) P02if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 ) Q10Qif ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 ) 01if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 ) Q11if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 ) Q20if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 ) Q02(4)当状态数量不是很大时,画出合理的状态空间图箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和野人数。
传教士和野人渡河问题
传教士和野人渡河问题刘宪国050422023野人过河问题描述如下:有三个传教士和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会有危险.一、算法分析先来看看问题的初始状态和目标状态,假设分为甲岸和乙岸:初始状态:甲岸,3野人,3传教士;乙岸,0野人,0传教士;船停在甲岸,船上有0个人;目标状态:甲岸,0野人,0传教士;乙岸,3野人,3传教士;船停在乙岸,船上有0个人;整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1传教士、渡1野人1传教士、渡2野人、渡2传教士。
算符知道以后,剩下的核心问题就是搜索方法了,本文采用深度优先搜索,通过一个FindNext(…)函数找出下一步可以进行的渡河操作中的最优操作,如果没有找到则返回其父节点,看看是否有其它兄弟节点可以扩展,然后用Process(…)函数递规调用FindNext(…),一级一级的向后扩展。
搜索中采用的一些规则如下:1、渡船优先规则:甲岸一次运走的人越多越好(即甲岸运多人优先),同时野人优先运走;乙岸一次运走的人越少越好(即乙岸运少人优先),同时传教士优先运走;2、不能重复上次渡船操作(通过链表中前一操作比较),避免进入死循环;3、任何时候河两边的野人和传教士数均分别大于等于0且小于等于3;4、由于只是找出最优解,所以当找到某一算符(当前最优先的)满足操作条件后,不再搜索其兄弟节点,而是直接载入链表。
5、若扩展某节点a的时候,没有找到合适的子节点,则从链表中返回节点a的父节点b,从上次已经选择了的算符之后的算符中找最优先的算符继续扩展b。
二、基本数据结构定义如下几个数据结构:typedef struct _riverside{ // 岸边状态类型int wildMan; // 野人数int churchMan; // 传教士数}RIVERSIDE;typedef struct _boat{ // 船的状态类型int wildMan; // 野人数int churchMan; // 传教士数}BOAT;typedef struct _question{ // 整个问题状态RIVERSIDE riverSide1; // 甲岸RIVERSIDE riverSide2; // 乙岸int side; // 船的位置, 甲岸为-1, 乙岸为1 BOAT boat; // 船的状态_question* pPrev; // 指向前一渡船操作_question* pNext; // 指向后一渡船操作}QUESTION;用QUESTION来声明一个最基本的链表。
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题37030602 王世婷一、实验问题传教士和食人者问题(The Missionaries and Cannibals Problem )。
在河的左岸有3个传教士、1条船和3个食人者,传教士们想用这条船将所有的成员运过河去,但是受到以下条件的限制:(1)传教士和食人者都会划船,但船一次最多只能装运两个;(2)在任何岸边食人者数目都不得超过传教士,否则传教士就会遭遇危险:被食人者攻击甚至被吃掉。
此外,假定食人者会服从任何一种过河安排,试规划出一个确保全部成员安全过河的计划。
二、解答步骤(1) 设置状态变量并确定值域M 为传教士人数,C 为野人人数,B 为船数,要求M>=C 且M+C <= 3,L 表示左岸,R 表示右岸。
初始状态 目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(2) 确定状态组,分别列出初始状态集和目标状态集用三元组来表示f S :(ML , CL , BL )(均为左岸状态)其中03,03ML CL ≤≤≤≤,BL ∈{ 0 , 1}0S :(3 , 3 , 1) g S : (0 , 0 , 0)初始状态表示全部成员在河的的左岸;目标状态表示全部成员从河的左岸全部渡河完毕。
(3) 定义并确定规则集合仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij 操作。
其中,第一下标i 表示船载的传教士数,第二下标j 表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij 操作,下标的定义同前。
则共有10种操作,操作集为F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}P 10 if ( ML ,CL , BL=1 ) then ( ML –1 , CL , BL –1 )P 01 if ( ML ,CL , BL=1 ) then ( ML , CL –1 , BL –1 )P 11 if ( ML ,CL , BL=1 ) then ( ML –1 , CL –1 , BL –1 )P 20 if ( ML ,CL , BL=1 ) then ( ML –2 , CL , BL –1 )P 02 if ( ML ,CL , BL=1 ) then ( ML , CL –2 , BL –1 )Q 10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q 01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q 11 if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(4)当状态数量不是很大时,画出合理的状态空间图图1 状态空间图箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
野人与传教士问题A算法
野人与传教士问题(A*算法)SY0903620 赵磊一、实验题目请用A*算法实现传教士和野人问题问题:设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去?算法设计要求给出:状态表示,规则库,启发函数等二、实验目的通过具体问题的编程求解,利用A*算法解决此经典问题,了解人工智能的启发式搜索算法的基本过程与原理。
三、设计思想1、编程工具采用C++语言在Visual Studio 6.0环境下编写;2、整体思想(1)把初始结点So放入OPEN 表中,计算f(So)。
(2)如果OPEN为空,则搜索失败,退出。
(3)把OPEN中的第一个节点(记为节点n)从表中移出放入CLOSED表。
(4)考察节点n是否为目标节点。
若是,则求得问题的解,退出。
(5)若节点n不可扩展,则转第(2)步。
(6)扩展节点n,用估价函数f(x)计算每个子节点的估价值,并为每个子节点配置指向父节点的指针,把这些子节点都送到OPEN表中,然后对OPEN表中的全部节点按估价值从小到大的顺序排列。
3、具体说明用A*算法求解传教士与野人问题。
M=C=5, K=3。
节点估价值设为f(n)=h(n)+g(n),g(n)设为节点搜索深度,而h(n)= m(n) + c(n) - 2b(n),其中m:河左岸的传教士人数;c:河左岸的野人人数;b:船是否在左岸,1:表示在左岸,0:表示不在左岸。
采用结构体定义形式,定义状态节点*NewNode(int m, int c, int b),其中包含m左岸传教士人数、c左岸野人人数、b船状态(左或右)。
开始状态为(3,3,1),目标状态为(0,0,0)。
若需要条件满足,即任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉,要对状态结点的安全性进行判断,判断一个状态是否为安全的,即是否满足在河的任何一岸,传教士人数不少于野人人数,或者只有野人而没有传教士。
用Prolog求解传教士和野人问题
用Prolog求解传教士和野人问题实验七用Prolog求解传教士和野人问题 1、实验目的复习经典谓词演算中的归结原理,掌握人工智能程序设计语言Prolog,理解通过搜索求解问题实现人工智能的思想。
2、实验原理谓词演算中的消解法,3、实验内容设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一边河岸上,野人的数量超过传教士,野人就要吃掉传教士,问怎样才能用船将3个传教士和3个野人从左岸都渡到右岸,又不会发生传教士被吃的事件呢,通过Prolog程序,给出乘船过河的动作序列。
4、实验步骤(1) 设计该问题的状态。
例如:((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)。
(2) 定义目标状态。
这里是:((0,0),(3,3),1)3) 描述可能的动作。
船上所能够载人的状态就是可能的操作。
用谓词(move表示。
(4) 判断合法状态(5) 深度优先搜索三个传教士和三个野人的示例程序如下:move(1,0).move(0,1).move(0,2).move(2,0).move(1,1).legal((X,Y,_)):-legal1(X),legal1(Y). legal1((X,Y)):-X=:=0,Y>=0,!. legal1((X,Y)):-Y=:=0,X>=0,!. legal1((X,Y)):-X>=Y,X>=0,Y>=0.update((X,Y,0),Move,Statu1):-(A,B)=X,(C,D)=Y,(E,F)=Move,C1 is C+E,D1 is D+F,A1 is A-E,B1 is B-F,Statu1=((A1,B1),(C1,D1),1). update((X,Y,1),Move,Statu1):- (A,B)=X, (C,D)=Y,(E,F)=Move,C1 is C-E,D1 is D-F,A1 is A+E,B1 is B+F,Statu1=((A1,B1),(C1,D1),0). connect(Statu,Statu1):- move(X,Y),update(Statu,(X,Y),Statu1), legal(Statu1).findroad(X,X,L,L):-write(L). findroad(X,Y,L,L1):-connect(X,Z),not(member(Z,L)),findroad(Z,Y,[Z|L],L1).传教士和野人问题有三个牧师和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险。
数据结构实验五——修道士野人问题
( 3 3 1 )船上人数[修道士,野人][3 1]右边岸上[0 2 0]
( 0 2 0 )船上人数[修道士,野人][2 0]左边岸上[2 2 1]
( 2 2 1 )船上人数[修道士,野人][2 2]右边岸上[0 0 0]
( 0 0 0 )
( 3 3 1 )船上人数[修道士,野人][3 1]右边岸上[0 2 0]
重复以上方式输出所有的渡河方式
五、运行测试与分析
输入
输出
实际
1 2
( 1 1 1 )船上人数[修道士,野人][1 1]右边岸上[0 0 0]
( 0 0 0 )
√
3 5
( 3 3 1 )船上人数[修道士,野人][3 2]右边岸上[0 1 0]
( 0 1 0 )船上人数[修道士,野人][1 0]左边岸上[1 1 1]
( 1 1 0 )船上人数[修道士,野人][1 1]左边岸上[2 2 1]
( 2 2 1 )船上人数[修道士,野人][2 2]右边岸上[0 0 0]
( 0 0 0 )
( 3 3 1 )船上人数[修道士,野人][2 2]右边岸上[1 1 0]
( 1 1 0 )船上人数[修道士,野人][2 1]左边岸上[3 2 1]
实验报告五
实验课名称:数据结构与程序设计实验
实验名称:修道士野人问题
班级:
学号:
姓名:
时间:
一、问题描述
河的左岸有N个野人和N个修道士以及一条小船,修道士们想用这条小船把所有的人都运到河的右岸,但又受到以下限制:
所有人都会划船,但船一次只能载C人
在任意岸上,野人数不能超过修道士数,否则修道士将会被野人吃掉。
struct Node *next;
传教士过河问题(实验二)
传教士过河问题实验报告计研-12 2012312120115 宋玲玲1.实验目的(1)了解知识表示相关技术;(2)掌握问题规约法或者状态空间法的分析方法。
2.实验内容从前有一条河,河的左岸有m个传教士、m个野人和一艘最多可乘n人的小船。
约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
搜索一条可使所有的野人和传教士安全渡到右岸的方案。
3.实验原理及方法假设开始时传教士、野人和船都在右岸,用数组(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个传教士和野人,每次返回一个野人和传教士,直到最终结果。
程序流程图如下:4、源程序清单:本程序用C++语言编写。
#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 mc(int a,int b,int c);int main(){cout<<"传教士与野人过河问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.上机内容
传教士与野人问题求解(宽度搜索算法)
二问题背景:
从前有一条河,河的左岸有m个传教士(Missionary)和m个野人(Cannibal),和一艘最多可乘n人的小船。
约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
三实验内容:
编程,接收m和n,搜索一条可让所有的野人和传教士安全渡到右岸的方案,例如下图:
(M表示传教士(Missionary),C 表示野人(Cannibal))
初态目标
Left Bank River Right
bank
Left
Bank
River Right
bank
M…. M….
C…. C….
注:本实验的举例均以3个传教士和3个野人同在左岸作为初始状态。
四实验方案和算法:
1.数据结构:
本实验需要用到的数据结构主要是队列和堆栈,其实现均包含于dso.h头文件中,分别命名为class stack和class queue。
2.宽度搜索算法:
(1)结点结构:
class Move {
public:
int missionary; //要移动的传教士数量
int cannibal; //野人
};
class ElemType : Move { //继承Move类,获得传教士,野人数据成员。
private:
bool boat; //船是否在左岸?
public:
ElemType* flag; //标示前一状态即扩展出本结点的父结点信息
ElemType(int MAX_PEOPLE) { //创建初始状态
missionary = cannibal = MAX_PEOPLE;
boat = true;
flag = NULL;
}
……
在这里,Elemtype集成了Move,从而获得Move类的传教士和野人数据成员。
以上两个类的数据成员用于保存所有扩展生成的结点。
其中missionary表示表示左岸上传教士的树目,cannibal表示左岸上野人的树目,boat表示船在哪个岸上(其中true表示在左岸,这是船的初始状态,表示false在右岸), flag 用于标示前一状态即扩展出本结点的父结点信息,以便最后回搜找出解的
路径。
举例说明:假设左岸有3个传教士和3个野人,小船最多可乘2人。
把当前左岸的状态抽象为:(3,3,1),前两个"3"代表左岸有3个传教士和3个野人,1代表船在左岸。
很明显,目标状态为(0,0,0),表示左岸的传教士和也人数目都是0,而船在右岸。
(2)船的行动规则(successor function):
把每一次可行的渡船方案作为行动规则,用Move类的(m,c)表示。
行动规则的两位数分别代表要移动的传教士,野人的数量。
对于固定大小的船,其装载能力是一定的,所以它的行动规则空间也是一定的。
在这里,用MoveGroup类的构造函数构造出所有的行动规则。
注意,这里MoveGroup类中的Move对象只有500的可用空间,所以,输入的传教士和野人数目构成的行动规则不能超过500种。
(3)宽度优先算法:
实验的主要搜索算法由ANSWER类的构造函数实现,这里主要用到了OPEN和CLOSED队列,以及一个临时的TEMP堆栈。
其中,OPEN表用于存放扩展结点,CLOSED表用于存放被扩展结点,TEMP则用于用于记录成功搜索的路径。
搜索过程大致如下描述:先构造初始结点以及船的行动规则,初始结点入OPEN队列,以宽度优先依次搜索OPEN队列头结点的子结点,同时保存受访问结点的父结点信息,知道搜索到目标结点或者无解为止。
算法框图如下所示:
3 程序界面和功能说明:
程序运行环境为DOS控制台,运行开始以后,程序提示输入需要坐船的传教士和野人数目,例如输入3表示有3个传教士和3个野人。
用户按回车键以后,程序继续提示输入船的装载能力,例如输入2表示这个船依次最多可以坐2人。
注:一般情况下,船的装载能力应该少于传教士或野人的数量,而且一般为偶数。
程序开始运行时的界面截图:
程序运行结束时的界面截图:
输出文件示例:
Left(3, 3) | (0, 0)Right
[Step 1]
Move 0 missionaries and 2 cannibals to the right side. Left(3, 1) | (0, 2)Right
[Step 2]
Move 0 missionaries and 1 cannibals to the left side. Left(3, 2) | (0, 1)Right
[Step 3]
Move 0 missionaries and 2 cannibals to the right side. Left(3, 0) | (0, 3)Right
[Step 4]
Move 0 missionaries and 1 cannibals to the left side. Left(3, 1) | (0, 2)Right
[Step 5]
Move 2 missionaries and 0 cannibals to the right side. Left(1, 1) | (2, 2)Right
[Step 6]
Move 1 missionaries and 1 cannibals to the left side. Left(2, 2) | (1, 1)Right
[Step 7]
Move 2 missionaries and 0 cannibals to the right side. Left(0, 2) | (3, 1)Right
[Step 8]
Move 0 missionaries and 1 cannibals to the left side. Left(0, 3) | (3, 0)Right
[Step 9]
Move 0 missionaries and 2 cannibals to the right side. Left(0, 1) | (3, 2)Right
[Step 10]
Move 0 missionaries and 1 cannibals to the left side.
Left(0, 2) | (3, 1)Right
[Step 11]
Move 0 missionaries and 2 cannibals to the right side.
Left(0, 0) | (3, 3)Right
OK!
5错误说明:
(1)关于有没有解的问题:由于传教士和野人问题是一个真实的问题,来到岸边的传教士和野人数目与船的装载能力都是随机的,所以某些特定情况下,要以一
定规则把人都运到船的对岸是没有解的,例如假设有10个传教士和10个野人,
船一次最多能够装2人,这时候是不能把人都运到对岸的,这时候程序会提示:
There may not be any way to transport these guys.
(2)关于运行时间的问题:本实验使用宽度优先搜索算法,但并没有进行优化,所以有时候程序虽然确实有解,但是由于算法的效率确实很低,造成的时间上的
开销有时候可能会比起喝一杯咖啡的时间还要长,这时候程序会提示:
Please wait patiently。
Working . . .
六心得体会:
这个是我们小组的第一个实验,由于经验以及能力有限,所以算法上比较简单,只用了一个宽度优先搜索算法,但毕竟能够成功找出解,虽然效率较低。
经过一些测试数据的测试以后,发现了宽度优先搜索算法虽然必能找到最优解(有时候无解),但效率真的很低,如我们提供的那个测试数据(50个传教士,50个野人,船最多能坐4人),虽然能解,但也花费了75秒多的时间才能找出解,可见优化算法的必要。