农夫过河数据结构Word文件下载.docx

上传人:b****6 文档编号:21569718 上传时间:2023-01-31 格式:DOCX 页数:9 大小:30.95KB
下载 相关 举报
农夫过河数据结构Word文件下载.docx_第1页
第1页 / 共9页
农夫过河数据结构Word文件下载.docx_第2页
第2页 / 共9页
农夫过河数据结构Word文件下载.docx_第3页
第3页 / 共9页
农夫过河数据结构Word文件下载.docx_第4页
第4页 / 共9页
农夫过河数据结构Word文件下载.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

农夫过河数据结构Word文件下载.docx

《农夫过河数据结构Word文件下载.docx》由会员分享,可在线阅读,更多相关《农夫过河数据结构Word文件下载.docx(9页珍藏版)》请在冰豆网上搜索。

农夫过河数据结构Word文件下载.docx

计算机与通信工程学院

专业:

计算机科学与技术

班级:

学号:

指导教师:

2012年6月21日

2

一,设计题目

问题描述:

一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。

否则狼会吃羊,羊会吃白菜。

所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不能吃白菜。

二,运行环境(软、硬件环境)

VC6.0Windows7系统

三,算法设计的思想

对于这个问题,我们需要先自动生成图的邻接矩阵来存储,主要方法是先生成各种安全状态结点,存放在顶点向量中;

再根据判断两个结点间状态是否可以转换来形成顶点之间的所有边,并把它们保存在邻接矩阵中。

在建立了图的邻接矩阵存储结构后,利用递归深度优先搜索求出从顶点(0,0,0,0)到顶点(1,1,1,1)的一条简单路径,这样做只能搜到一种合理方法,因为深度优先搜索遍历一个图的时候每一个结点只能被访问一次。

四,算法的流程图

要写算法的流程图,必须要先很了解自己的函数结构,我先在纸上手动的把整个过程在纸上画一遍,了解它的大体流程,然后把各个函数给分开,下面是我自己根据我的代码中画的各个函数画的流程图,希望老师满意。

主函数的流程图:

开始

初始化图结束

调用DFSpath输出路径

3

初始化图函数的流程图:

开始返回主函数

初始化邻接矩阵读取4个整型变量

判断它们判断状态

是否连接是否安全

初始化图的顶点读入两个顶点

DFSpath函数的流程图:

入栈

判断是否退栈被访问过

调用DFSpath返回主函数

4

五,算法设计分析

我的第一感觉,它可能是一个含有三个结点的图的问题,但这样做,我们没法来表示这个过程。

在这个问题的解决过程中,农夫需要多次架船往返于两岸之间,每次可以带一样东西或者自己单独过河,每一次过河都会使农夫、狼、羊和菜所处的位置发生变化。

如果我们用一个四元组(Farmer,Wolf,Sheep,Veget)表示当前农夫、狼、羊和菜所处的位置,其中每个元素可以是0或1,0表示在左岸,1表示在右岸。

这样,对这四个元素的不同取值可以构成16种不同的状

,0,0,0),最终要达到的目标为(1,1,1,1)。

状态,初始时的状态则为(0

态之间的转换可以有下面四种情况:

(1)农夫不带任何东西过河,可表示为:

(Farmer,Wolf,Sheep,Veget)(!

Farmer,Wolf,Sheep,Veget)我们需要把农夫的状态取反。

(2)当农夫带狼过河时,即当Farmer==Wolf时:

Farmer,!

Wolf,Sheep,Veget)我们要把农夫和狼的状态全部取反。

(3)当农夫带羊过河,即当Farmer==Sheep时:

Farmer,Wolf,!

Sheep,Veget)我们要把农夫和羊的状态进行取反。

Veget时:

(4)当农夫带菜过河时,即当Farmer==

Farmer,Wolf,Sheep,!

Veget)我们要把农夫和白菜的状态取反。

然后在这16种状态中,有些状态是不安全的,是不允许出现的,如(0,1,1,0)表示农夫和菜在南岸,而狼和羊在北岸,这样狼会吃掉羊。

我们需要从16种状态中删去这些不安全状态,将剩余的安全状态之间根据上面的转换关系连接起来,就得到如下图所示的两图。

并且我们在这采用邻接矩阵的方法来实现这个问题。

下面将会给出解题过程的一些细节。

图1为筛选后剩余的安全结点及其下标号的表,图2是农夫、狼、羊和菜安全转移到对岸的过程及其它们的状态图。

5

000010001200103010040101510106101171101811109111110

图1筛选后剩余的安全结点及其下标号

(0,0,0,0)(1,1,1,1)

(1,0,1,0)(0,1,0,1)(1,0,1,1)(0,0,0,1)

