- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
传教士问题
一. 问题描述 ? ? 有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,表示送船到左岸时的一次摆渡。 化简有:(M+N+1)-2+1=M+N。 ? 综合船在左岸和船在右岸两种情况下,所需要的最少摆渡次数用一个式子表示为:M+N-2B。其中B=1表示船在左岸,B=0表示船在右岸。 由于该摆渡次数是在不考虑限制条件下,推出的最少所需要的摆渡次数......从前有一条河,河的左岸有m个传教士(Missionary)和m个野人(Cannibal),和一艘最多可乘n人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
编程,接收m和n,搜索一条可让所有的野人和传教士安全渡到右岸的方案。
?
我们先假设左岸有3个传教士和3个野人,小船最多可乘2人。把当前左岸的状态抽象为:
(3,3,1)
前两个3代表左岸有3个传教士和3个野人,1代表船在左岸。把每一次可行的渡船方案作为算符。比如,在初始状态,让1个传教士和1个野人上船并渡到右岸,这一算符可表示为:
(1,1)
算符的两位数分别代表要移动的传教士,野人的数量;把人移到没有船的岸边并且改变状态向量中船的值。
对于固定大小的小船,算符的数量是一定的:
class Move {
public:
??? int missionary;????? //要移动的传教士数量
??? int cannibal;??????? //野人
};
class MoveGroup {
public:
??? Move move[500];????? //算符集
??? int numMove;???????? //可用算符的总数
??? MoveGroup(int MAX_ON_BOAT) {??? //利用构造器求算符集
?????? int m, c, i = 0;
?????? for (m = 0; m = MAX_ON_BOAT; m++)
?????????? for (c = 0; c = MAX_ON_BOAT; c++)
????????????? if (c==0 m!=0) {
move[i].missionary=m;
move[i].cannibal=0;
i++;
}
????????????? else if (m==0 c!=0) {
move[i].missionary=0;
move[i].cannibal=c;
i++;
}
????????????? else if (m+c=MAX_ON_BOAT m+c!=0 m=c) {
move[i].missionary = m;
move[i].cannibal = c;
i++;
}
?????? numMove = i;
??? }
};
创建一个MoveGroup 对象
MoveGroup mg(2);
即可得到当小船最多可乘2人时的算符集。
?
这个程序所要做的,就是通过这个已知的算符集,将初始状态(3,3,1)转变为最终状态(0,0,0)。我们应将状
文档评论(0)