(完整word版)传教士野人过河问题-两种解法思路

合集下载

传教士野人过河问题-两种解法思路

传教士野人过河问题-两种解法思路

实验 传教士野人过河问题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操作的下标,即分别表示船载的传教士数和食人者数。

求解野人与传教士问题1

求解野人与传教士问题1
题目:设有n个传教士和m个野人来到河边,打算乘一只般从右岸到左岸云。该般的负载能力为两人。在任何时候,如果野人人数超过传教士人数,野人就会把传教士吃掉。他们怎样才能用这条般安全地把所有的人都渡过河去?
题目分析:
定义节点的结构:以取般的一个来回作为一步搜索,这样节点可由下面几个量进行描述:两岸的传教士人数和野人人数、本节点距离起始节点的距离,即由初始节点搜索几步后到达本节点。需要注意的是并不是所有节点都是可达的,题目中对可达节点作出了限制,只有两大 岸上的人数必须不能为负。
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

我对野人过河的问题思考

我对野人过河的问题思考
Q20:if ( ML ,YL ,0)then ( ML+2 ,YL,1 )
Q02:if ( ML ,YL ,0)then ( ML ,YL +2,1)
4.确定合理的状态
在(ML , YL , BL)中, ,BL∈{ 0 , 1},因此共有4×4×2=32种状态,除去不合法状态和修道士被野人吃掉的状态,有意义的状态只有16种:
此问题严格的约束是船只能载两人和岸上野人不多于传教士。
二野人过河问题的知识表示及规则定义
知识表示是对知识的描述,即用一组符号把知识编码成计算机可以接受的某种结构。野人过河问题是一种过程性知识,有多种方法可以表示这个问题,此外野人过河问题推理所用知识和推出的结论都是可以精确表示的,因此它是属于确定性推理范畴的。
BoatWildNum=node(result(j),2)-node(result(j-1),2);
if node(result(j),3)==1
fprintf('第%d次:左岸到右岸,传教士过去%d人,野人过去%d人\n',...
StepNum,abs(BoatPriNum),abs(BoatWildNum));
index=1;
open_list=[1,0.01];%节点号启发函数值
while (1)
[row,~]=size(open_list);
if row==0
fprintf('all the nodes in open list have been expanded.');
return
end
for i1=1:row
S12=(1, 1,0) S13=(0, 2, 0) S14=(0, 1, 0)S15=(0, 0, 0)

修道士与野人问题教学文案

修道士与野人问题教学文案

修道士与野人问题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)数据结构设计逻辑结构设计: 图型结构存储结构设计: 链式存储结构采用这种数据结构的好处:便于采用广度搜索法,得到首先搜索到的边数最少的一条通路,输出一个最佳方案,采用图的邻接表存储结构搜索效率较高。

传教士和野人问题

传教士和野人问题

