传教士野人过河问题-两种解法思路
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题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
题目分析:
定义节点的结构:以取般的一个来回作为一步搜索,这样节点可由下面几个量进行描述:两岸的传教士人数和野人人数、本节点距离起始节点的距离,即由初始节点搜索几步后到达本节点。需要注意的是并不是所有节点都是可达的,题目中对可达节点作出了限制,只有两大 岸上的人数必须不能为负。
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
修道士与野人问题教学文案
修道士与野人问题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)数据结构设计逻辑结构设计: 图型结构存储结构设计: 链式存储结构采用这种数据结构的好处:便于采用广度搜索法,得到首先搜索到的边数最少的一条通路,输出一个最佳方案,采用图的邻接表存储结构搜索效率较高。
传教士问题
一.问题描述有M个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡。
任何时刻在河的两岸以及船上的野人数目总是不超过传教士的数目。
二.问题分析本问题采用A*算法求解,解答的关键与难点如下:1.评估函数的建立。
评估函数为f=h+d=M+N-2*B+d.。
M表示左岸的传教士的人数,N表示左岸野人的数目,B取值为0或1 。
1表示船在左岸,0 表示船在右岸。
d 表示节点的深度。
下面我们来证明h(n)=M+C-2B是满足A*条件的。
我们分两种情况考虑。
先考虑船在左岸的情况。
如果不考虑限制条件,也就是说,船一次可以将三人从左岸运到右岸,然后再有一个人将船送回来。
这样,船一个来回可以运过河2人,而船仍然在左岸。
而最后剩下的三个人,则可以一次将他们全部从左岸运到右岸。
所以,在不考虑限制条件的情况下,也至少需要摆渡[(M+N-3)/2]*2+1次。
其中分子上的"-3"表示剩下三个留待最后一次运过去。
除以"2"是因为一个来回可以运过去2人,需要[(M+N-3)/2]个来回,而"来回"数不能是小数,需要向上取整,这个用符号[ ]表示。
而乘以"2"是因为一个来回相当于两次摆渡,所以要乘以2。
而最后的"+1",则表示将剩下的3个运过去,需要一次摆渡。
化简有:M+N-2。
再考虑船在右岸的情况。
同样不考虑限制条件。
船在右岸,需要一个人将船运到左岸。
因此对于状态(M,N,0)来说,其所需要的最少摆渡数,相当于船在左岸时状态(M+1,N,1)或(M,N+1,1)所需要的最少摆渡数,再加上第一次将船从右岸送到左岸的一次摆渡数。
因此所需要的最少摆渡数为:(M+N+1)-2+1。
其中(M+N+1)的"+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个状态构成。
下表列出分析的结果:()(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个合法状态。
传教士-野人问题
传教士-野人问题传教士-野人问题有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)。
传教士野人过河问题两种解法思路
第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。
方法二:启发式搜索
构造启发式函数为:
选择较大值的结点先扩展。
野人传教士过河问题
一、对N=5、k≤3时,求解传教士和野人问题的产生式系统各组成部分进行描述(给出综合数据库、规则集合的形式化描述,给出初始状态和目标条件的描述),并画出状态空间图。
答:用M表示传教士,C表示野人,B表示船,L表示左岸,R表示右岸。
初始状态:目标状态:1,综合数据库定义三元组:(M,C,B)其中:0=<M l<=5,表示传教士在河左岸的人数。
0=<C l<=5,表示野人在河左岸的人数。
B l属于集合(0,1),B l=1,表示船在左岸,B l=0,表示船在右岸。
2,规则集规则集可以用两种方式表示,两种方法均可。
按每次渡河的人数分别写出每一个规则,共(3 0)、(0 3)、(2 1)、(1 1)、(1 0)、(0 1)、(2 0)、(0 2)八种渡河的可能(其中(x y)表示x个传教士和y个野人上船渡河),因此共有16个规则(从左岸到右岸、右岸到左岸各八个)。
注意:这里没有(1 2),因为该组合在船上的传教士人数少于野人人数。
规则集如下:IF (M l, C l, 1) THEN (M l -3, C l, 0) p30IF (M l, C l, 1) THEN (M l, C l -3, 0) p03IF (M l, C l, 1) THEN (M l -2, C l -1, 0) p21IF (M l, C l, 1) THEN (M l -1, C l -1, 0) p11IF (M l, C l, 1) THEN (M l -1, C l, 0) p10IF (M l, C l, 1) THEN (M l, C l -1, 0) p01IF (M l, C l, 1) THEN (M l -2, C l, 0) p20IF (M l, C l, 1) THEN (M l, C l -2, 0) p02IF (M l , C l, 0) THEN (M l +3, C l, 1) q30IF (M l, C l, 0) THEN (M l, C l +3, 1) q03IF (M l, C l, 0) THEN (M l +2, C l +1, 1) q21IF (M l, C l, 0) THEN (M l +1, C l +1, 1) q11IF (M l, C l, 0) THEN (M l +1, C l, 1) q10IF (M l, C l, 0) THEN (M l, C l +1, 1) q01IF (M l, C l, 0) THEN (M l +2, C l, 1) q20IF (M l, C l, 0) THEN (M l, C l +2, 1) q02第二种方法:将规则集综合在一起,简化表示。
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)
传教士和野人渡河问题
传教士和野人渡河问题刘宪国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来声明一个最基本的链表。
野蛮人过河问题算法说明及程序
传教士与野人问题算法及程序说明0810504班一.问题说明有3个传教士和3个野蛮人来到河边,打算乘一只船从左岸渡到右岸。
该船的负载能力为2人,在任何时刻如果野蛮人人数超过传教士人数,野蛮人就会把传教士吃掉。
他们怎样才能用这条船安全让所有人都渡过河。
二.算法说明采用递归算法。
因为每次过河都要遵循几个约定,一为两边岸上野蛮人的数量必须大于传教士的数量,二为船上最多只能装两个人,所以采用递归算法不断嵌套循环模拟每次过河的过程,同时加上若干递归中止返回条件,则可以推得过河的方法。
三.数据结构船结构:即表示船上野蛮人和传教士的个数typedef struct Boat{int numX; /// 传教士个数int numY; /// 野蛮人个数}Boat;从左岸到右岸时船上装的人的种类,有3种,即2个野人和0个传教士,0个野人和2个传教士,1个野人和1个传教士。
Boat LtoR[3]={{2,0},{0,2},{1,1}};从右岸回左岸时船上装的人的种类,有2种,即1个野人或1个传教士Boat RtoL[2]={{1,0},{0,1}};递归函数1: int fnPassRiver1(x1,y1,x2,y2)表示每次由一个野蛮人驾船从右岸回左岸后,再向右过河的过程递归函数2: int fnPassRiver2(x1,y1,x2,y2)表示每次由一个传教士驾船从右岸回左岸后,再向右过河的过程四.具体算法第一次过河时,有三种情况,即2个野人和0个传教士,0个野人和2个传教士,1个野人和1个传教士,所以在主函数中用参数是k的三重for循环,确定整体过河框架。
在接下来的从左向右的过河之前,存在两种可能,即驾船从右边回来的是野蛮人或传教士,因此用两个递归函数fnPassRiver1()和fnPassRiver2()分类。
函数fnPassRiver1()和fnPassRiver2()的内容相似,即先递归中判断止条件,若满足三个条件中的任意一个,都跳出此次循环,回到上一级递归;若不满足,则进入下一级循环,此时改变了函数fnPassRiver1(x1,y1,x2,y2)和fnPassRiver2(x1,y1,x2,y2)中的传递参数x1,y1,x2,y2,改变的依据是数组LtoR[3]中的三组值。
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题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操作的下标,即分别表示船载的传教士数和食人者数。
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题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操作的下标,即分别表示船载的传教士数和食人者数。
传教士与食人魔过河
标出。
Sk=(m, c, b)
初始状态只有一个:S0=(3, 3, 1),初始状态表示全部成员在河的的左岸;
目标状态也只有一个:Sg=(0,0,0),表示全部成员从河的左岸全部渡河完毕。
(3)定义并确定操作集。
仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为 Pij 操作。其中,第一下标
i 表示船载的传教士数,第二下标 j 表示船载的食人者数;同理,从右岸将船划回左岸称之
{ int i , loop; struct SPQ *newnode; struct SPQ *ntx; loop = oend -> loop; ntx = oend; resultnum = 0; for( i = 0 ; i <= loop ; i++ ) { newnode = (struct SPQ*) malloc (sizeof(spq)); if(newnode==NULL) { printf("\n 内存不够!\n"); exit(0); } newnode -> sr = ntx -> sr; newnode -> pr = ntx -> pr;
表 6—1 传教士和食人者问题的全部可能状态
状态
m, c, b 状 态 m, c, b 状 态
m, c, b 状 态
m, c, b
S0
3,3,1
S8
1,3,1
S16
Hale Waihona Puke 3,3,0S241,3,0
S1
3,2,1
S9
1,2,1
S17
3,2,0
S25
1,2,0
S2
3,1,1
S10
传教士野人问题参考答案
传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<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)。
模拟十二
模拟十二一、传教士渡河问题:在河的左岸有N个传教士和N个野人,河边有一条小船,每次只能乘载两个人渡河,为了保证安全,任何时候野人的数目都不能超过传教士的数目。
给定N,求出所有的渡河方案。
输入:文件的输入只有一个整数N(N<=8)输出:文件的输出第一行只有一个整数N,表示N种渡河方案。
接下来是渡河方案,每个渡河方案包含三个用一个空格分隔整数M C B。
其中M为左岸传教士的数目,C为野人的数目,B为船在左岸的标志,B=1表示船在左岸,B=0表示船在右岸。
每种方案应该包含每一次的渡河过程。
两种不同方案之间用一个空行分隔。
二、输入一个字母组成的集合X(X的元素个数不超过5个),输出一个由集合X的元素组成的长度不超过N的不含有连续相同的子串的字符串个数。
输入:文件的输入只有两行,第一行为集合X中提供的字符,第二行为一个整数N。
输出:文件的输出只有一个整数,为符合问题的所有字符串个数。
三、输入数据是3个整数:K(K〈=20,)N(N〈=6),M(M〈=20)。
给定一个圆,它被分成n个扇区,请为每一个扇区选择一个整数(必须大于等于K)。
向各扇区中放入整数之后,你可以从单个扇区中选取一个整数;或从相邻的2个或多个扇区中各选一个整数,相加后形成一个新的整数,请使用这些整数以形成一个连续的整数序列:m,m+1,m+2,…,Im是预先给定的,你的任务是使整数I尽可能大。
输入:文件中只有三个用一个空格分隔的整数N,M,K。
输出:文件的第一行为你的数字序列产生的最大整数I。
以下各行列出各圆中各扇区中数字安排的所有可能的方案,这种安排必须能够产生整数序列:m,m+1,m+2,…,I。
每一种方案都是一个数字列表,它独占一行,其中第一个数字必须是本行中各数字的最小者。
第六章 问题解决与创造力培养
小学儿童问题解决能力的培养
创造适当的氛围,鼓励学生主动质疑 帮助学生正确表征问题 帮助学生形成合理的知识结构 对学生的思维策略进行训练 帮助学生养成分析问题和策略性思维的习 惯
第二节 创造性及其培养
创造性是心理学研究中一个热门领域和焦 点问题。 对创造性的研究,有助于人们克服种种困 难,完成意料之外的任务,增加选择和行 为的自由度。 对教师而言,有助于理解素质教育的深刻 内涵,促进教学改革的深入。
我国高创造性学生的特点(郑日昌)
作文想象力丰富,能独立选材,题材新颖、风趣,审 美感强; 能闻一知十,举一反三,触类旁通; 对环境的感受力相当高,能察觉别人忽略的事实; 心智活动思路通畅,解答问题敏捷; 能提出卓越见解,以特异方法解决问题,用新奇方式 处理问题; 办事非常热心,坚持不懈,不怕挫折; 独立性强,有评鉴力,有主见,不轻听别人的意见; 有自信心,有理想抱负; 兴趣广泛又专一; 有强烈的好奇心和探究心理。
(三)创造性的主要成分
1 、认知成分:包括创造的意图、创造的 动机、创造的欲望等,它是创造活动强有 力的推动力。 2 、创造性思维:指有创见的思维,是创 造活动的核心成分。 3 、创造性人格:研究表明,高创造者一 般具有其显著的人格特点。
创造型学生的人格和行为特点(美国)
1.具有创造才能学生的人格特征 对自己的信念坚定不移; 有强烈的好奇心; 沉醉于自己正在从事的工作; 感受性高; 思维独立性强; 善于利用自己的直觉; 不迷信权威; 敢冒风险; 富于幽默感; 态度乐观; 成就动机高; 想象力高强。
其基本做法是:教师先提出问题,然后鼓励学生寻找尽可能 多的答案,不必考虑答案是否正确,教师也不作评论,一直 到所有可能想到的答案都提出来了为止。 采用班组讨论的方法来解决问题。通过集体讨论,每个学生 从各自不同的角度提出不同的见解,大大拓宽了解决问题的 范围,有时,一个学生的发言能启发另一个学生悟出或改进 解决问题的方法。此外,小组讨论能产生社会心理学家称之 为“社会促进”的现象,即当一个人看到其他人正在完成某 个任务时,自己也会积极去思考。 小组讨论对创造性思维也有不利的一面 。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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人第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人问题结束由结果可以看出,方法二的结果为方法一的第一种结果,两者具有一致性。
五、总结与教训:最开始时采用的方法为:用向量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;。