(1,1,1,0)(0,1,0,0)(0,0,1,0)(1,1,0,1)

图2农夫、狼、羊和菜问题的状态图

这样,原始问题就转换为在这个图中寻找一条从顶点(0,0,0,0)到顶点(1,1,1,1)的路径的问题,这就要选用深度优先搜索的方法。

六,运行结果分析

6

结果分析:

这四个数字依次代表农夫,狼,羊,白菜,(0,0,0,0)表示四种生物都在南岸,也就是初始状态,(1,0,1,0)代表农夫带着羊去了北岸,(0,0,1,0)代表农夫空手从北岸回到南岸,(1,0,1,1)代表农夫带着白菜去了北岸,(0,0,0,1)代表农夫带着羊又回到了南岸,(1,1,0,1)代表农夫带着狼去了北岸,(0,1,0,1)代表农夫空手回到了南岸,(1,1,1,1)农夫带着羊又来到了北岸。

到此为止,农夫把所有东西都带到了北岸。

七,收获及体会

最开始拿到这道题,我们都能用自己的语言来描述怎么做才能达到目的,但细细想来,我们怎样用计算机语言来实现这个过程呢,我最开始想到的是用关节点和连通图来做,但是这道题的过程却没法来实现,最后考虑到用这种四元组形式的结点来表示图,0和1代表每种生物不同的状态,它或者在北岸,或者在南岸,总共有16个结点,如果这样保持16个结点,并在下面的函数中每次都判断这个结点的状态是不是安全的,这使其很麻烦,所以在开始的时候直接筛选出安全状态的结点,不再考虑不安全的,把图的结点数直接降到10个,这样思路会更清晰,这是做这道题时的一些问题和解决方法。

还有一点就是如果用深度优先搜索的话,只能输出问题的一种方法,如果采用队列方法的话,应该可以输出全部方法,由于时间原因,我选择的是深度优先搜索,希望老师不要介意。

另外就是做这种实际性的题目,要求我们把书本上学的内容能合理的运用,这其实是比较难的,通过自己写这个代码,自己也更深刻的理解解决问题的几个大步骤,以前做题都是只要能够完成题目的要求即可,有时就是代码的累积,现在做数据结构,他强调的就是结构,针对一个题目,我们不再简单地只是要完成它,更重要的是选择合适的数据结构来实现,这才是最重要的,我这个题用的是图的结构,并用深度优先搜索来搜索出一条从初始状态到最后状态的路径,不管题目的简单与麻烦,我都是自己认真的尽力去做,就像和做数据结构的试验作业一样,要的就是自己动手,尽力去做到最好,这份报告是我花了很长时间才整理好的,包括画流程图,算法分析过程等,我把代码的每一步都写出了它的注释,希望老师满意,同时也感谢老师对我们的辅导,谢谢老师~

八,源代码

#include<

stdio.h>

7

#defineVEX_NUM10//声明一个最大值为VEX_NUM

#defineFALSE0//0代表为假

#defineTRUE1//1代表为真

typedefstruct

{

intFarmer,Wolf,Sheep,Veget;

}VexType;

//这个是图中每个顶点类型,包括四个数,0代表在南岸,1代表北岸typedefstruct

intvexnum,e;

//这个是图的顶点个数

VexTypevexs[VEX_NUM];

//它是顶点向量,分别表示各个顶点的内容

intadj[VEX_NUM][VEX_NUM];

//这个是邻接矩阵,我用的是邻接矩阵的方法}AdjGraph;

//这个是表示该图的结构体

intvisited[VEX_NUM];

//这个是来表示是否访问过该顶点,0代表没有访问过,//1代表已经访问过

intpath[VEX_NUM];

//这个数组是用来存储它的路径的,用来输出intsafe(intF,intW,intS,intV)//这个函数来判断这个结点状态是否安全{

if(F!

=S&

&

(W==S||S==V))//这个状态表示,农夫和羊不在同一边,没有农夫//保护羊,防止狼吃羊,

return0;

//也没有农夫去管制羊,防止羊吃掉白菜

else

return1;

//否则就是安全的。

这时返回1

}

intconnected(AdjGraph&

G,inti,intj)//这个函数用来判断图的第i个和//第j个顶点是否可以经过一次过河来相互转换

intk;

8

k=0;

//从整体来看,前三个if语句是计算除了人之外,其余有几种东西状//态发生了改变,这个计数要是小于1才有可能这两个顶点可以转换,因为人一//次只能带一种东西

if(G.vexs[i].Wolf!

=G.vexs[j].Wolf)

k++;

//当狼的状态发生改变,k++

if(G.vexs[i].Sheep!

=G.vexs[j].Sheep)

