图的深度优先遍历实现农夫过河
数据结构课程设计报告
农夫过河
学号:xxxxxxxxxx
姓名:xxx
专业:xxxxxx
班级:xxxxxxxxx
指导教师:xx
完成日期: 2018年6月
一、问题描述:
要求设计实现农夫过河问题(农夫带着一只狼,一只羊,一棵白菜,一次只能带一个东西)如何安全过河。
船上一次只能带一个东西,只有农夫会划船。当农夫不在时,狼如果和羊在一起,狼会把羊吃掉,羊不能和白菜在一起,羊会把白菜吃掉。但是狼不吃白菜。试求通过计算,得到能够使农夫,狼,羊,白菜一起安全过河的方法。
问题的解决方案:
可以用栈与队列、深度优先搜索算法及广度优先搜索算法相应的原理去解决问题。
- 实现四个过河对象(农夫、白菜、羊和狼)的状态,可以用一个四位二进制数来表示,0表示未过河,1表示已经过河了。
- 过河的对象必须与农夫在河的同一侧,可以设计函数来判断。
- 防止状态往复,即农夫将一个东西带过去又带回来的情况发生,需将所有可能的状态进行标定。
- 可用深度优先搜索算法及广度优先搜索算法去解题。
- 在基本要求达到后,可进行创新设计,如系统用户功能控制,改进算法的实现,实现友好的人机交互等等。
二、系统设计
1.功能实现概括:
在实现农夫过河中,我采用了无向图的结构来存储结点信息,用邻接矩阵存储结点的关系,用一个四位二进制数来表示过河状态,0表示河北岸,1表示从河南岸,初始状态农夫、狼、羊、白菜都在河北岸,用0000表示。完全过河后用1111表示。
图的遍历过程采用了深度优先搜素算法,将遍历的过程存入一个数组来记录过河过程,经过系统分析,农夫过河有两种解答方式,由于深度优先算法是遍历所有结点,造成数组部分被覆盖,在第二次遍历时改动了一些算法结构,使得第二种过河方式得以保存实现。
2.程序功能模块:
该系统分为三大模块
第一块:将农夫、狼、羊、白菜作为图的结点元素构建图的结点结构体,构造邻接矩阵,构造图时先判断结点的安全状态,创建只有安全结点,再判断各个结点之间的联系,将有关系的边存入邻接矩阵,构造图的结构。
第二块:利用深度优先搜索算法进行图的遍历,遍历到一个结点时,判断寻找与其有关系的下一个结点,将下一个结点的下标存入设定的ray数组,数组存放的既是过河过程。第二次遍历时,为避免深度优先搜素算法使得存入部分下标被覆盖,在可能被覆盖的结点进行算法改动,将另一种过程存入预定的ray2数组,从而实现两种过河过程。
第三块:分别循环访问ray和ray2数组, 判断数组元素对应的下标结点,打印出对应的过河过程和河两岸的对象状态,最后输出总的过河过程。
3.系统流程图
(1)图的结构:
因为从初始状态0000到1111一共有16种情况,判断其安全的情况共有十种,再判断各个结点的连接关系,运用邻接矩阵构建图的结构
(2)流程图:
略
4.系统的功能调试
本程序不需要用户输入,只需要用户按回车键即可观察下一步的操作即可。通过一定的界面友好的展示给用户正确的过程。
这是第一种过河方式
这是第二种过河方式
两种过河方式在第三步,第四步,第五步有所不同
详细代码如下:
#include <iostream>
#include <windows.h>
#include <stdio.h>
using namespace std;#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXSIZE 16
#define INFINTITY 65535int visited[MAXSIZE];
int ray[MAXSIZE];
int ray2[MAXSIZE];
static int sum =0;
typedef int EdgeType;/*状态顶点*/
typedef struct
{int farmer; //农夫 int wolf; //狼 int sheep; //羊 int cabbage; //白菜
}status;/*邻接矩阵结点*/
typedef struct
{int stanum; //顶点个数status vexs[MAXSIZE]; //储存顶点数组EdgeType arc[MAXSIZE][MAXSIZE]; //邻接矩阵权值
}MGraph;/*判断该状态是否安全*/
int isSafe(int farmer,int wolf,int sheep,int cabbage)
{//狼羊同岸 或 羊菜同岸if(((farmer!=wolf)&&(wolf==sheep))||((farmer!=sheep)&&(sheep==cabbage)))return FALSE;elsereturn TRUE;
}/*判断两个点是否有联系*/
int Truemove(MGraph G,int i,int j)
{int change = 0;if(G.vexs[i].farmer==G.vexs[j].farmer) //判断农夫是否移动return FALSE;else if(G.vexs[i].wolf!=G.vexs[j].wolf) //狼 change++;if(G.vexs[i].sheep!=G.vexs[j].sheep) //羊 change++;if(G.vexs[i].cabbage!=G.vexs[j].cabbage) //白菜 change++;if(change>1)return FALSE;elsereturn TRUE;
}/*创建只有安全结点的图*/
void CreateUDG(MGraph &G)
{G.stanum=0;//将判断安全的状态存入数组 10种 for(int i=0;i<=1;i++){for(int j=0;j<=1;j++){for(int k=0;k<=1;k++){for(int l=0;l<=1;l++){if(isSafe(i,j,k,l)){G.vexs[G.stanum].farmer=i;G.vexs[G.stanum].wolf=j;G.vexs[G.stanum].sheep=k;G.vexs[G.stanum].cabbage=l;G.stanum++;}}}}}//将有关系的边存入邻接矩阵 构建图的结构 for(int i = 0;i < G.stanum;i++){for(int j = 0;j< G.stanum;j++){if(Truemove(G,i,j)){G.arc[i][j] = TRUE;}else{G.arc[i][j] = INFINTITY;}}}
}/*邻接矩阵的深度优先递归算法*/
void DFS(MGraph G,int i,int a)
{if(a==1){visited[i] = TRUE;//cout<<i<<" ";//cout<<G.vexs[i].farmer<<G.vexs[i].wolf<<G.vexs[i].sheep<<G.vexs[i].cabbage<<endl;if(i==9)return;for(int j=0;j<G.stanum;j++)if(G.arc[i][j] != INFINTITY && !visited[j]){ray[i] = j; //cout<<j<<" "; DFS(G,j,a);} }else if(a==2){visited[i] = TRUE;//cout<<i<<" ";//cout<<G.vexs[i].farmer<<G.vexs[i].wolf<<G.vexs[i].sheep<<G.vexs[i].cabbage<<endl;if(i==9)return;for(int j=0;j<G.stanum;j++)if(G.arc[i][j] != INFINTITY && !visited[j]){if(j==1||j==6){continue;}ray2[i] = j;//cout<<j<<" "; DFS(G,j,a);} }}/*邻接矩阵的深度优先遍历算法*/
void TraverseDFS(MGraph G,int a)
{if(a==1){for(int i = 0;i<G.stanum;i++){visited[i] = FALSE;ray[i] = -1;}for(int i=0;i<G.stanum;i++)if(!visited[i]) //对未访问过的顶点调用DFS 若是连通图的话,只会执行一次DFS(G,i,a); }else if(a==2){for(int i = 0;i<G.stanum;i++){visited[i] = FALSE;ray2[i] = -1;}for(int i=0;i<G.stanum;i++)if(!visited[i]) //对未访问过的顶点调用DFS 若是连通图的话,只会执行一次DFS(G,i,a); }}/*查找下标*/
int find(MGraph G,int farmer,int wolf,int sheep,int cabbage)
{for (int i = 0; i < G.stanum; i++){if (G.vexs[i].farmer == farmer && G.vexs[i].wolf == wolf && G.vexs[i].sheep == sheep && G.vexs[i].cabbage == cabbage ){return i; //返回当前位置}}return -1;
}/*展示面板*/
void showTable1() //船在上
{cout<<"========================================================================================================================"<<endl;cout<<" << 船 # * - - "<<endl;cout<<" / \\ * * - "<<endl;cout<<" \\ / "<<endl;cout<<" << * - - "<<endl;cout<<" * * "<<endl;cout<<" * - - "<<endl;cout<<" << * * "<<endl;cout<<" "<<endl;cout<<" * * - "<<endl;cout<<" << * - - "<<endl;cout<<"========================================================================================================================"<<endl;
}
void showTable2() //船在下
{cout<<"========================================================================================================================"<<endl;cout<<" << * - - "<<endl;cout<<" * * - "<<endl;cout<<" "<<endl;cout<<" <<- - "<<endl;cout<<" * * "<<endl;cout<<" * - - "<<endl;cout<<" << # * * "<<endl;cout<<" / \\ "<<endl;cout<<" \\ / * * - "<<endl;cout<<" << 船 * * - - "<<endl;cout<<"========================================================================================================================"<<endl;
}
void showPeole1(MGraph G,int i)//北方的状态
{cout<<" 北方"<<" ";if(G.vexs[i].farmer==0)cout<<"\t农夫";if(G.vexs[i].wolf==0)cout<<"\t狼";if(G.vexs[i].sheep==0)cout<<"\t羊";if(G.vexs[i].cabbage==0)cout<<"\t白菜";cout<<endl;
}
void showPeole2(MGraph G,int i)//南方的状态
{cout<<" 南方"<<" ";if(G.vexs[i].farmer==1)cout<<"\t农夫";if(G.vexs[i].wolf==1)cout<<"\t狼";if(G.vexs[i].sheep==1)cout<<"\t羊";if(G.vexs[i].cabbage==1)cout<<"\t白菜";cout<<endl;
}/*加入叙述语句*/
void saySomething(MGraph G,int i,int a)
{if(a==1){int wolf = 0, sheep = 0, cabbage = 0;if(sum!=0){cout<<"\n\n\t第"<<sum<<"步:\t";if(G.vexs[ray[i]].wolf != G.vexs[i].wolf){if(G.vexs[ray[i]].farmer == 1)cout<<"农 夫 带 狼 去 了 南 边 "<<endl;elsecout<<"农 夫 带 狼 去 了 北 边 "<<endl;}else if(G.vexs[ray[i]].sheep != G.vexs[i].sheep){if(G.vexs[ray[i]].farmer == 1)cout<<"农 夫 带 羊 去 了 南 边 "<<endl;elsecout<<"农 夫 带 羊 去 了 北 边 "<<endl; }else if(G.vexs[ray[i]].cabbage != G.vexs[i].cabbage){if(G.vexs[ray[i]].farmer == 1)cout<<"农 夫 带 白 菜 去 了 南 边 "<<endl;elsecout<<"农 夫 带 白 菜 去 了 北 边 "<<endl;}else{if(G.vexs[ray[i]].farmer == 1)cout<<"农 夫 独 自 去 了 南 边 "<<endl;elsecout<<"农 夫 独 自 去 了 北 边 "<<endl;}}sum++; }else if(a==2){int wolf = 0, sheep = 0, cabbage = 0;if(sum!=0){cout<<"\n\n\t第"<<sum<<"步:\t";if(G.vexs[ray2[i]].wolf != G.vexs[i].wolf){if(G.vexs[ray2[i]].farmer == 1)cout<<"农 夫 带 狼 去 了 南 边 "<<endl;elsecout<<"农 夫 带 狼 去 了 北 边 "<<endl;}else if(G.vexs[ray2[i]].sheep != G.vexs[i].sheep){if(G.vexs[ray2[i]].farmer == 1)cout<<"农 夫 带 羊 去 了 南 边 "<<endl;elsecout<<"农 夫 带 羊 去 了 北 边 "<<endl; }else if(G.vexs[ray2[i]].cabbage != G.vexs[i].cabbage){if(G.vexs[ray2[i]].farmer == 1)cout<<"农 夫 带 白 菜 去 了 南 边 "<<endl;elsecout<<"农 夫 带 白 菜 去 了 北 边 "<<endl;}else{if(G.vexs[ray2[i]].farmer == 1)cout<<"农 夫 独 自 去 了 南 边 "<<endl;elsecout<<"农 夫 独 自 去 了 北 边 "<<endl;}}sum++; }}/*打印全部操作*/
void sayall(MGraph G,int i,int end,int a)
{if(a==1){sum = 1;cout<<"\n\n\n第一种总路程为:"<<endl;while(i!=end){cout<<endl;saySomething(G,i,a);i = ray[i];}getchar();system("cls");}else if(a==2){sum = 1;cout<<"\n\n\n第二种总路程为:"<<endl;while(i!=end){cout<<endl;saySomething(G,i,a);i = ray2[i];}getchar();system("cls"); }}
/*展示总面板*/
void showAll(MGraph G,int start,int end,int a)
{if(a==1){cout<<" 农夫过河《一》"<<endl<<endl;int low = start;while(start!=end){showPeole1(G,start); //北 if(G.vexs[start].farmer==0)showTable1();elseshowTable2();showPeole2(G,start); //南 saySomething(G,low,a);low = start;start=ray[start];getchar();system("cls");}showPeole1(G,start);if(G.vexs[start].farmer==0)showTable1();elseshowTable2();showPeole2(G,low);saySomething(G,low,a);start=find(G,0,0,0,0);//重置下标getchar();system("cls");}else if(a==2){cout<<" 农夫过河《二》"<<endl<<endl; sum=0;int low = start;while(start!=end){showPeole1(G,start); //北 if(G.vexs[start].farmer==0)showTable1();elseshowTable2();showPeole2(G,start); //南 saySomething(G,low,a);low = start;//cout<<"start="<<start<<endl;//测试遍历过程下标 start=ray2[start];getchar();system("cls");}showPeole1(G,start);if(G.vexs[start].farmer==0)showTable1();elseshowTable2();showPeole2(G,start);saySomething(G,low,a);start=find(G,0,0,0,0);//重置下标getchar();} }int main()
{MGraph G;CreateUDG(G);int start = find(G,0,0,0,0);int end = find(G,1,1,1,1);TraverseDFS(G,1); //第一种遍历答案 TraverseDFS(G,2); //第二种遍历答案 showAll(G,start,end,1);//第一种过河方式 sayall(G,start,end,1);//输出第一种过河过程 showAll(G,start,end,2);//第二种过河方式 sayall(G,start,end,2);//输出第二种过河过程 }
如有错误,欢迎指出。
图的深度优先遍历实现农夫过河相关推荐
- 实验报告C语言实现图的深度遍历,图的深度优先遍历的C语言实现.pdf
图的深度优先遍历的C语言实现.pdf 维普资讯 九 江 职 业 技 术 学 院 学 报 JournalofJiujiangVocational&TechnicalCollege 2004.2 ...
- 数据结构 图的深度优先遍历 C
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...
- java语言实现图的深度优先遍历
java语言实现图的深度优先遍历: 图的存储采用的是邻接矩阵存储的方式,对下面的无向图进行遍历 代码如下: public class Deep {int count=0;public static v ...
- 广度优先搜索生成树怎么画_图的深度优先遍历与广度优先遍历以及最小生成树...
图的深度优先遍历 题目:写出附从每个顶点出发的一次深度优先搜索遍历序列.在纸上画出遍历过程和序列,提交截图. 错误回答 从A点开始遍历:0124-01324-0134-0324-034 从B点开始遍历 ...
- C++实现图的深度优先遍历和广度优先遍历
图的深度和广度优先遍历 图的深度优先遍历 1.算法思想 2.邻接矩阵构造图 3.邻接表构造图 图的广度优先遍历 1.算法思想 2.邻接矩阵构造图 图的深度优先遍历 1.算法思想 (1)从图中的某个初始 ...
- 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构与算法学习笔记:图...
图: 图结构区别于线性结构和树型结构,区别可见下图 逻辑上的图(graph)结构由顶点(vertex)和边(edge)组成. 一个图结构G包含顶点集合V和边集合E,任何两个顶点之间可以有一个边表示两者 ...
- 邻接矩阵存储图的深度优先遍历
练习6.1 邻接矩阵存储图的深度优先遍历 (20 分) 试实现邻接矩阵存储图的深度优先遍历. 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visi ...
- 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构|图的邻接表与深度、广度优先搜索
线性存储元素时,元素的关系也同时确定了.而非线性数据结构就不同了,需要同时考虑存储数据元素和数据元素的关系. 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位 ...
- 树与图的深度优先遍历
树与图的深度优先遍历*: 树其实也是图的一种 图: 分为有向图和无向图 图的储存: 第一种:邻接矩阵,就是一个二维数组,缺点:当点和边特别多的时候,存不下,一般用的比较少,而且非常浪费空间 第二种:邻 ...
最新文章
- 关于System.InvalidOperationException异常
- 代码中的各种时间格式
- adg类似于mysql半同步机制_MySQL基准测试异步复制和半同步复制延迟对比
- 如何有效的压缩虚拟磁盘
- AngularStrap -- Popovers
- 华睿相机sdk 开发_索尼发布相机远程操作SDK(软件开发工具包)
- 放苹果(信息学奥赛一本通-T1192)
- 在eclipse中使用Github进行单元测试
- Mycat实战之配置EP分片
- 按键精灵修改html内容,按键精灵将表格录入网页.doc
- Tmall商城系统后台管理订单模块分析
- 习题2_2、韩信点兵
- python最早诞生于什么国_类型学最早诞生于哪个学科?()
- python量化实战 顾比倒数线_龙腾四海:顾比倒数线+顾比均线
- 计算机辅助牙种植,牙种植模型的计算机辅助设计和制作的应用研究
- Python+OpenCV实现图像处理OCR手写数字识别原理
- java中的三目运算
- 密码学_SM4国密算法
- php 取消warning,php怎么关闭warning提示
- windows 11变回原来的右键菜单