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

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

一、算法的定义
有三个牧师和三个野人过河,只有一条能装下 两个人的船,在河的任何一方或者船上,如果野人 的人数大于牧师的人数,那么牧师就会有危险(被 野人吃掉)。你能找出一种安全的渡河方案吗?请 记录详细的方法和步骤!
第一步:两个野人划船到B岸 一个野人划船回到A岸
第二步:两个野人划船到B岸 一个野人划船回到A岸
请大家把书本打开翻到68页,快速浏览 本页的内容。
流程图的常用符号
起止框;输入输出框;处理框;判断框;流程线。
图形符号
名称
说明
起止框 算法的开始或结束
输入输出框 输入和输出数据
处理框 指出要处理的内容
判断框 条件判断及产生分支的情况
流程线 从一个步骤到下一个步骤
五、程序的三种基本结构
顺序结构 早晨起床
第二步:在含有假币的那组金币中任意取2枚分别放在天平两边,若平衡,则剩下 的那枚是假币;若不平衡,较轻的那枚是假币。
自然语言表示
开始 将9枚金币平均分成3组
任取其中2组分别放在天平两边
Y
N
是否平衡?
输出Y 结束
假币在剩下的那组中
任取其中2枚分别放在天平两边
Y
N
是否平衡?
假币在较轻的那组中
三、算法的表示形式
请设计一个算法,求键盘输入两数之和并输出结果。
自然语言
用键盘先输入一个数, 再输入另一个数, 计算两数和, 输出“和”的结果。
流程图
开始 输入一个加数 输入另一个加数 计算两数之和
输出和 结束
计算机语言
Private Sub Command1_Click()
a = Val(Text1.Text) b = Val(Text2.Text) sum = a + b Print sum End Sub
我对野人过河的问题思考

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)
课程设计--修道士野人过河问题

数据结构课程设计修道士野人过河问题班级:计师111学号:1113012027姓名:成粤任课老师:陈德裕时间:2013.01.16修道士与野人问题假设有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)数据结构设计逻辑结构设计: 图型结构存储结构设计: 链式存储结构采用这种数据结构的好处:便于采用广度搜索法,得到首先搜索到的边数最少的一条通路,输出一个最佳方案,采用图的邻接表存储结构搜索效率较高。
传教士野蛮人过河问题--python

传教⼠野蛮⼈过河问题--python三名传教⼠和三个野蛮⼈同在⼀个⼩河渡⼝,渡⼝上只有⼀条可容两⼈的⼩船。
问题的⽬标是要⽤这条⼩船把这六个⼈全部渡到对岸去,条件是在渡河的过程中,河两岸随时都保持传教⼠⼈数不少于野蛮⼈的⼈数,否则野蛮⼈会把处于少数的传教⼠状态集合为(x,y,b)三元组,x表⽰左岸野⼈数,y表⽰左岸传教⼠数,x,y取值0~3。
b为0表⽰船在左边,b为1表⽰船在右边动作集合为⼀个传教⼠从左到右,两个传教⼠从左到右,⼀个野⼈从左到右,两个野⼈从左到右,⼀个野⼈⼀个传教⼠从左到右;从右到左类似也有5个动作,共10个动作,于是就可以画出⼀个状态转换图,下⾯的python代码可以帮助我们完成这个任state_legal判断给定状态是否合法,act_legal判断在当前状态执⾏给定动作是否合法,f(x,y,b)打印所有从(x,y,b)可以执⾏的动作和转移到的状态def state_legal(x, y, b):if x < 0 or y < 0 or x > 3 or y > 3:return Falseif y < x and y > 0:return Falseelif (3-y) < 3-x and 3-y > 0:return Falseelse:return Truedef act_legal(x, y, b, xx, yy, bb):if b != bb:return Falseif b == 0 and state_legal(x - xx, y - yy, 1 - b):return Trueelif b == 1 and state_legal(x + xx, y + yy, 1 - b):return Trueelse:return False#when calling f, (x,y,b) is ensured to be state_legaldef f(x,y,b):for act in actions:if act_legal(x, y, b, act[0], act[1], act[2]):if act[2] == 0:print(x,y,b,"---",act, '---', x - act[0], y - act[1], 1 - b)else:print(x,y,b,"---",act, '---', x + act[0], y + act[1], 1 - b)a = (0,1,2,3)actions = []for b in (0,1):for x in (0,1,2):for y in (0,1,2):if x + y >= 1 and x + y <= 2:actions.append((x,y,b))print(actions)for x in a:for y in a:for b in (0,1):if not(x == 0 and y == 0) and state_legal(x, y, b):f(x,y,b)#x is num of savages, y is num of missionaries。
野人过河问题算法分析

野人过河问题算法分析野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢?一、算法分析先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:初始状态:甲岸,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。
二、基本数据结构仔细阅读问题,可以发现有些基本东西我们必须把握,例如:每时刻河两岸野人牧师各自的数目、船的状态、整个问题状态。
传教士与野人过河问题

