请问传教士和野人问题怎么用c++实现?

zzw820626 2003-12-14 03:23:16
请问传教士和野人问题怎么用c++实现?
...全文
554 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
yifengling0 2003-12-14
  • 打赏
  • 举报
回复
http://www.vccode.com/file_show.php?id=2056

可以在这里下到代码
yifengling0 2003-12-14
  • 打赏
  • 举报
回复
vccode 上的一个文章,希望有点帮助

传教士与野人问题解决方案--A*算法
问题的提出
设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。该船的负载能力为两人。在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。他们怎样才能用这条船安全地把所有人都渡过河去?

分析
为了使渡河的次数尽可能的少,理想的方案是从右岸去左岸时船满载(载两个人),从左岸回来时载一个人,如果不考虑任何时候野人人数不得超过传教士的人数的这个限制条件,容易推出最快的渡河步数为9步。 J
解决方案
1. 状态空间表示
传教士
野人
船上人数 
左岸人数
右岸人数
如:       

表示右岸有两个传教士和一个野人,船上有一个野人,左岸有一个传教士和一个野(辅助node 数据结构中的RightToLeft标志就可知道船的走向)

初始状态 目标状态
2. 扩展规则
按照每次船载人的几种可能性来进行状态空间的扩张,同时需满足以下要求:
l 状态矩阵中任何元素为非负的整数
l 任何时候野人的人数不得超过传教士的人数
l 船上人数不得超过两个,但也不能为零个,否则无意义(初始状态和目标状态除外)
由此,状态矩阵表示船上人数的行向量只有五种组合:(0 ,1)(1,0)(1,1)(0,2)(2,0),扩展的时候同时需考虑船的位置。 J
3. 搜索算法
采用有序搜索中的A*算法实现整个搜索过程,启发函数为
f(n)=g(n)+h(n)
g(n)取搜索树中结点的深度(node.step),
h(n)取理想状态下从该结点到目标结点最小的路径深度(有公式)。
(关于f(n)的定义,有兴趣的可参考函数void UpdateFn(node *expandnode)的定义部分,不是很完美的一个估价函数,但比较好理解) J
程序设计
1. 程序框图
基本同书P.72图3.11,不过在处理succssor结点上不同,实在找不到一个好的画框图的软件,用word来作它实在是太费时了,先搁着不画。
2. 数据结构
l struct node { //状态结点数据结构
int Sspace[3][2]; //状态空间
bool RightToLeft; //记录船的走向,为true时表示船从右岸到左岸,false为由左到右
int Fn; //结点的权值
int step; //接点载搜索树中的深度
struct node * father; //指向父辈结点,用来返回父辈结点的信息
}
l struct list{ //open表和close表中结点的数据结构
struct list *previous; //指向链表中前一个结点
struct node StateNode; //存放状态结点数据信息
struct list *next; //之相链表中后一个结点
}
l open表和close表均采用链表形式,这样可以很方便的对结点尽心删除、增加和查找等操作,而且在搜索空间不确定的情况下可以更合理的对内存空间进行管理。其中,open表带有三个指针
list *OpenlistHead //头结点指针
list *OpenlistIndex //指向搜索到的最佳扩展结点的指针
list *OpenlistTail //链表尾指针
close表带有两个指针
list *ClosedlistHead //头结点指针
list *ClosedlistTail //尾结点指针
3. 说明
程序在Visual C++6.0环境下编译通过,结果可以在dos提示符下输入solution >>result.txt命令获得一个文本文件,然后用一个文本编辑软件查看。
源程序有少量的注释,目前对野人与传教士人数的限制有两种理解,若想看一看所谓的九步就能全部渡过江去,只需将solution.cpp文件中bool TryToExpandNode(list *openlisthead,list *closedlisthead,node *expandnode,int m,int s)函数定义部分的下面几行代码注释掉,重新编译运行即可。
if((expandnode->SSpace[Right][M]+m)<(expandnode->SSpace[Right][S]+s)&&expandnode->SSpace[Right][M]+m!=0) return false;
if((expandnode->SSpace[Left][M]+m)<(expandnode->SSpace[Left][S]+s)&&expandnode->SSpace[Left][M]+m!=0) return false;
由于估价函数f(n)选取的原因,搜索过程不一定很完美,也许有很多人须改进的地方,但目前的水平,只能搜索到这种程度了,至于是否算得上啊A*算法,我还不敢确认。 J
作者:bye
Email:liuwenguo@sina.com


16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