农夫过河问题

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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;in;i++)

visited[i]=FALSE; //标志向量初始

for(i=0;in;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;jn;j++) //依次搜索vi的邻接点

if(G->edges[i][j]==1&&!visited[j])

相关文档
最新文档