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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

农夫过河问题的算法与实现讲解.docx

1、农夫过河问题的算法与实现讲解 农夫过河问题的算法与实现院(系)名称 专 业 班 级 学 号 学 生 姓 名 指 导 教 师 年 月 日引言.11.问题的描述.22.需求分析.33.概要设计.4 3.1数据结构的设计.4 3.2算法的设计.5 3.3抽象数据类型的设计.54.详细设计.6 4.1算法的主要思想.6 4.2主要功能函数设计.7 4.3算法的实现.75.代码实现.106.测试与运行.18 6.1测试工具.18 6.2运行结果.18 七.总结与体会.19八.参考文献.20 农夫过河问题的算法与实现 引言所谓农夫过河问题是指农夫带一只狼、一只羊和一棵白菜在河南岸, 需要安全运到北岸。一条

2、小船只能容下他和一件物品, 只有农夫能撑船。问农夫怎么能安全过河, 当然狼吃羊, 羊吃白菜, 农夫不能将这两种或三种物品单独放在河的一侧, 因为没有农夫的照看, 狼就要吃羊, 而羊可能要吃白菜? 这类问题的实质是系统的状态问题, 要寻求的是从初始状态经一系列的安全状态到达系统的终止状态的一条路径.一.问题的描述任何的实际问题,都可以抽象成固定的数学模型,然后再根据模型解决问题。这样就可以不考虑繁琐的实际过程,从而简化问题。在我们的问题中,过河与没过河是两种不同的状态。农夫、狼、羊和菜,分别处于这两种状态。而,如果把他们看成一个系统,则农夫、狼、羊和菜的不同状态组合成系统的2的4次方种,即16种

3、状态。但在系统的16种状态中,有些不满足题给条件,应给予剔除。剔除的判断条件:羊跟狼、菜状态相同,且不同于农夫的状态。当我们挑选好一系列系统的合法状态后,我们的问题就清晰了很多。我们不妨设,没过河状态为0,过河为1。我们的问题就抽象为,系统从初始状态(0000),经过有限的合法状态,到达最终状态(1111)的过程。系统不同的合法状态之间,可能,有的有路,有的则不能到达。具体的判断条件是,农夫可以与一件物品同时边,或自己单独变。根据这一个条件,我们可以抽象出一个图来:系统的每一种状态视为一个节点,满足条件的节点间有一条路。这样问题就抽象为,在无向图中找一条路。二、需求分析1、针对实现整个过程需要

4、多步,不同步骤中各个事物所处位置不同的情况,可定义一个结构体来实现对四个对象狼、羊、白菜和农夫的表示。对于起始岸和目的岸,可以用0或者1来表示,以实现在程序设计中的简便性。2、题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,进行下一步试探。这就需要使用循环或者递归算法,避免随机盲目运算且保证每种情况均试探到。 3、题目要求求出农夫带一只羊,一条狼和一颗白菜过河的办法,所以依次成功返回运算结果后,需要继续运算,直至求出结果,即给出农夫的过河方案。4、输出界面要求具有每一步中农夫所带对象及每步之后各岸的物体,需要定义不同的数组来分别

5、存储上述内容,并使界面所示方案清晰简洁。 三.概要设计3.1数据结构的设计利用图论知识求解的过程。假设分别用farmer表示农夫,wolf表示狼,sheep表示羊,veget表示白菜。初始状态是f、w、s、v都在原岸,即初始状态V1为=f,w,s,v,在原岸全部可能出现的状态为以下16种:fwsv、fwv、fsv、wsv、fw、fs、fv、ws、wv、sv、f、w、s、v、,这里表示原岸是空集, 即人、狼、羊、白菜都已运到河的对岸去了。 根据题意可以得到,这16种情况中有6种情况是不允许出现的。它们是:wsv(狼、羊、白菜)、fw(农夫、狼)、fv(农夫、白菜)、ws(狼、羊)、 sv(羊、白

6、菜)、f(农夫)。如fv表示人和白菜在原岸,而狼和羊在对岸,这显然是不行的。因此,允许出现的情况只有10种。 我们构造一个图,它的顶点就是这10种状态。如果船某次从河的一岸划往另一岸时,使原岸的状态从V变成V,我们就作一条从V到V的弧,这样就可以得到如下图所示的有向图人狼羊白菜 人狼 人狼白菜 人羊白菜 人羊 狼白菜 狼 草 羊 空 由于船是在两岸间往返的,那么“过河”问题就转换成在上图中找出一条由结点fwsv到结点的路径,这条路径中相邻的两条弧或者都是由同一点引出的,或者都是进入同一个结点的,这样的路径是很容易找到的。从图中得到两条这样的路径,路径一:人狼羊白菜狼白菜人狼白菜白菜人羊白菜羊人

