农夫过河问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计题目:农夫过河
一.问题描述
一个农夫带着一只狼、一只羊和一箩白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。过河有以下规则:
(1)农夫一次最多能带一样东西(或者是狼、或者是羊、或者是白菜)过河;
(2)当农夫不在场是狼会吃羊;
(3)当农夫不在场是羊会吃掉白菜。
现在要求为农夫想一个方案,能将3样东西顺利地带过河。从出事状态开始,农夫将羊带过河,然后农夫将羊待会来也是符合规则的,然后农夫将羊带过河仍然是符合规则的,但是如此这般往返,搜索过程便进入了死循环,因此,在这里,采用改进的搜索算法进行搜索。
二.基本要求
(1)为农夫过河问题抽象数据类型,体会数据模型在问题求解中的重要性;
(2)要求利用数据结构的方法以及C++的编程思想来完成问题的综合设
计;
(3)在问题的设计中,使用深度优先遍历搜索方式,避免死循环状态;
(4)设计一个算法求解农夫过河问题,并输出过河方案;
(5)分析算法的时间复杂度。
三.概要设计
(1)数据结构的设计
typedef struct // 图的顶点
{
int farmer; // 农夫
int wolf; // 狼
int sheep; // 羊
int veget; // 白菜
}Vertex;
设计Vertex结构体的目的是为了存储农夫、狼、羊、白菜的信息,因为在遍历图的时候,他们的位置信息会发生变化,例如1111说明他们都在河的北岸,而0000说明他们都在河的南岸。
t ypedef struct
{
int vertexNum; // 图的当前顶点数
Vertex vertex[VertexNum]; // 顶点向量(代表顶点)
bool Edge[VertexNum][VertexNum]; // 邻接矩阵. 用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关
}AdjGraph; // 定义图的邻接矩阵存储结构
存储图的方法是用邻接矩阵,所以设计一个简单的AdjGraph结构体是为了储图的顶点数与边数,农夫过河问题我采用的是图的深度优先遍历思想。
(2)算法的设计
深度优先遍历基本设计思想:设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的1/12边(x,y)。若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边。上述过程直至从x出发的所有边都已检测过为止。此时,若x不是源点,则回溯到在x之前被访问过的顶点;否则图中所有和源点有路径相通的顶点(即从源点可达的所有顶点)都已被访问过,若图G是连通图,则遍历过程结束,否则继续选择一个尚未被访问的顶点作为新源点,进行新的搜索过程。
程序中的深度优先遍历算法如下:
void dfsPath(AdjGraph *graph, int start, int end) // 深度优先搜索从u到v的简单路径
//DFS--Depth First Search
{
int i = 0;
visited[start] = true; //标记已访问过的顶点
if (start == end)
{
return ;
}
for (i = 0; i < graph->vertexNum; i++)
{
if (graph->Edge[start][i] && !visited[i])
{
retPath[start] = i;
dfsPath(graph, i, end);
}
}
}
(3)抽象数据类型设计
int locate(AdjGraph *graph, int farmer, int wolf, int sheep, int veget) // 查找顶点(F,W,S,V)在顶点向量中的位置
bool isSafe(int farmer, int wolf, int sheep, int veget) // 判断目前的(F,W,S,V)是否安全
bool isConnect(AdjGraph *graph, int i, int j) // 判断状态i与状态j之间是否可转换
void printPath(AdjGraph *graph, int start, int end) // 输出从u到v的简单路径,即顶点序列中不重复出现的路径
void dfsPath(AdjGraph *graph, int start, int end) // 深度优先搜索从u到v的简单路径 //DFS--Depth First Search
四.详细设计
1.问题遵循的原则
(1)图:顶点和连线的集合,G=(V,E),其中V是图中顶点的有穷非空集合,E是两个顶点的关系的集合,即图中连线的集合。若E中顶点对
(2)网:带权值的图称为网
(3)邻接矩阵:表示顶点之间连接关系的矩阵。
2.算法描述
(1)深度优先遍历的递归算法:
typedef enum{FALSE,TRUE}Boolean;//FALSE为0,TRUE为
Boolean visited[MaxVertexNum]; //访问标志向量是全局量
void DFSTraverse(ALGraph *G) //深度优先遍历以邻接表表示的图G,而以邻接矩阵表示G时,算法完全与此相同 int i;
{
for(i=0;i
visited[i]=FALSE; //标志向量初始
for(i=0;i
if(!visited[i]) //vi未访问过
DFS(G,i); //以vi为源点开始DFS搜索
}//DFSTraverse
(2)邻接矩阵表示的深度优先遍历算法:
void DFSM(MGraph *G,int i) //以vi为出发点对邻接矩阵表示的图G进行DFS搜索,设邻接矩阵是0,l矩阵 int j;
{
printf("visit vertex:%c",G->vexs[i]);//访问顶点vi
visited[i]=TRUE;
for(j=0;j
if(G->edges[i][j]==1&&!visited[j])