ImageVerifierCode 换一换
格式:DOCX , 页数:8 ,大小:26.63KB ,
资源ID:2364196      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/2364196.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(传教士问题.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

传教士问题.docx

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、,船一个来回可以运过河2人,而船仍然在左岸。而最后剩下的三个人,则可以一次将他们全部从左岸运到右岸。所以,在不考虑限制条件的情况下,也至少需要摆渡(M+N-3)/2*2+1次。其中分子上的3表示剩下三个留待最后一次运过去。除以2是因为一个来回可以运过去2人,需要(M+N-3)/2个来回,而来回数不能是小数,需要向上取整,这个用符号 表示。而乘以2是因为一个来回相当于两次摆渡,所以要乘以2。而最后的1,则表示将剩下的3个运过去,需要一次摆渡。 化简有: M+N-2。 再考虑船在右岸的情况。同样不考虑限制条件。船在右岸,需要一个人将船运到左岸。因此对于状态(M,N,0)来说,其所需要的最少摆渡数,

3、相当于船在左岸时状态(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。其中B1表示船在左岸,B0表示船在右岸。 由于该摆渡次数是在不考虑限制条件下,推出的最少所需要的摆渡次数.从前有一条河,河的左岸有m个传教士(Missionary)和m个野人(Cannibal),和一艘最多可

4、乘n人的小船。约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。编程,接收m和n,搜索一条可让所有的野人和传教士安全渡到右岸的方案。我们先假设左岸有3个传教士和3个野人,小船最多可乘2人。把当前左岸的状态抽象为:(3,3,1)前两个3代表左岸有3个传教士和3个野人,1代表船在左岸。把每一次可行的渡船方案作为算符。比如,在初始状态,让1个传教士和1个野人上船并渡到右岸,这一算符可表示为:(1,1)算符的两位数分别代表要移动的传教士,野人的数量;把人移到没有船的岸边并且改变状态向量中船的值。对于固定大小的小船,算符的数量是一定的:class Move public

5、: int missionary; /要移动的传教士数量 int cannibal; /野人;class MoveGroup public: Move move500; /算符集 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) movei.missionary=m;movei.cannibal=0;i+; else if (m=

6、0 & c!=0) movei.missionary=0;movei.cannibal=c;i+; else if (m+c=c) movei.missionary = m;movei.cannibal = c;i+; numMove = i; ;创建一个MoveGroup 对象MoveGroup mg(2);即可得到当小船最多可乘2人时的算符集。这个程序所要做的,就是通过这个已知的算符集,将初始状态(3,3,1)转变为最终状态(0,0,0)。我们应将状态作为搜索的元素。构建类时应注意,并不是每个算符对于任意的状态都是可以应用的,这需要对应用算符后的安全性进行检查,以判断这一算符对当前状态是否

7、可用;同时,类中也要包含一个判断当前状态是否是最终节点(0,0,0)的方法;当然”=”,”=”这两个运算符以及null值,这是调用dso.h时所不可或缺的。(详见源文件)class ElemType : Move /继承Move类,获得传教士,野人数据成员。private: bool boat; /船是否在左岸?public: ElemType* flag; /这个后边再说,暂时用不到 ElemType(int MAX_PEOPLE) /创建初始状态 missionary = cannibal = MAX_PEOPLE; boat = true; flag = NULL; ElemType()

8、 bool operator =(ElemType e) return this-missionary=e.missionary &this-cannibal=e.cannibal &this-boat=e.boat; void operator =(ElemType e) this-missionary = e.missionary; this-cannibal = e.cannibal; this-boat = e.boat; this-flag = e.flag; ElemType friend operator (ElemType source, Move &mv) /移动操作,通过重

9、载运算符“”,你将在isSafe(ElemType)中见到用法。 ElemType result; if(source.boat = 1) result.missionary = (source.missionary -= mv.missionary); result.cannibal = (source.cannibal -= mv.cannibal); result.boat = 0; else result.missionary = (source.missionary += mv.missionary); result.cannibal = (source.cannibal += mv

10、.cannibal); result.boat = 1; return result; bool isSafe(Move &mv, int MAX_PEOPLE) /判断当前状态在进行mv操作后还是不是安全状态 if( (boat=1&(missionary-mv.missionary 0 | cannibal-mv.cannibal MAX_PEOPLE | cannibal+mv.cannibal MAX_PEOPLE) ) return false; else ElemType temp = *this mv; if( temp.missionary=0 | temp.missionar

11、y=MAX_PEOPLE | (temp.missionary=temp.cannibal & MAX_PEOPLE-temp.missionary = MAX_PEOPLE-temp.cannibal) return true; else return false; bool isSuccess() return missionary=0 & cannibal=0 & boat=0; /isSuccess()判断当前状态是否为最终节点 int getM() return missionary; int getC() return cannibal; int getB() return boat; void print() cout ( missionary , cannibal, boat ) next; while(temp != rear) if(temp-next = rear) return &temp-next-node; temp = temp-next; return &temp-node; ;当得到了一个最终节点(0,0,0)时,如果我们前边的操作没有保存路径的话,那么我们就只知道这个问题有解

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1