7、羊,路径二:人狼羊白菜狼白菜人狼白菜狼人狼羊羊人羊,它们的长度都是7,也就是说,农夫至少要经过7次摆渡才能将狼、羊、白菜都安全摆渡到对岸,可以有两种方案。如果要求解至少需要摆渡的次数,那就是去找路径长度最小的路径。从上面的分析得知,需要在图中找出一条从顶点fwsv到顶点的最短路径。采用广度优先搜索算法:用一个具有四个元素的数组来表示人、狼、羊、白菜在原岸的状态。初始顶点V1为人、狼、羊、白菜都在原岸,即V1=1,1,1,1,当人或某一件物品在对岸时,相应的数组元素值置为0。扩展新顶点所用的运算算符有以下四种情况:农夫独自摆渡过河,农夫带着狼摆渡过河,农夫带着羊摆渡过河,农夫带着白菜摆渡过河。约

8、束条件为当农夫与羊不在一起时,狼与羊或羊与白菜不能在一起,因为在无人看管的情况下,狼要吃羊,羊要吃白菜。按照这样的顶点产生规则和约束条件我们可以在程序中建立如上图所示的有向图,同时,遍历这个有向图,找出顶点到顶点的最短路径和路径长度。3.2算法的设计本程序可以分成四个模块,分别是:找到所有情况的点、从中挑选出满足题意的点、创建满足题意的点之间的边、通过图的深度优先遍历找到过河方案。各模块之间的关系图如下:3.3抽象数据类型的设计 本题采用的是图,因此要用到定义图的结构体 typedef struct / 图的顶点 int farmer; / 农夫int wolf; / 狼int sheep;

9、/ 羊int veget; / 白菜Vertex; typedef struct int vertexNum; / 图的当前顶点数 Vertex vertexVertexNum; / 顶点向量(代表顶点) bool EdgeVertexNumVertexNum; / 邻接矩阵. 用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关 AdjGraph; / 定义图的邻接矩阵存储结构 四.详细设计4.1算法的主要思想为简化结点,将农夫、狼、羊、白菜用0和1两种状态量表示,0表示在河的南岸,也就是初始所在的河岸。1表示在河的北岸,即渡过河到达的对岸。那么初始状态即为0000,将其变为1111的

10、中间状态量即为过河方案。那么就从16种所有情况的顶点中选择符合题意的结点,因为并不是所有点都满足题意,限制要求为农夫每次最多可带狼、羊、白菜中的一个过河,农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开。选出所有满足题意的结点后,就要构造边,边即为符合题意两结点之间的连接。中间有边的两结点必须符合农夫的状态在变,并且农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开。选出所有符合题意的结点和边后就构成了图,采用邻接表的存储结构,然后通过图的深度优先遍历,将所有满足题意的结点遍历一遍并输出,到1111时即输出了过河方案的全部步骤。4.2主要功能函数设计1.查找顶点在顶点向量中的位置in

11、t locate(AdjGraph *graph, int farmer, int wolf, int sheep, int veget)2. 判断目前的(F,W,S,V)是否安全 bool isSafe(int farmer, int wolf, int sheep, int veget) 3.判断状态i与状态j之间是否可转换 bool isConnect(AdjGraph *graph, int i, int j)4.创建连接图void CreateG(AdjGraph *graph)5.输出从u到v的简单路径,即顶点序列中不重复出现的路径 void printPath(AdjGraph

12、*graph, int start, int end) 6.深度优先搜索从u到v的简单路径 /DFS-Depth First Search void dfsPath(AdjGraph *graph, int start, int end)4.3算法的实现 查找顶点在顶点向量中的位置int locate(AdjGraph *graph, int farmer, int wolf, int sheep, int veget)for (int i = 0; i vertexNum; i+) if ( graph-vertexi.farmer = farmer & graph-vertexi.wolf

13、 = wolf & graph-vertexi.sheep = sheep & graph-vertexi.veget = veget ) return i; /返回当前位置 return -1; /没有找到此顶点 判断目前的(F,W,S,V)是否安全 bool isSafe(int farmer, int wolf, int sheep, int veget) /当农夫与羊不在一起时,狼与羊或羊与白菜在一起是不安全的if ( farmer != sheep & (wolf = sheep | sheep = veget) ) return false;else return true; /

14、安全返回true 判断状态i与状态j之间是否可转换 bool isConnect(AdjGraph *graph, int i, int j) int k = 0; if (graph-vertexi.wolf != graph-vertexj.wolf) if (graph-vertexi.wolf != graph-vertexj.wolf) k+; if (graph-vertexi.sheep != graph-vertexj.sheep) k+; if (graph-vertexi.veget != graph-vertexj.veget) k+; / 以上三个条件不同时满足两个且农

15、夫状态改变时,返回真, 也即农夫每次只能带一件东西过桥 if (graph-vertexi.farmer != graph-vertexj.farmer & k = 1) return true; else return false; 5.代码实现#includeusing namespace std;#define VertexNum 16 /最大顶点数 typedef struct / 图的顶点 int farmer; / 农夫int wolf; / 狼int sheep; / 羊int veget; / 白菜Vertex; typedef struct int vertexNum; /