传教士和野人问题传教士和野人问题(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个状态构成。

下表列出分析的结果:( ) ( ) ( 0 0 1)达不到( 0 0 0) (传教士均在右,船在( 0 1 0) 左) ( 0 2 0) ( 0 1 1) ( 0 3 0)达不到 ( 0 2 1) ( 1 0 0)不合法( 0 3 1) (右岸野人多) ( 1 0 1)不合法( 1 1 0) (右岸野人多) ( 1 2 0)不合法( 1 1 1) (左岸野人多) ( 1 2 1)不合法( 1 3 0)不合法(左岸野人多) (左岸野人多) ( 1 3 1)不合法( 2 0 0)不合法(左岸野人多) (右岸野人多) ( 2 0 1)不合法( 2 1 0)不合法(右岸野人多) (右岸野人多) ( 2 1 1)不合法( 2 3 0)不合法(右岸野人多) (右岸野人多) ( 2 2 1) ( 3 0 0) ( 2 3 1)不合法( 2 2 0) (左岸野人多) ( 3 1 0) ( 3 0 1)达不到 ( 3 2 0)( 3 1 1) ( 3 3 0)达不到 ( 3 2 1)( 3 3 1)规则集可以划分为两组:一组是从左岸到右岸,称为p操作,另一组是从右岸到左岸,称为q操作。

传教士和野人过河

传教士和野人过河

实验报告一、实验名称:传教士和野人过河二、实验目的:这是经典的过河方案规划问题,通过本实验的设计与编程实现让学生掌握基于状态空间知识表示方法的一般搜索策略。

三、实验内容:设有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操作。

传教士-野人问题

传教士-野人问题

传教士-野人问题传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<n,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。

设m为传教士的人数,c为野人的人数,用状态空间发求解此问题的过程如下:< bdsfid="64" p=""></n,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。

设m为传教士的人数,c为野人的人数,用状态空间发求解此问题的过程如下:<> M、C = N,boat = k,要求M>=C且M+C <= K初始状态目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(1)用三元组来表示(ML , CL , BL)其中0<=ML , CL <= 3 , BL ∈{ 0 , 1}(3 , 3 , 1) (0 , 0 , 0)(2)规则集合P10if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11if ( 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 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 Q 01f=2 P 02 f=1 Q 01f=1 Q 11f=1 P 01 f=2 P 11 (3,3,1)(3,2,0)(2,2,0)(3,1,0)(3,2,1)(3,0,0) f=3 P 02(3,1,1) f=2 Q 01(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(0,2,0) f=4 P 20(0,3,1)f=3 Q 01(0,1,1)f=5 P 02(0,2,1) f=4 Q 01 (0,0,0)f=3 Q 01(1,1,1) f=4 Q 106.2.3 用状态空间法求解传教士和食人者问题例6-2 传教士和食人者问题(The Missionaries and Cannibals Problem)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验 传教士野人过河问题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操作的下标,即分别表示船载的传教士数和食人者数。

三、算法设计方法一: 树的遍历根据规则由根(初始状态)扩展出整颗树,检测每个结点的“可扩展标记”,为“-1”的即目标结点。

由目标结点上溯出路径。

见源程序1。

方法二:启发式搜索构造启发式函数为:6.01-ML CLf--⎧=⎨∞⎩满足规则时其它选择较大值的结点先扩展。

见源程序2。

四、实验结果方法一的实验结果:传教士野人过河问题第1种方法:第1次:左岸到右岸,传教士过去1人,野人过去1人第2次:右岸到左岸,传教士过去1人,野人过去0人第3次:左岸到右岸,传教士过去0人,野人过去2人第4次:右岸到左岸,传教士过去0人,野人过去1人第5次:左岸到右岸,传教士过去2人,野人过去0人第6次:右岸到左岸,传教士过去1人,野人过去1人第7次:左岸到右岸,传教士过去2人,野人过去0人第8次:右岸到左岸,传教士过去0人,野人过去1人第9次:左岸到右岸,传教士过去0人,野人过去2人第10次:右岸到左岸,传教士过去0人,野人过去1人第11次:左岸到右岸,传教士过去0人,野人过去2人第2种方法:第1次:左岸到右岸,传教士过去1人,野人过去1人第2次:右岸到左岸,传教士过去1人,野人过去0人第3次:左岸到右岸,传教士过去0人,野人过去2人第4次:右岸到左岸,传教士过去0人,野人过去1人第5次:左岸到右岸,传教士过去2人,野人过去0人第6次:右岸到左岸,传教士过去1人,野人过去1人第7次:左岸到右岸,传教士过去2人,野人过去0人第8次:右岸到左岸,传教士过去0人,野人过去1人第9次:左岸到右岸,传教士过去0人,野人过去2人第10次:右岸到左岸,传教士过去1人,野人过去0人第11次:左岸到右岸,传教士过去1人,野人过去1人第3种方法:第1次:左岸到右岸,传教士过去0人,野人过去2人第2次:右岸到左岸,传教士过去0人,野人过去1人第3次:左岸到右岸,传教士过去0人,野人过去2人第4次:右岸到左岸,传教士过去0人,野人过去1人第5次:左岸到右岸,传教士过去2人,野人过去0人第6次:右岸到左岸,传教士过去1人,野人过去1人第7次:左岸到右岸,传教士过去2人,野人过去0人第8次:右岸到左岸,传教士过去0人,野人过去1人第9次:左岸到右岸,传教士过去0人,野人过去2人第10次:右岸到左岸,传教士过去0人,野人过去1人第11次:左岸到右岸,传教士过去0人,野人过去2人第4种方法:第1次:左岸到右岸,传教士过去0人,野人过去2人第2次:右岸到左岸,传教士过去0人,野人过去1人第3次:左岸到右岸,传教士过去0人,野人过去2人第4次:右岸到左岸,传教士过去0人,野人过去1人第5次:左岸到右岸,传教士过去2人,野人过去0人第6次:右岸到左岸,传教士过去1人,野人过去1人第7次:左岸到右岸,传教士过去2人,野人过去0人第8次:右岸到左岸,传教士过去0人,野人过去1人第9次:左岸到右岸,传教士过去0人,野人过去2人第10次:右岸到左岸,传教士过去1人,野人过去0人第11次:左岸到右岸,传教士过去1人,野人过去1人方法二的实验结果:传教士野人过河问题方法如下第1次:左岸到右岸,传教士过去1人,野人过去1人 l:2r,2y r:1r,1y 第2次:右岸到左岸,传教士过去1人,野人过去0人 l:3r,2y r:0r,1y 第3次:左岸到右岸,传教士过去0人,野人过去2人 l:3r,0y r:0r,3y 第4次:右岸到左岸,传教士过去0人,野人过去1人 l:3r,1y r:0r,2y 第5次:左岸到右岸,传教士过去2人,野人过去0人 l:1r,1y r:2r,2y 第6次:右岸到左岸,传教士过去1人,野人过去1人 l:2r,2y r:1r,1y 第7次:左岸到右岸,传教士过去2人,野人过去0人 l:0r,2y r:3r,1y 第8次:右岸到左岸,传教士过去0人,野人过去1人 l:0r,3y r:3r,0y 第9次:左岸到右岸,传教士过去0人,野人过去2人 l:0r,1y r:3r,2y 第10次:右岸到左岸,传教士过去0人,野人过去1人 l:0r,2y r:3r,1y 第11次:左岸到右岸,传教士过去0人,野人过去2人 l:0r,0y r:3r,3y 问题结束由结果可以看出,方法二的结果为方法一的第一种结果,两者具有一致性。

五、总结与教训:最开始时采用的方法为:用向量0123456{,,,,,,}A X X X X X X X 表示状态,其中02~X X 表示三个传教士的位置,35~X X 表示三个野人的位置,6X 表示船的位置。

0表示在河左岸,1表示已渡过了河,在河右岸。

设初始状态和目标状态分别为:0:{0,0,0,0,0,0,0}S S =:{1,1,1,1,1,1,1}g G S =但在描述规则时发现这样定义会造成规则麻烦、不清晰,原因在于此题并不关心是哪几个传教士和野人在船上,仅关心其人数,故没有必要将每个人都设置变量,分别将传教士、野人、船作为一类即可。

四、源代码1. 源程序1:树的遍历%野人和传教士过河问题%date:2010/12/14%author:wang shi tingfunction [ ]=guohe()clear all;close all;global n node;n=2;solveNum=1; %问题的解法result=zeros(100,1);node=zeros(300,5);node(1,:)=[3,3,1,1,-1];%初始化%1左岸传教士数 2左岸野人数 3船(1为左岸,0为右岸)%4是否可扩展(1为可扩展) 5父节点号(-1表示无父节点,即为初始节点) j=1;% for j=1:nwhile (1)if j>nbreakendif node(j,4)==1 %判断结点是否可扩展if node(j,3)==1 %船在左岸if ( (node(j,1)==0) || (node(j,1)==3) )&&(node(j,2)>=1) forward(j,0,1);endif (node(j,1)==1 && node(j,2)==1 || node(j,1)==3 && node(j,2)==2) forward(j,1,0);endif (node(j,1)>=1 && node(j,1)==node(j,2))forward(j,1,1);endif (node(j,1)==0 || node(j,1)==3)&& node(j,2)>=2forward(j,0,2);endif (node(j,1)==2 && node(j,2)==2 || node(j,1)==3 && node(j,2)==1) forward(j,2,0);endelseif node(j,3)==0%船在右岸if ( (node(j,1)==0) || (node(j,1)==3) )&&(node(j,2)<=2)afterward(j,0,1);endif (node(j,1)==2 && node(j,2)==2 || node(j,1)==0 && node(j,2)==1) afterward(j,1,0);endif (node(j,1)<=2 && node(j,1)==node(j,2))afterward(j,1,1);endif (node(j,1)==0 || node(j,1)==3)&& node(j,2)<=1afterward(j,0,2);endif (node(j,1)==1 && node(j,2)==1 || node(j,1)==0 && node(j,2)==2) afterward(j,2,0);endendendj=j+1;endfprintf('传教士野人过河问题\n');for t=1:nj=1;k=t;StepNum=1;if node(k,4)==-1while (k~=-1)result(j)=k;k=node(k,5);j=j+1;endj=j-1;fprintf('第%d种方法:\n',solveNum);while j>1BoatPriNum=node(result(j),1)-node(result(j-1),1);BoatWildNum=node(result(j),2)-node(result(j-1),2);if node(result(j),3)==1fprintf('第%d次:左岸到右岸,传教士过去%d人,野人过去%d人\n',...StepNum,abs(BoatPriNum),abs(BoatWildNum));StepNum=StepNum+1;endif node(result(j),3)==0fprintf('第%d次:右岸到左岸,传教士过去%d人,野人过去%d人\n',...StepNum,abs(BoatPriNum),abs(BoatWildNum));StepNum=StepNum+1;endj=j-1;endpause(0.2);fprintf('\n');solveNum=solveNum+1;endendfprintf('问题结束');%%%从左岸到右岸,船上传教士x个,野人y个function []=forward(z,x,y)global n;global node;node(n,1)=node(z,1)-x;node(n,2)=node(z,2)-y;node(n,3)=0;r=search(z);if(~r)returnendnode(z,4)=0;node(n,4)=1;node(n,5)=z;s=destination();if snode(n,4)=-1;endn=n+1;%%%%从右岸到左岸,船上传教士x个,野人y个function []=afterward(z,x,y)global n;global node;node(n,1)=node(z,1)+x;node(n,2)=node(z,2)+y;node(n,3)=1;r=search(z);if(~r)returnendnode(z,4)=0;node(n,4)=1;node(n,5)=z;s=destination();if snode(n,4)=-1;endn=n+1;%%function r=search(x)global n node;i=x;while node(i,5)~=-1if node(i,1)==node(n,1) && node(i,2)==node(n,2) && node(i,3)==node(n,3) r=0;returnendi=node(i,5);end%跟初始节点比较if node(i,1)==node(n,1) && node(i,2)==node(n,2) && node(i,3)==node(n,3)r=0;returnendr=1;%均不相同%%function s=destination()global n node;if node(n,1)==0 && node(n,2)==0 && node(n,3)==0s=1;returnends=0;2. 运用启发式函数%%%野人和传教士过河问题%date:2010/12/15%author:wang shi tingfunction [ ]=guohe()clear all;close all;global n node open_list index;n=2;result=zeros(100,1);node=zeros(100,5);node(1,:)=[3,3,1,1,-1];%初始化%1左岸传教士数 2左岸野人数 3船(1为左岸,0为右岸)%4是否可扩展(1为可扩展) 5父节点号(-1表示无父节点,即为初始节点)index=1;open_list=[1,0.01];%节点号启发函数值while (1)[row,~]=size(open_list);if row==0fprintf('all the nodes in open list have been expanded.');returnendfor i1=1:rowopen_list(i1,2)=6.01-node(open_list(i1,1),1)-node(open_list(i1,1),2);%定义启发函数if node(open_list(i1,1),4)==-1%如果该结点是目标结点,则打印结果fprintf('传教士野人过河问题\n');j=1;k=open_list(i1,1);StepNum=1;while (k~=-1)result(j)=k;k=node(k,5);j=j+1;endj=j-1;fprintf('方法如下\n');while j>1BoatPriNum=node(result(j),1)-node(result(j-1),1);BoatWildNum=node(result(j),2)-node(result(j-1),2);if node(result(j),3)==1fprintf('第%d次:左岸到右岸,传教士过去%d人,野人过去%d人\n',...StepNum,abs(BoatPriNum),abs(BoatWildNum));StepNum=StepNum+1;endif node(result(j),3)==0fprintf('第%d次:右岸到左岸,传教士过去%d人,野人过去%d人\n',...StepNum,abs(BoatPriNum),abs(BoatWildNum));StepNum=StepNum+1;endj=j-1;endpause(0.2);fprintf('问题结束\n');returnendend[r_row,~,~]=find(open_list(:,2)==max(open_list(:,2)));j=open_list(r_row(1,1),1);if node(j,3)==1 %船在左岸if ( (node(j,1)==0) || (node(j,1)==3) )&&(node(j,2)>=1)forward(j,0,1);endif (node(j,1)==1 && node(j,2)==1 || node(j,1)==3 && node(j,2)==2) forward(j,1,0);endif (node(j,1)>=1 && node(j,1)==node(j,2))forward(j,1,1);endif (node(j,1)==0 || node(j,1)==3)&& node(j,2)>=2forward(j,0,2);endif (node(j,1)==2 && node(j,2)==2 || node(j,1)==3 && node(j,2)==1) forward(j,2,0);endelseif node(j,3)==0%船在右岸if ( (node(j,1)==0) || (node(j,1)==3) )&&(node(j,2)<=2)afterward(j,0,1);endif (node(j,1)==2 && node(j,2)==2 || node(j,1)==0 && node(j,2)==1) afterward(j,1,0);endif (node(j,1)<=2 && node(j,1)==node(j,2))afterward(j,1,1);endif (node(j,1)==0 || node(j,1)==3)&& node(j,2)<=1afterward(j,0,2);endif (node(j,1)==1 && node(j,2)==1 || node(j,1)==0 && node(j,2)==2) afterward(j,2,0);endend%display(open_list);open_list(r_row(1),:)=[ ];index=index-1;%open表个数减1%display(open_list);end%%%从左岸到右岸,船上传教士x个,野人y个function []=forward(z,x,y)global n;global node open_list index;node(n,1)=node(z,1)-x;node(n,2)=node(z,2)-y;node(n,3)=0;r=search(z);if(~r)returnendnode(z,4)=0;node(n,4)=1;node(n,5)=z;s=destination();if snode(n,4)=-1;endindex=index+1;open_list(index,1)=n;n=n+1;%%%%从右岸到左岸,船上传教士x个,野人y个function []=afterward(z,x,y)global n;global node open_list index;node(n,1)=node(z,1)+x;node(n,2)=node(z,2)+y;node(n,3)=1;r=search(z);if(~r)returnendnode(z,4)=0;node(n,4)=1;node(n,5)=z;s=destination();if snode(n,4)=-1;endindex=index+1;open_list(index,1)=n;n=n+1;%%function r=search(x)global n node;i=x;while node(i,5)~=-1if node(i,1)==node(n,1) && node(i,2)==node(n,2) && node(i,3)==node(n,3) r=0;returnendi=node(i,5);end%跟初始节点比较if node(i,1)==node(n,1) && node(i,2)==node(n,2) && node(i,3)==node(n,3) r=0;returnendr=1;%均不相同%%function s=destination()global n node;if node(n,1)==0 && node(n,2)==0 && node(n,3)==0s=1;returnends=0;。

相关文档
最新文档