//当羊的状态发生改变,k++

if(G.vexs[i].Veget!

=G.vexs[j].Veget)

//当白菜的状态发生改变,k++

if(G.vexs[i].Farmer!

=G.vexs[j].Farmer&

k<

=1)//要想这两个顶点能发//生转换,人的状态必须发生改变,并且其余状态改变的物品小于等于1

//说明可以经过一次过河转换

//否则就是不可以发生转换

intlocate(AdjGraph&

G,intF,intW,intS,intV)//这个函数是用来求四种//东西的某种状态在图中是第几个顶点

inti;

for(i=0;

i<

G.vexnum;

i++)//判断给定的这个状态和图中的某个顶点状态是//否完全一致

if(G.vexs[i].Farmer==F&

G.vexs[i].Wolf==W&

G.vexs[i].Sheep==S&

G.

vexs[i].Veget==V)

returni;

//如果一致就把这个顶点的下标返回

return-1;

//其余的返回-1,表示不存在

voidCreate(AdjGraph&

G)//这个是用来创造图,包括处于安全状态结点的筛

9

//选和邻接矩阵的初始化。

inti,j,F,W,S,V;

i=0;

for(F=0;

F<

=1;

F++)//一种东西有南北岸之分,总共分为十六种状态,

for(W=0;

W<

W++)//但只有部分是安全的,这做的就是选出安全状态

for(S=0;

S<

S++)//安全的条件就是不能让其形成生物链

for(V=0;

V<

V++)

if(safe(F,W,S,V)==1)//判断该种状态是否安全,会不会出//现谁吃谁的情况

G.vexs[i].Farmer=F;

//如果这种状态安全,就把这种状//态记录下来

G.vexs[i].Wolf=W;

G.vexs[i].Sheep=S;

G.vexs[i].Veget=V;

i++;

//进行下一个状态判断

G.vexnum=i;

//把最后的安全状态的顶点数记录下来

i++)//接下来是对邻接矩阵的初始化

for(j=0;

j<

j++)

if(connected(G,i,j)==1)//connected函数是用来//判断这两个顶点是否可以经过一次过河可以相互达到

G.adj[i][j]=G.adj[i][j]=1;

//如果经过一次//过河可以相互转换,把邻接矩阵的该位置赋值为1

G.adj[i][j]=G.adj[j][i]=0;

//否则就把邻接//矩阵该点位置赋值为0

return;

10

voidprintpath(AdjGraph&

G,intu,intv)//这个是用来输出该图从第u个顶//点到第v个顶点上的路径

intk=u;

while(k!

=v)//依次循环向后,直到第v个结点,跳出循环

printf("

(%d,%d,%d,%d)\n"

G.vexs[k].Farmer,G.vexs[k].Wolf,G.vexs[k].

Sheep,G.vexs[k].Veget);

//输出路径上各个顶点的内容

k=path[k];

//依次向后移动

G.vexs[k].Farmer,G.vexs[k].Wolf,G.vexs[k

].Sheep,G.vexs[k].Veget);

//输出最后一个顶点的内容

voidDFSpath(AdjGraph&

G,intu,intv)//这个函数利用递归形式图的深度遍//历来找到从第u个顶点到第v个顶点的路径

intj;

visited[u]=1;

//把第u个顶点的visited赋值为1,说明已经访问过了

j++)//从邻接矩阵中找到第u个顶点可到的顶点

if(G.adj[u][j]==1&

visited[j]==0&

visited[v]==0)

{//表示可以从第u顶点到第j个顶点,并且他没有被访问过

path[u]=j;

//这是找到了路径上其中的一步,我们需要用path数组//记录下它下一步走到了那个顶点的下标

DFSpath(G,j,v);

//用递归的方法再去找他的下一步,一步一步朝下//找,直到访问到visited[v]为1

11

voidmain()

inti,j;

AdjGraphgraph;

//定义一个图

Create(graph);

//创造该图,初始化该图

graph.vexnum;

i++)

visited[i]=0;

//把图的各个顶点都先初始化为没有访问过

i=locate(graph,0,0,0,0);

//求出(0,0,0,0)这个顶点状态的下标

j=locate(graph,1,1,1,1);

//求出(1,1,1,1)这个顶点状态的下标

DFSpath(graph,i,j);

//求从下标为i到下标为j的路径,用path数组保存

if(visited[j]==1)//最后一个顶点已经被访问到,说明已经找到了从第i//个顶点到第j个顶点路径

0代表南岸,1代表北岸\n四个整数依次代表\n(农夫狼羊白菜)\n"

);

//进行一些必要的说明

printpath(graph,i,j);

//用输出函数输出它的路径

12

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

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

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