实验:农夫狼羊和菜问题
农夫过河

else
{
graph->Edge[i][j] = graph->Edge[j][i] = false;
}
}
}
return;
}
// 判断在河的那一边
char* judgement(int state)
{
return ( (0 == state) ? "左岸" : "右岸" );
// 查找顶点(F,W,S,V)在顶点向量中的位置
int locate(AdjGraph *graph, int farmer, int wolf, int sheep, int veget)
{
// 从0开始查找
for (int i = 0; i < graph->vertexNum; i++)
{
graph->vertex[i].farmer = farmer;
graph->vertex[i].wolf = wolf;
graph->vertex[i].sheep = sheep;
}
void enQueue_seq( PSeqQueue paqu, DataType x ) {
if ( (paqu->r + 1) % MAXNUM == paqu->f )
printf( "Full queue.\n" );
else {
paqu->q[paqu->r] = x;
{
return i; //返回当前位置
}
}
return -1; //没有找到此顶点
实习六-农夫过河问题

农夫过河问题一、需求分析1.问题描述:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。
他要把这些东西全部运到北岸。
他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。
如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。
2.基本要求:(1)利用图的存储结构(2)图的搜索算法(3)求出农夫将所有的东西运过河的所有方案二、设计1. 设计思想(1)存储结构以邻接矩阵存储合理状态,用一个一维数组保存所有的方案;(2)主要算法基本思想人,狼,羊和白菜共有2的四次方16种状态(河岸的状态可由人的状态确定),去掉不允许出现的6种状态,10个状态对应矩阵的10个结点值,然后根据状态的连续改变初始化矩阵,接着就用递归的深度优先法搜索所有的路径,即求出过河的方案。
main2. 设计表示(1)函数调用关系图main→Judge→Initiate→DFS→Push→StackPop→Top→GetTop→printfpath→Ch(2)函数接口规格说明int Judge(int a,int b) //将16种状态通过a,b输入,去掉不允许的6种int GetTop(Path *path,int *m) //出栈int Push(Path *path,int m) //入栈int Top(Path *path ,int *m) //读出栈顶值void Initiate(AdjMGraph *G,int n)//邻接矩阵顶点数为n的邻接矩阵G的建立int DFS(AdjMGraph *G,Path *path,int x,int t) 图G中搜索的起始点为X,从t点开始搜索与x关联的顶点,搜索过的点入栈path。
int printfpath(Path *path) //复制出出栈path中所有值,用FA【】保存void Printf(AdjMGraph *G)//辅助:邻接矩阵输出,用于观察搜索的过程。
用流程图描述算法

输入、输出框: 作用:指出要输入和输出的内容。 例如:
输入a
特点:一个入口 和 一个出口
处理框:
作用:指出要处理的内容。 例如:
a=a+1
a=a+1
???
特点:一个入口 和 一个出口
判别框:
作用:用于表示分支情况,框内书写判断条件。 例如:
Y N
a≤b
特点:一个入口 和 两个出口
流程线:
作用:用于表示程序的流向。 例如:
Y N
a≤b
连接框:
作用:用于连接因写不下而断开的流程线。 例如:
1 1
特点:一个入口 或 一个出口
练一练
用流程图描述用高斯公式求自然数 之和的算法。 sum = 1 + 2 + 3 + … + (n-1) + n
自然语言
1.输入n的值 1+n 2.计算 sum = ×n 2 3.输出sum的值
N
输出sum
End
用流程图描述算法 T = n! = 1×2×3×…×n
自然语言 1. 2. 3. 4. 5. 6. 输入n; sum=1; i=1; 计算sum=sum*i; 计算i=i+1; 如果i≤n执行4, 否则执行7 7. 输出sum的值 并结束算法。
流程图
Start
输入n
sum=1,i=1 sum=sum*i i=i+1 Y i≤n
算法和算法描述的方法农夫带狼、山羊、蔬菜过河的问题
一个农夫带着一条狼、一头山羊和一
篮蔬菜过河,但只有一条小船。每次只能
让农夫带一样东西过河,而且农夫在场的 情况下三样东西将相安无事。一旦农夫不 在,狼会吃羊,羊会吃蔬菜。问农夫如何 能安全地带这三样东西过河?
数据结构实验-农夫过河问题

农夫过河问题一、实验目的掌握广度优先搜索策略,并用队列求解农夫过河问题二、实验内容问题描述:一农夫带着一只狼,一只羊和一颗白菜,身处河的南岸,他要把这些东西全部运到北岸,遗憾的是他只有一只小船,小船只能容下他和一件物品。
这里只能是农夫来撑船,同时因为狼吃羊、羊吃白菜、所以农夫不能留下羊和狼或羊和白菜在河的一边,而自己离开;好在狼属肉食动物,不吃白菜。
农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(1)设计物品位置的表示方法和安全判断算法;(2)设计队列的存储结构并实现队列的基本操作(建立空队列、判空、入队、出队、取对头元素),也可以使用STL中的队列进行代码的编写;(3)采用广度优先策略设计可行的过河算法;(4)输出要求:按照顺序输出一种可行的过河方案;提示:可以使用STL中的队列进行代码编写。
程序运行结果:二进制表示:1111011011100010101100011001,0000三、农夫过河算法流程⏹Step1:初始状态0000入队⏹Step2:当队列不空且没有到达结束状态1111时,循环以下操作:⏹队头状态出队⏹按照农夫一个人走、农夫分别带上三个物品走,循环以下操作:⏹农夫和物品如果在同一岸,则计算新的状态⏹如果新状态是安全的并且是没有处理过的,则更新path[ ],并将新状态入队⏹当状态为1111时,逆向输出path[ ]数组附录一:STL中队列的使用注:队列,可直接用标准模板库(STL)中的队列。
需要#include<queue>STL中的queue,里面的一些成员函数如下(具体可以查找msdn,搜索queue class):front:Returns a reference to the first element at the front of the queue.pop:Removes an element from the front of the queuepush:Adds an element to the back of the queueempty:Tests if the queue is empty三、实验代码FarmerRiver.H#ifndef FARMERRIVER_H#define FARMERRIVER_Hint FarmerOnRight(int status); //农夫,在北岸返回1,否则返回0int WorfOnRight(int status); //狼int CabbageOnRight(int status); //白菜int GoatOnRight(int status); //羊int IsSafe(int status); //判断状态是否安全,安全返回1,否则返回0void FarmerRiver();#endifSeqQueue.h#ifndef SEQQUEUE_H#define SEQQUEUE_Htypedef int DataType;struct Queue{int Max;int f;int r;DataType *elem;};typedef struct Queue *SeqQueue;SeqQueue SetNullQueue_seq(int m);int IsNullQueue_seq(SeqQueue squeue);void EnQueue_seq(SeqQueue squeue, DataType x);void DeQueue_seq(SeqQueue);DataType FrontQueue_seq(SeqQueue);#endifFarmerRiver.c#include <stdio.h>#include <stdlib.h>#include "SeqQueue.h"#include "FarmerRiver.h"int FarmerOnRight(int status) //判断当前状态下农夫是否在北岸{return (0!=(status & 0x08));}int WorfOnRight(int status){return (0!=(status & 0x04));}int CabbageOnRight(int status){return (0!=(status & 0x02));}int GoatOnRight(int status){return (0!=(status & 0x01));}int IsSafe(int status) //判断当前状态是否安全{if ((GoatOnRight(status)==CabbageOnRight(status)) &&(GoatOnRight(status)!=FarmerOnRight(status)))return (0); //羊吃白菜if ((GoatOnRight(status)==WorfOnRight(status)) && (GoatOnRight(status)!=FarmerOnRight(status))) return 0; //狼吃羊return 1; //其他状态是安全的}void FarmerRiver(){int i, movers, nowstatus, newstatus;int status[16]; //用于记录已考虑的状态路径SeqQueue moveTo;moveTo = SetNullQueue_seq(20); //创建空列队EnQueue_seq(moveTo, 0x00); //初始状态时所有物品在北岸,初始状态入队for (i=0; i<16; i++) //数组status初始化为-1{status[i] = -1;}status[0] = 0;//队列非空且没有到达结束状态while (!IsNullQueue_seq(moveTo) && (status[15]==-1)){nowstatus = FrontQueue_seq(moveTo); //取队头DeQueue_seq(moveTo);for (movers=1; movers<=8; movers<<=1)//考虑各种物品在同一侧if ((0!=(nowstatus & 0x08)) == (0!=(nowstatus & movers)))//农夫与移动的物品在同一侧{newstatus = nowstatus ^ (0x08 | movers); //计算新状态//如果新状态是安全的且之前没有出现过if (IsSafe(newstatus)&&(status[newstatus] == -1)){status[newstatus] = nowstatus; //记录新状态EnQueue_seq(moveTo, newstatus); //新状态入队}}}//输出经过的状态路径if (status[15]!=-1){printf("The reverse path is: \n");for (nowstatus=15; nowstatus>=0; nowstatus=status[nowstatus]){printf("The nowstatus is: %d\n", nowstatus);if (nowstatus == 0)return;}}elseprintf("No solution.\n");}Sequeue.c#include <stdio.h>#include <stdlib.h>#include "SeqQueue.h"SeqQueue SetNullQueue_seq(int m){SeqQueue squeue;squeue = (SeqQueue)malloc(sizeof(struct Queue));if (squeue==NULL){printf("Alloc failure\n");return NULL;}squeue->elem = (int *)malloc(sizeof(DataType) * m);if (squeue->elem!=NULL){squeue->Max = m;squeue->f = 0;squeue->r = 0;return squeue;}else free(squeue);}int IsNullQueue_seq(SeqQueue squeue){return (squeue->f==squeue->r);}void EnQueue_seq(SeqQueue squeue, DataType x) //入队{if ((squeue->r+1) % squeue->Max==squeue->f) //是否满printf("It is FULL Queue!");else{squeue->elem[squeue->r] = x;squeue->r = (squeue->r+1) % (squeue->Max);}}void DeQueue_seq(SeqQueue squeue) //出队{if (IsNullQueue_seq(squeue))printf("It is empty queue!\n");elsesqueue->f = (squeue->f+1) % (squeue->Max); }DataType FrontQueue_seq(SeqQueue squeue) //求队列元素{if (squeue->f==squeue->r)printf("It is empty queue!\n");elsereturn (squeue->elem[squeue->f]);}main.c#include <stdio.h>#include <stdlib.h>#include "FarmerRiver.h"int main(void){FarmerRiver();return 0;}实验结果:四、实验总结。
狼羊白菜实验报告

== a[iStep][1])则出现错误,应返回操作。
开始
a[0][0]=0,a[0][1]=0 ,a[0][2]=0,a[0][3]= 0
递归
结束
同时定义一维数组 b[M]来存储每一步中人是如何过河的。设计程序中实现递归 操作部分的核心程序为: for(i=-1;i<=2;i++) {b[iStep] = i; memcpy(a[iStep+1],a[iStep],16); a[iStep+1][3]=1-a[iStep+1][3];
else {printf("<-----people "); printf("%s\n",name[b[i]+1]); } }
} printf("\n\n\n\n"); return; } for(i=0;i< iStep;i++) {if (memcmp(a[i],a[iStep],20)==0) {return; } } if (a[iStep][1] != a[iStep][3] && (a[iStep][2] == a[iStep][1] || a[iStep][0] == a[iStep][1])) { return; } for (i = -1; i <= 2; i++) { b[iStep] = i; memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1])); a[iStep + 1][3] = 1 - a[iStep + 1][3]; if (i == -1) {
过河
农
农夫过河问题(C++编写)

cout<<" **
------------------------
**\n";
cout<<" **
|
农夫过河问题
|
**\n";
cout<<" **
------------------------
**\n";
cout<<"
****************************************************************************\n";
1、问题描述
从前,一个农夫带着一只狼,一只羊和一棵白菜要河(注意该狼被农夫训服了,但还会 吃羊)。他要将所有东西安全的带到河的对岸,不幸的是河边只有一条船,只能装下农夫和 他的一样东西,并且农夫必须每次都随船过,因为只有他能撑船。在无人看管的情况下,狼 要吃羊,羊要吃白菜,因此,农夫不能在河的某边岸上单独留下狼和羊,也不能单独留下羊 和白菜。那么农夫如何才能使三样东西平安过河呢?
3)、如果上两个条件都不满,则可执行运输的动作,但每次都应考虑,该运 输情况以前是否执行过(即两岸以及船上的东西以时四者各自的状态,并递归的进行下一次运载。
5、系统测试
6、经验总结
解决实际问题时,应先分析实际问题,找出实际问题的所有约束条件, 然后对问题进行数学模型的抽象化,抓主要因素,省去一些不需要的因素,将其 抽象为数学问题,然后再从整体上设计算法,搭建程序的框架,最后一步步完善 细节,这样做,会使本来毫无头绪的问题变得清晰起来。
if (a[ferryTimes][i] == a[ferryTimes][3]) {
参考答案
第4章搜索策略部分参考答案有一农夫带一条狼,一只羊和一框青菜与从河的左岸乘船倒右岸,但受到下列条件的限制:(1) 船太小,农夫每次只能带一样东西过河;(2)如果没有农夫看管,则狼要吃羊,羊要吃菜。
请设计一个过河方案,使得农夫、浪、羊都能不受损失的过河,画出相应的状态空间图。
题示:(1) 用四元组(农夫,狼,羊,菜)表示状态,其中每个元素都为0或1,用0表示在左岸,用1表示在右岸。
(2) 把每次过河的一种安排作为一种操作,每次过河都必须有农夫,因为只有他可以划船。
解:第一步,定义问题的描述形式用四元组S=(f,w,s,v)表示问题状态,其中,f,w,s和v分别表示农夫,狼,羊和青菜是否在左岸,它们都可以取1或0,取1表示在左岸,取0表示在右岸。
第二步,用所定义的问题状态表示方式,把所有可能的问题状态表示出来,包括问题的初始状态和目标状态。
由于状态变量有4个,每个状态变量都有2种取值,因此有以下16种可能的状态:S0=(1,1,1,1),S1=(1,1,1,0),S2=(1,1,0,1),S3=(1,1,0,0)S4=(1,0,1,1),S5=(1,0,1,0),S6=(1,0,0,1),S7=(1,0,0,0)S8=(0,1,1,1),S9=(0,1,1,0),S10=(0,1,0,1),S11=(0,1,0,0)S12=(0,0,1,1),S13=(0,0,1,0),S14=(0,0,0,1),S15=(0,0,0,0)其中,状态S3,S6,S7,S8,S9,S12是不合法状态,S0和S15分别是初始状态和目标状态。
第三步,定义操作,即用于状态变换的算符组F由于每次过河船上都必须有农夫,且除农夫外船上只能载狼,羊和菜中的一种,故算符定义如下:L(i)表示农夫从左岸将第i样东西送到右岸(i=1表示狼,i=2表示羊,i=3表示菜,i=0表示船上除农夫外不载任何东西)。
由于农夫必须在船上,故对农夫的表示省略。
农夫过河——狼羊菜问题
农夫过河——狼⽺菜问题
话说⼀位农夫带着⼀只狼、⼀只⽺和⼀个卷⼼菜过河,⽆奈船⼩,农夫每次只能运送⼀样东西,考虑到狼吃⽺、⽺吃菜,因此运送的顺序⾄关重要。
在现实世界⾥解决这个问题并不困难,相信很多⼈都已经有了答案,但是如何⽤程序来解决这⼀问题,就需要动动脑筋了。
这⼜是⼀个与移动物品有关的问题,在前⾯汉诺塔的例⼦中,我们已经领略了解决这类问题的⽅法,⼤致分为三个步骤:
1. 将现实问题转化为数学问题,即,建⽴模型;
2. 将数学问题转化为程序问题,即,给出数据结构及算法;
3. 编写程序解决问题。
下⾯我们就沿着这样的思路来寻找问题的答案。
阅读原⽂。
题目 流程农夫过河
题目流程农夫过河一、基础过河规则类题目(1 - 5题)题目1:农夫带着狼、羊和一筐白菜要过河。
只有一条小船,农夫每次只能带一样东西过河。
如果农夫不在,狼会吃羊,羊会吃白菜。
请问农夫怎样才能安全地把狼、羊和白菜都运到河对岸?解析:1. 农夫先把羊运到河对岸,然后农夫独自返回。
- 原因是狼不吃白菜,这样河这边留下狼和白菜是安全的。
2. 农夫再把狼运到河对岸,然后农夫带着羊返回。
- 因为如果不把羊带回来,狼会吃羊。
3. 农夫把白菜运到河对岸,然后农夫独自返回。
- 此时河对岸有狼和白菜,是安全的。
4. 最后农夫把羊运到河对岸。
题目2:农夫要带狐狸、鸡和一袋米过河。
船很小,农夫每次只能带一个东西过河。
如果农夫不在,狐狸会吃鸡,鸡会吃米。
农夫应该怎样安排过河顺序?解析:1. 农夫先把鸡运到河对岸,然后农夫独自返回。
- 这样河这边留下狐狸和米是安全的。
2. 农夫再把狐狸运到河对岸,然后农夫带着鸡返回。
- 防止狐狸吃鸡。
3. 农夫把米运到河对岸,然后农夫独自返回。
- 此时河对岸有狐狸和米,安全。
4. 最后农夫把鸡运到河对岸。
题目3:农夫带着狗、兔子和一篮胡萝卜过河。
船只能载农夫和一样东西。
若农夫不在,狗会咬兔子,兔子会吃胡萝卜。
怎样安全过河?解析:1. 农夫先带兔子过河,然后独自返回。
- 因为狗不吃胡萝卜,这样河这边狗和胡萝卜是安全的。
2. 农夫再带狗过河,然后带兔子返回。
- 避免狗咬兔子。
3. 农夫带胡萝卜过河,然后独自返回。
- 此时河对岸狗和胡萝卜安全。
4. 最后农夫带兔子过河。
题目4:有个农夫要带蛇、鼠和一袋谷子过河,船每次只能载农夫和一样东西。
农夫不在时,蛇会吃鼠,鼠会吃谷子。
如何安全渡河?解析:1. 农夫先带鼠过河,然后独自返回。
- 此时河这边蛇和谷子是安全的。
2. 农夫再带蛇过河,然后带鼠返回。
- 防止蛇吃鼠。
3. 农夫带谷子过河,然后独自返回。
- 河对岸蛇和谷子安全。
4. 最后农夫带鼠过河。
题目5:农夫带着猫、鱼和一盆花过河。
数据结构实验-农夫过河问题
农夫过河问题一、实验目的掌握广度优先搜索策略,并用队列求解农夫过河问题二、实验内容问题描述:一农夫带着一只狼,一只羊和一颗白菜,身处河的南岸,他要把这些东西全部运到北岸,遗憾的是他只有一只小船,小船只能容下他和一件物品。
这里只能是农夫来撑船,同时因为狼吃羊、羊吃白菜、所以农夫不能留下羊和狼或羊和白菜在河的一边,而自己离开;好在狼属肉食动物,不吃白菜。
农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(1)设计物品位置的表示方法和安全判断算法;(2)设计队列的存储结构并实现队列的基本操作(建立空队列、判空、入队、出队、取对头元素),也可以使用STL中的队列进行代码的编写;(3)采用广度优先策略设计可行的过河算法;(4)输出要求:按照顺序输出一种可行的过河方案;提示:可以使用STL中的队列进行代码编写。
程序运行结果:二进制表示:1111011011100010101100011001,0000三、农夫过河算法流程⏹Step1:初始状态0000入队⏹Step2:当队列不空且没有到达结束状态1111时,循环以下操作:⏹队头状态出队⏹按照农夫一个人走、农夫分别带上三个物品走,循环以下操作:⏹农夫和物品如果在同一岸,则计算新的状态⏹如果新状态是安全的并且是没有处理过的,则更新path[ ],并将新状态入队⏹当状态为1111时,逆向输出path[ ]数组附录一:STL中队列的使用注:队列,可直接用标准模板库(STL)中的队列。
需要#include<queue>STL中的queue,里面的一些成员函数如下(具体可以查找msdn,搜索queue class):front:Returns a reference to the first element at the front of the queue.pop:Removes an element from the front of the queuepush:Adds an element to the back of the queueempty:Tests if the queue is empty三、实验代码FarmerRiver.H#ifndef FARMERRIVER_H#define FARMERRIVER_Hint FarmerOnRight(int status); //农夫,在北岸返回1,否则返回0int WorfOnRight(int status); //狼int CabbageOnRight(int status); //白菜int GoatOnRight(int status); //羊int IsSafe(int status); //判断状态是否安全,安全返回1,否则返回0void FarmerRiver();#endifSeqQueue.h#ifndef SEQQUEUE_H#define SEQQUEUE_Htypedef int DataType;struct Queue{int Max;int f;int r;DataType *elem;};typedef struct Queue *SeqQueue;SeqQueue SetNullQueue_seq(int m);int IsNullQueue_seq(SeqQueue squeue);void EnQueue_seq(SeqQueue squeue, DataType x);void DeQueue_seq(SeqQueue);DataType FrontQueue_seq(SeqQueue);#endifFarmerRiver.c#include <stdio.h>#include <stdlib.h>#include "SeqQueue.h"#include "FarmerRiver.h"int FarmerOnRight(int status) //判断当前状态下农夫是否在北岸{return (0!=(status & 0x08));}int WorfOnRight(int status){return (0!=(status & 0x04));}int CabbageOnRight(int status){return (0!=(status & 0x02));}int GoatOnRight(int status){return (0!=(status & 0x01));}int IsSafe(int status) //判断当前状态是否安全{if ((GoatOnRight(status)==CabbageOnRight(status)) && (GoatOnRight(status)!=FarmerOnRight(status)))return (0); //羊吃白菜if ((GoatOnRight(status)==WorfOnRight(status)) && (GoatOnRight(status)!=FarmerOnRight(status))) return 0; //狼吃羊return 1; //其他状态是安全的}void FarmerRiver(){int i, movers, nowstatus, newstatus;int status[16]; //用于记录已考虑的状态路径SeqQueue moveTo;moveTo = SetNullQueue_seq(20); //创建空列队EnQueue_seq(moveTo, 0x00); //初始状态时所有物品在北岸,初始状态入队for (i=0; i<16; i++) //数组status初始化为-1{status[i] = -1;}status[0] = 0;//队列非空且没有到达结束状态while (!IsNullQueue_seq(moveTo) && (status[15]==-1)){nowstatus = FrontQueue_seq(moveTo); //取队头DeQueue_seq(moveTo);for (movers=1; movers<=8; movers<<=1)//考虑各种物品在同一侧if ((0!=(nowstatus & 0x08)) == (0!=(nowstatus & movers)))//农夫与移动的物品在同一侧{newstatus = nowstatus ^ (0x08 | movers); //计算新状态//如果新状态是安全的且之前没有出现过if (IsSafe(newstatus)&&(status[newstatus] == -1)){status[newstatus] = nowstatus; //记录新状态EnQueue_seq(moveTo, newstatus); //新状态入队}}}//输出经过的状态路径if (status[15]!=-1){printf("The reverse path is: \n");for (nowstatus=15; nowstatus>=0; nowstatus=status[nowstatus]){printf("The nowstatus is: %d\n", nowstatus);if (nowstatus == 0)return;}}elseprintf("No solution.\n");}Sequeue.c#include <stdio.h>#include <stdlib.h>#include "SeqQueue.h"SeqQueue SetNullQueue_seq(int m){SeqQueue squeue;squeue = (SeqQueue)malloc(sizeof(struct Queue));if (squeue==NULL){printf("Alloc failure\n");return NULL;}squeue->elem = (int *)malloc(sizeof(DataType) * m);if (squeue->elem!=NULL){squeue->Max = m;squeue->f = 0;squeue->r = 0;return squeue;}else free(squeue);}int IsNullQueue_seq(SeqQueue squeue){return (squeue->f==squeue->r);}void EnQueue_seq(SeqQueue squeue, DataType x) //入队{if ((squeue->r+1) % squeue->Max==squeue->f) //是否满printf("It is FULL Queue!");else{squeue->elem[squeue->r] = x;squeue->r = (squeue->r+1) % (squeue->Max);}}void DeQueue_seq(SeqQueue squeue) //出队{if (IsNullQueue_seq(squeue))printf("It is empty queue!\n");elsesqueue->f = (squeue->f+1) % (squeue->Max); }DataType FrontQueue_seq(SeqQueue squeue) //求队列元素{if (squeue->f==squeue->r)printf("It is empty queue!\n");elsereturn (squeue->elem[squeue->f]);}main.c#include <stdio.h>#include <stdlib.h>#include "FarmerRiver.h"int main(void){FarmerRiver();return 0;}实验结果:四、实验总结。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验:农夫狼羊和菜问题————————————————————————————————作者:————————————————————————————————日期:实验6:农夫、狼、羊和菜问题一、实验目的:1. 会定义图的抽象数据类型;2. 熟悉图的基本结构,掌握程序中的用户头文件、实现文件和主文件之间的相互关系及各自的作用;3. 熟悉对图的一些基本操作和具体的函数定义;4.掌握在实际问题中运用所学知识解决实际问题的方法和步骤。
二、实验内容描述:有一农夫带着一条狼、一只羊和一筐菜,想从河的左岸乘船到右岸。
但由于船太小,农夫每次只能带一样东西过河,而且,如果没有农夫看管,则狼会吃羊,羊会吃菜。
问农夫怎样过河才能把每样东西安全地送过河。
三、实验要求:1. 将上述问题用图表示出来;2. 选择图的一种存储结构,编写一个自动生成该图的算法;3.在上述基础上编写求解该问题的算法程序,并用此程序上机运行、调试,4.屏幕显示结果,能结合程序进行分析。
四、问题分析:该问题从表面上看,并不是一个图的问题,但可以把它用图表示出来,从而转换为一个图的问题。
在这个问题的解决过程中,农夫需要多次架船往返于两岸之间,每次可以带一样东西或者自己单独过河,每一次过河都会使农夫、狼、羊和菜所处的位置发生变化。
如果用一个四元组(Farmer,Wolf,Sheep,Veget)表示当前农夫、狼、羊和菜所处的位置,其中每个元素可以是0或1,0表示在左岸,1表示在右岸。
这样,对这四个元素的不同取值可以构成16种不同的状态,初始时的状态则为(0,0,0,0),最终要达到的目标为(1,1,1,1)。
状态之间的转换可以有下面四种情况:(1)农夫不带任何东西过河,可表示为:(Farmer,Wolf,Sheep,Veget) (!Farmer,Wolf,Sheep,Veget)(2)当农夫和狼在相同位置时,表示农夫带狼过河,即当Farmer=Wolf时:(Farmer,Wolf,Sheep,Veget) (!Farmer,!Wolf,Sheep,Veget)(3)当农夫和羊在相同位置时,表示农夫带羊过河,即当Farmer=Sheep时:(Farmer,Wolf,Sheep,Veget) (!Farmer,Wolf,!Sheep,Veget)(4)当农夫和菜在相同位置时,表示农夫带菜过河,即当Farmer=Veget 时: (Farmer,Wolf,Sheep,Veget) (!Farmer,Wolf,Sheep,!Veget)在这16种状态中,有些状态是不安全的,是不允许出现的,如(1,1,0,0)表示农夫和狼在右岸,而羊和菜在左岸,这样羊会吃掉菜。
如果从16种状态中删去这些不安全状态,将剩余的安全状态之间根据上面的转换关系连接起来,就得到如下图所示的图。
图1 农夫、狼、羊和菜问题的状态图这样,原始问题就转换为在这个图中寻找一条从顶点(0,0,0,0)到顶点(1,1,1,1)的路径的问题。
五、存储结构:采用邻接矩阵和邻接表都可以完成求图中两顶点间的路径问题,这里,我们不妨采用邻接矩阵存储结构。
其中图的每个顶点结点包括四个域,类型定义为: typedef struct /*定义图的顶点类型*/ {int Farmer,Wolf,Sheep,Veget;}VexType;图的邻接矩阵存储结构定义为:#define VEX-NUM 10 /*最大顶点个数*/ typedef struct{(0,0,(1,0,1,(0,0,(1,1,(0,1,(1,1,(0,1,(1,1,(1,0,(0,0,int vexnum,e; /*图的当前顶点数和边数*/ VexType vex[VEX-NUM]; /*顶点向量*/int adj[VEX-NUM][VEX-NUM]; /*邻接矩阵*/}AdjGraph;六、算法思想:在这个问题中,首先需要自动生成图的邻接矩阵存储,具体方法是先生成各种安全状态结点,存放在顶点向量中;再根据状态之间的转换关系形成顶点之间的所有边,保存在邻接矩阵中。
在建立了图的邻接矩阵存储结构后,利用深度优先搜索思想求出从顶点(0,0,0,0)到顶点(1,1,1,1)的一条简单路径。
七、实验程序:#include<stdio.h>#define VEX_NUM 10typedef enum{FALSE,TRUE}Boolean;typedef struct{int Farmer,Wolf,Sheep,Veget;}VexType;typedef struct{int vexnum,e;VexType vexs[VEX_NUM];int adj[VEX_NUM][VEX_NUM];}AdjGraph;Boolean visited[VEX_NUM];int path[VEX_NUM];int locate(AdjGraph*G,int F,int W,int S,int V){int i;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)return(i);return(-1);}int is_safe(int F,int W,int S,int V){if(F!=S&&(W==S||S==V))return(0);elsereturn(1);}int is_connected(AdjGraph*G,int i,int j){int k;k=0;if(G->vexs[i].Wolf!=G->vexs[j].Wolf)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)return(1);elsereturn(0);}void CreateG(AdjGraph*G){int i,j,F,W,S,V;i=0;for(F=0;F<=1;F++)for(W=0;W<=1;W++)for(S=0;S<=1;S++)for(V=0;V<=1;V++)if(is_safe(F,W,S,V)){G->vexs[i].Farmer=F;G->vexs[i].Wolf=W;G->vexs[i].Sheep=S;G->vexs[i].Veget=V;i++;}G->vexnum=i;for(i=0;i<G->vexnum;i++)for(j=0;j<G->vexnum;j++)if(is_connected(G,i,j))G->adj[i][j]=G->adj[i][j]=1;elseG->adj[i][j]=G->adj[j][i]=0;return;}void print_path(AdjGraph*G,int u,int v) {int k;k=u;while(k!=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];}printf("(%d,%d,%d,%d)\n",G->vexs[k].Farmer,G->vexs[k].Wolf,G->vexs[k].Sheep,G->vexs[k].Veg et);}void DFS_path(AdjGraph*G,int u,int v){int j;visited[u]=TRUE;for(j=0;j<G->vexnum;j++)if(G->adj[u][j]&&!visited[j]&&!visited[v]){path[u]=j;DFS_path(G,j,v);}}void main(){int i,j;AdjGraph graph;CreateG(&graph);for(i=0;i<graph.vexnum;i++)visited[i]=FALSE;i=locate(&graph,0,0,0,0);j=locate(&graph,1,1,1,1);DFS_path(&graph,i,j);if(visited[j])print_path(&graph,i,j);if(visited[j])print_path(&graph,i,j);return;}八、实验测试结果:(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)九、程序功能分析、运行结果分析:。