传教士-野人问题有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个野人来到河边渡河, 河岸有一条船, 每次至多可供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个合法状态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
野人过河问题算法分析野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢?一、算法分析先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:初始状态:甲岸,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, 乙岸为1BOAT boat; // 船的状态_question* pPrev; // 指向前一渡船操作_question* pNext; // 指向后一渡船操作}QUESTION;用QUESTION来声明一个最基本的链表。
三、程序流程及具体设计本文只找出了最优解,据我所知,本问题有三种解。
如果真要找出这三种解,^_^,那就得加强对链表的操作了,比如说自己写一个动态链表类,顺便完成一些初始化工作,估计看起来会舒服些。
下面给出部分关键程序:// 主函数int main(){// 初始化QUESTION* pHead = new QUESTION;pHead->riverSide1.wildMan = 3;pHead->riverSide1.churchMan = 3;pHead->riverSide2.wildMan = 0;pHead->riverSide2.churchMan = 0;pHead->side = -1; // 船在甲岸pHead->pPrev = NULL;pHead->pNext = NULL;pHead->boat.wildMan = 0;pHead->boat.churchMan = 0;if (Process(pHead)){// ......... 遍历链表输出结果}cout<<"成功渡河。
";}elsecout<<"到底怎样才能渡河呢? 郁闷!"<<endl;// 回收内存空间while (pHead){QUESTION* pTemp = pHead->pNext;delete pHead;pHead=pTemp;}pHead = NULL;return 0;}// 渡船过程, 递规调用函数FindNext(...)BOOL Process(QUESTION* pQuest){if (FindNext(pQuest)){QUESTION* pNew = new QUESTION;pNew->riverSide1.wildMan = pQuest->riverSide1.wildMan + pQuest->boat.wildMan*(pQuest->side);pNew->riverSide1.churchMan =pQuest->riverSide1.churchMan + pQuest->boat.churchMan*(pQuest->side); pNew->riverSide2.wildMan = 3 - pNew->riverSide1.wildMan; pNew->riverSide2.churchMan = 3 -pNew->riverSide1.churchMan;pNew->side = (-1)*pQuest->side;pNew->pPrev = pQuest;pNew->pNext = NULL;pNew->boat.wildMan = 0;pNew->boat.churchMan = 0;pQuest->pNext = pNew;if (pNew->riverSide2.wildMan==3 &&pNew->riverSide2.churchMan==3)return TRUE; // 完成return Process(pNew);}else{QUESTION* pPrev = pQuest->pPrev;if (pPrev == NULL)return FALSE; // 无解delete pQuest;pPrev->pNext = NULL;return Process(pPrev); // 返回其父节点重新再找}return TRUE;}// 判断有否下一个渡河操作, 即根据比较算符找出可以接近目标节点的操作// 算符共5个: 1野/ 1牧 / 1野1牧 / 2野 / 2牧BOOL FindNext(QUESTION* pQuest){// 基本规则// 渡船的优先顺序: 甲岸运多人优先, 野人优先; 乙岸运少人优先, 牧师优先.static BOAT boatState[5]; // 5个算符if (pQuest->side == -1){boatState[0].wildMan = 2;boatState[0].churchMan = 0;boatState[1].wildMan = 1;boatState[1].churchMan = 1;boatState[2].wildMan = 0;boatState[2].churchMan = 2;boatState[3].wildMan = 1;boatState[3].churchMan = 0;boatState[4].wildMan = 0;boatState[4].churchMan = 1;}else{boatState[0].wildMan = 0;boatState[0].churchMan = 1;boatState[1].wildMan = 1;boatState[1].churchMan = 0;boatState[2].wildMan = 0;boatState[2].churchMan = 2;boatState[3].wildMan = 1;boatState[3].churchMan = 1;boatState[4].wildMan = 2;boatState[4].churchMan = 0;}int i; // 用来控制算符if (pQuest->boat.wildMan == 0 && pQuest->boat.churchMan == 0) // 初始状态, 第一次渡河时i = 0; // 取算符1else{for (i=0; i<5; i++) // 扩展同一节点时, 已经用过的算符不再用, 按优先级来if (pQuest->boat.wildMan == boatState[i].wildMan && pQuest->boat.churchMan == boatState[i].churchMan)break;i++;}if (i < 5){int j;for (j=i; j<5; j++){int nWildMan1 = pQuest->riverSide1.wildMan + boatState[j].wildMan * pQuest->side;int nChurchMan1 = pQuest->riverSide1.churchMan + boatState[j].churchMan * pQuest->side;int nWildMan2 = 3 - nWildMan1;int nChurchMan2 = 3 - nChurchMan1;// 判断本次操作的安全性, 即牧师数量>=野人或牧师数为0if ((nWildMan1 <= nChurchMan1 || nChurchMan1 == 0) &&(nWildMan2 <= nChurchMan2 || nChurchMan2 == 0) &&nWildMan1 >=0 && nChurchMan1 >=0 && nWildMan2 >=0 && nChurchMan2 >= 0){// 本操作是否重复上次操作,注意方向不同if (pQuest->pPrev != NULL){if (pQuest->pPrev->boat.wildMan == boatState[j].wildMan &&pQuest->pPrev->boat.churchM an == boatState[j].churchMan)continue;}break; // 该操作可行, 推出循环,只找出当前最优节点}}if (j < 5){pQuest->boat.wildMan = boatState[j].wildMan;pQuest->boat.churchMan = boatState[j].churchMan; return TRUE;}}return FALSE;}。