16、图的当前顶点数 Vertex vertexVertexNum; / 顶点向量(代表顶点) bool EdgeVertexNumVertexNum; / 邻接矩阵. 用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关 AdjGraph; / 定义图的邻接矩阵存储结构 bool visitedVertexNum = false; / 对已访问的顶点进行标记(图的遍历) int retPathVertexNum = -1; / 保存DFS搜索到的路径,即与某顶点到下一顶点的路径 int locate(AdjGraph *graph, int farmer, int wolf, int she

17、ep, int veget)for (int i = 0; i vertexNum; i+) if ( graph-vertexi.farmer = farmer & graph-vertexi.wolf = wolf & graph-vertexi.sheep = sheep & graph-vertexi.veget = veget ) return i; /返回当前位置 return -1; /没有找到此顶点 / 判断目前的(F,W,S,V)是否安全 bool isSafe(int farmer, int wolf, int sheep, int veget) /当农夫与羊不在一起时,狼

18、与羊或羊与白菜在一起是不安全的if ( farmer != sheep & (wolf = sheep | sheep = veget) ) return false;else return true; / 安全返回true / 判断状态i与状态j之间是否可转换 bool isConnect(AdjGraph *graph, int i, int j) int k = 0; if (graph-vertexi.wolf != graph-vertexj.wolf) k+; if (graph-vertexi.sheep != graph-vertexj.sheep) k+;if (graph-

19、vertexi.veget != graph-vertexj.veget) k+; / 以上三个条件不同时满足两个且农夫状态改变时,返回真, 也即农夫每次只能带一件东西过桥 if (graph-vertexi.farmer != graph-vertexj.farmer & k = 1) return true; else return false; / 创建连接图void CreateG(AdjGraph *graph) int i = 0;int j = 0; / 生成所有安全的图的顶点 for (int farmer = 0; farmer = 1; farmer+) for (int

20、wolf = 0; wolf = 1; wolf+) for (int sheep = 0; sheep = 1; sheep+) for (int veget = 0; veget vertexi.farmer = farmer; graph-vertexi.wolf = wolf; graph-vertexi.sheep = sheep; graph-vertexi.veget = veget; i+; / 邻接矩阵初始化即建立邻接矩阵 graph-vertexNum = i; for (i = 0; i vertexNum; i+) for (j = 0; j vertexNum; j+

21、) / 状态i与状态j之间可转化,初始化为1,否则为0 if (isConnect(graph, i, j) graph-Edgeij = graph-Edgeji = true; else graph-Edgeij = graph-Edgeji = false; return; / 判断在河的哪一边char* judgement(int state)return ( (0 = state) ? 左岸 : 右岸 );/ 输出从u到v的简单路径,即顶点序列中不重复出现的路径 void printPath(AdjGraph *graph, int start, int end) int i = s

22、tart; cout farmer , wolf , sheep , veget endl;while (i != end) cout ( vertexi.farmer) , vertexi.wolf) , vertexi.sheep) , vertexi.veget) ); cout endl;i = retPathi; cout ( vertexi.farmer) , vertexi.wolf) , vertexi.sheep) , vertexi.veget) );cout endl; / 深度优先搜索从u到v的简单路径 /DFS-Depth First Search void dfsP

23、ath(AdjGraph *graph, int start, int end) int i = 0; visitedstart = true; /标记已访问过的顶点 if (start = end)return ;for (i = 0; i vertexNum; i+) if (graph-Edgestarti & !visitedi) retPathstart = i; dfsPath(graph, i, end); int main() AdjGraph graph; CreateG(&graph); int start = locate(&graph, 0, 0, 0, 0); int

24、 end = locate(&graph, 1, 1, 1, 1); dfsPath(&graph, start, end); if (visitedend) / 有结果 printPath(&graph, start, end); return 0;return -1; 6.测试与运行 6.1测试工具在vc+6.0下调试并运行程序即可得到解决问题的方案.6.2运行结果7.总结与体会通过这个程序的学习,很受启发,明白了如何用计算机解决实际生活中的问题。 刚开始接到这个题目时,感觉到相当困难,因为这种题以前是考验我们的IQ用的, 现在没想到要用计算机来解决,而且计算机又没有思想,怎样让它想问题,

25、实现我们需要的功能。原来,可以把实际的问题转变为数学模型, 通过计算机超强悍的循环功能和强大的数据处理能力, 把所有可能的结果都算出来,然后用约束项来对这些结果进行筛选, 然后把结果用数学格式来输出,让问题得以求解。“纸上得来终觉浅,绝知此事要躬行。”通过这两周的课程设计,使我对书上的的理论知识有了更深的理解,也使我对于数据结构这门课程有了新的认识,意识到它的重要性。课程设计是一个必须经历的过程,是我们理解书本知识、熟悉所学专业的一次很好实践。 在这次设计过程中,体现出自己单独设计程序的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。8.参考文献1.王红梅、王涛、胡明编著。数据结构。清华大学出版社出版,2011.62.王红梅编著。算法设计与分析。 清华大学出版社,20063.严蔚敏 吴伟民 ,数据结构(C语言版)清华大学出版社 2011.74.徐孝凯 数据结构使用教程 清华大学出版社 1999.12

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

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