农夫过河数据结构

合集下载

数据结构课程设计报告(农夫过河)

数据结构课程设计报告(农夫过河)

数据结构课程设计报告(农夫过河)第一篇:数据结构课程设计报告(农夫过河)目录引言...................................................2 问题描述..............................................3 基本要求 (3)2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性;........3 2.2设计一个算法求解农夫过河问题,并输出过河方案;......................3 3 概要设计 (3)3.1 数据结构的设计。

....................................................3 3.1.1农夫过河问题的模型化.............................................3 3.1.2 算法的设计 (4)4、运行与测试 (6)5、总结与心得..........................................7 附录...................................................7 参考文献. (13)引言所谓农夫过河问题是指农夫带一只狼、一只羊和一棵白菜在河南岸, 需要安全运到北岸。

一条小船只能容下他和一件物品, 只有农夫能撑船。

问农夫怎么能安全过河, 当然狼吃羊, 羊吃白菜, 农夫不能将这两种或三种物品单独放在河的一侧, 因为没有农夫的照看, 狼就要吃羊, 而羊可能要吃白菜? 这类问题的实质是系统的状态问题, 要寻求的是从初始状态经一系列的安全状态到达系统的终止状态的一条路径。

1 问题描述一个农夫带一只狼、一棵白菜和一只羊要从一条河的南岸过到北岸,农夫每次只能带一样东西过河,但是任意时刻如果农夫不在场时,狼要吃羊、羊要吃白菜,请为农夫设计过河方案。

基本要求2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性;2.2设计一个算法求解农夫过河问题,并输出过河方案;概要设计3.1 数据结构的设计。

农夫过河问题(数据结构课设)

农夫过河问题(数据结构课设)

#include "stdafx.h"#include <stdio.h>/*0代表在河的这边;1代表在河的对岸*/struct Condition {int farmer;int wolf;int sheep;int cabbage;};/*设置结构体*/struct Condition conditions [100];/*结构体条件数组*/char* action[100];/*字符串数组*/ void takeWolfOver(int i)/*把狼带过去*/ {action[i] = "带狼过去. (wolf)--->对岸";conditions[i+1].wolf=1;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=conditions[i].cabbage;} void takeWolfBack(int i)/*把狼带回来*/{action[i] = "带狼回来. 本岸<---(wolf)";conditions[i+1].wolf=0;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=conditions[i].cabbage;} void takeSheepOver(int i)/*把羊带过去*/{action[i] = "带羊过去. (sheep)--->对岸";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=1;conditions[i+1].cabbage=conditions[i].cabbage;} void takeSheepBack(int i)/*把羊带回来*/{action[i] = "带羊回来. 本岸<---(sheep)";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=0;conditions[i+1].cabbage=conditions[i].cabbage;} void takeCabbageOver(int i)/*把菜带过去*/{action[i] = "带菜过去. (cabbage)--->对岸";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=1;} void takeCabbageBack(int i)/*把菜带回来*/{action[i] = "带菜回来. 本岸<---(cabbage)";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=0;} void getOverBarely(int i)/*过河时的情况*/{action[i] = "空手过去. (barely)--->对岸";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=conditions[i].cabbage;/*全不动*/} void getBackBarely(int i)/*返回时的情况*/{action[i] = "空手回来. 本岸<---(barely)";conditions[i+1].wolf=conditions[i].wolf;conditions[i+1].sheep=conditions[i].sheep;conditions[i+1].cabbage=conditions[i].cabbage;} void showSolution(int i)/*显示解决方法*/{int c;printf("\n");printf ("%s\n", "解决办法:");for(c=0; c<i; c++){printf ("step%d: %s\n", c+1, action[c]);/*换行输出*/}printf ("%s\n", "Successful!");}void tryOneStep(int i)/*再试一遍*/{int c;int j;if(i>=100)/*检查循环是否出现问题*/{printf("%s\n", "渡河步骤达到100步,出错!");return;}if(conditions[i].farmer==1&&conditions[i].wolf==1&&conditions[i].sheep==1&&conditions[i].cabbage==1)/*检查是否都过河*/{showSolution(i);/*是的,都过河了.返回*/return;}if((conditions[i].farmer!=conditions[i].wolf &&conditions[i].wolf==conditions[i].sheep)||(conditions[i].farmer!=conditions[i].sheep && conditions[i].sheep==conditions[i].cabbage))/*检查是否丢失,出错*/{/*不,狼会吃掉羊,或者羊会吃掉菜的*/return;}/*检查条件是否满足*/for (c=0; c<i; c++){if(conditions[c].farmer==conditions[i].farmer&&conditions[c].wolf==conditions[i].wolf&&conditions[c].sheep==conditions[i].sheep&&conditions[c].cabbage==conditions[i].cabbage) {return;}}j=i+1;if(conditions[i].farmer==0)/*农夫在河这边*/{conditions[j].farmer=1;getOverBarely(i);tryOneStep(j);if(conditions[i].wolf==0)/*如果狼没带过去*/{takeWolfOver(i);tryOneStep(j);}if(conditions[i].sheep==0){takeSheepOver(i);tryOneStep(j);}if(conditions[i].cabbage==0){takeCabbageOver(i);tryOneStep(j);}}else{conditions[j].farmer=0;getBackBarely(i);tryOneStep(j);if(conditions[i].wolf==1){takeWolfBack(i);tryOneStep(j);}if(conditions[i].sheep==1){takeSheepBack(i);tryOneStep(j);}if(conditions[i].cabbage==1){takeCabbageBack(i);tryOneStep(j);}}} int main()/*主函数*/{printf("问题:农夫过河。

数据结构实验-农夫过河问题

数据结构实验-农夫过河问题

农夫过河问题一、实验目的掌握广度优先搜索策略,并用队列求解农夫过河问题二、实验内容问题描述:一农夫带着一只狼,一只羊和一颗白菜,身处河的南岸,他要把这些东西全部运到北岸,遗憾的是他只有一只小船,小船只能容下他和一件物品。

这里只能是农夫来撑船,同时因为狼吃羊、羊吃白菜、所以农夫不能留下羊和狼或羊和白菜在河的一边,而自己离开;好在狼属肉食动物,不吃白菜。

农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(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;}实验结果:四、实验总结。

数据结构农夫过河项目课报告

数据结构农夫过河项目课报告

数据结构农夫过河项目课报告数据结构-农夫过河项目课报告-计算机四班第七组项目名称:农夫过河算法与数据结构设计专业班级:计算机科学与技术四班学生姓名:王喆指导教师: 完成日期:2015年12月28日数据结构-农夫过河项目课报告-计算机四班第七组农夫过河算法与数据结构设计摘要农夫过河问题即一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他需要把这些东西全部运到河的北岸。

而他只有一条小船,且这只小船小到只能容下他和一件物品,另外只有农夫能撑船。

农夫不能留下狼和羊自己离开,也不能留下白菜和羊自己离开,更不能留下狼,羊和白菜而独自离开,因为没有农夫的照看,狼就要吃掉羊,而羊又要吃掉白菜。

好在狼是是肉动物,它不吃白菜,问农夫应该采取什么方案才能将所有的东西安全地从河的南岸运到北岸,这类农夫问题是一个传统的数据结构问题,农夫过河问题根据图求解的搜索过程可采用两种不同的策略:一种是图的深度优先遍历搜索,另外一种是广度优先遍历搜索。

如果采用深度优先遍历搜索,则需要采用递归的方式来编写程序,而这种程序的系统的开销比较大,如果采用广度优先搜索,则可以借助队列的方式,这种方式开销较小。

关键字:农夫过河,广度优先遍历搜索,队列,深度优先遍历搜索,递归。

2数据结构-农夫过河项目课报告-计算机四班第七组目录1.前言…………………………………………………………42.设计任务与技术要求………………………………………43.总体设计方案………………………………………………44.数据结构和算法的设计……………………………………55.程序测试与调试(一)……………………………………7 6.程序测试与调试(二)..........................................9 7.程序出现的问题及修改情况....................................14 8.心得与体会.........................................................14 参考文献 (15)3数据结构-农夫过河项目课报告-计算机四班第七组1.前言课程研究项目是《数据结构》课程学习的重要方式之一,也是《数据结构》课程学习的重要组成部分之一。

【数据结构与算法】狼、羊、菜和农夫过河:使用图的广度优先遍历实现

【数据结构与算法】狼、羊、菜和农夫过河:使用图的广度优先遍历实现

【数据结构与算法】狼、⽺、菜和农夫过河:使⽤图的⼴度优先遍历实现【数据结构与算法】狼、⽺、菜和农夫过河:使⽤图的⼴度优先遍历实现Java农夫需要把狼、⽺、菜和⾃⼰运到河对岸去,只有农夫能够划船,⽽且船⽐较⼩。

除农夫之外每次只能运⼀种东西。

还有⼀个棘⼿问题,就是如果没有农夫看着,⽺会偷吃菜,狼会吃⽺。

请考虑⼀种⽅法,让农夫能够安全地安排这些东西和他⾃⼰过河。

解题思路学了图论的⼴度优先遍历算法后,我们可以使⽤⼴度优先遍历的思想来完成这道题。

⾸先定义如何表达农夫、狼、⽺、菜在河的哪⼀边。

只有两种状态:1. 在河的⼀边(假设为东边)2. 在河的另⼀边(假设为西边)那么恰好可以⽤0和1来表达,任务定义如下(使⽤字符串来表达):// ⼈狼⽺菜// 源: 0 0 0 0//⽬标: 1 1 1 1String s = "0000";String t = "1111";那接下来程序的任务就是搜索出从s到t的过程了。

那么如何转换成图论问题?我们知道,0000 代表农夫、狼、⽺、菜都在河的东边,那么下⼀种状态可以有如下⼏种选择:1. 东:空狼⽺菜 | 西:⼈空空空(农夫⾃⼰过河)2. 东:空空⽺菜 | 西:⼈狼空空(农夫带狼过河)3. 东:空狼空菜 | 西:⼈空⽺空(农夫带⽺过河)4. 东:空狼⽺空 | 西:⼈空空菜(农夫带菜过河)我们根据这个可以绘制⼀个图,顶点0000 分别与顶点1000、顶点1100、顶点1010、顶点1001有边连接;其中,根据规则在没有农夫的情况下,狼和⽺不能在⼀起,⽺和菜不能在⼀起,所以排除掉以上的1,2,4选项。

那么下⼀个状态就是 0101然后根据这个原理,再往下查找有哪些是可以的:1. 东:⼈狼空菜 | 西:空空⽺空(农夫⾃⼰过河)2. 东:⼈狼⽺菜 | 西:空空空空(农夫带⽺过河)我们根据这个也可以绘制⼀个图,顶点0101 分别与顶点0000、顶点0010有边连接;然后再根据规则进⾏查找。

数据结构课程设计-农夫过河-实验报告.

数据结构课程设计-农夫过河-实验报告.

一、需求分析描述1、针对实现整个过程需要多步,不同步骤中各个事物所处位置不同的情况,可定义一个结构体来实现对四个对象狼、羊、白菜和农夫的表示。

对于起始岸和目的岸,可以用0或者1来表示,以实现在程序设计中的简便性。

2、题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,进行下一步试探。

这就需要使用循环或者递归算法,避免随机盲目运算且保证每种情况均试探到。

3、题目要求求出农夫带一只羊,一条狼和一颗白菜过河的办法,所以依次成功返回运算结果后,需要继续运算,直至求出结果,即给出农夫的过河方案。

4、输出界面要求具有每一步中农夫所带对象及每步之后各岸的物体,需要定义不同的数组来分别存储上述内容,并使界面所示方案清晰简洁。

二、系统架构设计1.设计中首先涉及的就是数据类型的定义,首先,定义一个结构体用来存放农夫、狼、羊、白菜的信息。

具体定义为:struct Condition{int farmer;int wolf;int sheep;int cabbage;};定义了一个结构体数组Condition conditions[100],定义状态数组用来记录他们过河的状态0:起始岸;1:目的岸;程序中定义的char action100数组用来存放各个物件以及人过河或返回的说明语句。

2.程序中定义的子函数有:2.1 将狼带到目的岸以及带回起始岸的函数takeWolfOver()和takeWolfBack ();takeWolfOver()函数中将conditions[i+1].wolf=1,白菜、羊的状态不变,同时要有action[i]=" take wolf over."将狼带到目的岸语句;takeWolfBack()函数中将conditions[i+1].wolf=0,白菜、羊的状态不变,同时要有action[i]=" take wolf back."将狼带回起始岸语句。

农夫过河问题的求解

农夫过河问题的求解
void ListTraverse(LinkType p, status(*visit)(LinkType q));
//从p(P!=NULL)指示的结点开始,依次对每个结点调用函数visit
其中部分操作的伪码算法如下:
BOOL InitList(OrderdeList &L)
{
if(MakeNode(head,ˊˊ)){ //头结点的虚设元素为空格符ˊˊ
{
//分配由p指向的数据元素为e、后继为“空”的结点,并返回TRUE,
//若分配失败,则返回FALSE
p=(Link Type)malloc(sixeof(Node Type));
if(!p)return FALSE;
p->data=e;p->next=NULL; return TRUE;
}
void freeNode(LinkType &p)
//销毁有序链表L
bool Listempty(OrderedList L);
//若L不存在或为“空表”,则返回TRUE,否则返回FALSE
int ListLengty(OrderedList L);
//返回链表的长度
Linktype GetelemPos(OrderedList L, int pos);
构造有序集算法createset读入n个元素逐个用locateelem判定不在当前集合中及确定插入位置后才用insertafetr插入到有序集中所以时间复杂度是on求并集算法union利用集合的有序性将两个集合的个元素不重复地依次利用append插入到当前并集的末尾故可在omn时间内完成
实验报告
题目:编制一个演示农夫过河问题的求解的程序
per=L.head; p=pre->next;

农夫过河问题

农夫过河问题
{
df=d[i].f-d[j].f;
dw=abs(d[i].w-d[j].w);
ds=abs(d[i].s-d[j].s);
dc=abs(d[i].c-d[j].c);
if(df!=0&&(dw+ds+dc)<=1)
{
edge[num].col=i;
edge[num++].row=j;
}
}
return num;
int right_edge(DataType *vertex,RowCol *edge,int n) //选出满足题意的边
void DepthFSearch(AdjLGraph G,int v,int visited[],DataType vert[],int *a)
//图的深度优先遍历
3.3抽象数据类型的设计
{
if(!visited[w])
DepthFSearch(G,w,visited,d1,s);
w=GetNextVex(G,v,w);
}
}
4.3函数的调用关系图
5.测试结果
农夫过河问题
1.问题描述
一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。
typedef struct
{
AdjLHeight a[100];//邻接表数组
int numOfVerts;//结点个数
int numOfEdges;//边个数

数据结构—农夫过河问题

数据结构—农夫过河问题

题目:一个农夫带着一匹狼、一只羊、一颗白菜要过河,只有一条船而且农夫每次最多只能带一个动物或物品过河,并且当农夫不在的时候狼会吃羊,羊会吃白菜,列出所有安全将所有动物和物品带过河的方案。

要求:广度优先搜索农夫过河解,并输出结果源代码:#include <stdio.h>#include <stdlib.h>typedef int DataType;struct SeqQueue{int MAXNUM;int f, r;DataType *q;};typedef struct SeqQueue *PSeqQueue; // 顺序队列类型的指针类型PSeqQueue createEmptyQueue_seq(int m)//创建一个空队列{PSeqQueue queue = (PSeqQueue)malloc(sizeof(struct SeqQueue)); if (queue != NULL){queue->q = (DataType*)malloc(sizeof(DataType) *m);if (queue->q){queue->MAXNUM = m;queue->f = 0;queue->r = 0;return (queue);}elsefree(queue);}printf("Out of space!!\n"); // 存储分配失败return NULL;}int isEmptyQueue_seq(PSeqQueue queue)//判断队列是否为空{return (queue->f == queue->r);}void enQueue_seq(PSeqQueue queue, DataType x)//入队{if ((queue->r + 1) % queue->MAXNUM == queue->f)printf("Full queue.\n");else{queue->q[queue->r] = x;queue->r = (queue->r + 1) % queue->MAXNUM;}}void deQueue_seq(PSeqQueue queue)// 删除队列头部元素{if (queue->f == queue->r)printf("Empty Queue.\n");elsequeue->f = (queue->f + 1) % queue->MAXNUM;}DataType frontQueue_seq(PSeqQueue queue)//取队头元素{if (queue->f == queue->r)printf("Empty Queue.\n");elsereturn (queue->q[queue->f]);}int farmer(int location)//判断农夫的位置 1000表示在北岸{return (0 != (location &0x08));}int wolf(int location)//判断狼的位置 0100表示在北岸{return (0 != (location &0x04));}int cabbage(int location)//判断白菜的位置 0010表示在北岸{return (0 != (location &0x02));}int goat(int location)//判断羊的位置 0001表示在北岸{return (0 != (location &0x01));}int safe(int location)//安全状态的判断{if ((goat(location) == cabbage(location)) && (goat(location) != farmer(location))) //羊与白菜不安全return 0;if ((goat(location) == wolf(location)) && (goat(location) != farmer(location)))//羊与狼不安全return 0;return 1; // 其他状态是安全的}void bin_print(int num)//将十进制数转换成二进制数输出{char tmp[4];int i;for (i = 0; i < 4; ++i){tmp[i] = num & 0x01;num >>= 1;}for (i = 3; i >= 0; --i)putchar((tmp[i] == 0)?'0':'1');return;}int main(){int i, movers, location, newlocation;int a=0;int r[16];int route[16]; //用于记录已考虑的状态路径PSeqQueue moveTo; //用于记录可以安全到达的中间状态moveTo = createEmptyQueue_seq(20); //创建空队列enQueue_seq(moveTo, 0x00); //初始状态进队列for (i = 0; i < 16; i++)route[i] = -1; //准备数组route初值route[0] = 0;while (!isEmptyQueue_seq(moveTo) && (route[15] == - 1)){location = frontQueue_seq(moveTo); //取队头状态为当前状态deQueue_seq(moveTo);for (movers = 1; movers <= 8; movers <<= 1)//考虑各种物品移动 if ((0 != (location & 0x08)) == (0 != (location & movers)))//判断农夫与移动的物品是否在同一侧{newlocation = location ^ (0x08 | movers);//计算新状态,代表把船上的(0x08|movers)从一个岸移到另一个岸;(0x08|movers)代表船上有农夫和movers代表的东西if (safe(newlocation) && (route[newlocation] == -1)) //新状态安全且未处理{route[newlocation] = location; //记录新状态的前驱 enQueue_seq(moveTo, newlocation); //新状态入队}}}// 打印出路径if (route[15] != -1)//到达最终状态{printf("The reverse path is : \n");for (location = 15; location >= 0; location = route[location]) {r[a]=location;a++;if (location == 0) break;}for(i=a-1;i>=0;i--){printf("%d ",r[i]);bin_print(r[i]);//用1表示北岸,0表示南岸,用四位二进制数的顺序依次表示农夫、狼、白菜、羊的位置if(r[i]==0) printf("开始\n");//0000else if(r[i]==1) printf(" 农夫独自返回南岸\n"); //0001else if(r[i]==2) printf(" 农夫带着羊返回南岸\n");//0010else if(r[i]==3) printf(" 白菜与羊共同在北岸,不安全\n"); //0011else if(r[i]==4) printf(" 只有狼在北岸,农夫独自返回南岸\n"); //0100else if(r[i]==5) printf(" 狼与羊共同在北岸,不安全\n");//0101else if(r[i]==6) printf(" 农夫独自返回南岸\n");//0110else if(r[i]==7) printf(" 狼、白菜和羊共同在北岸,不安全\n");// 0111else if(r[i]==8) printf(" 农夫独自去北岸\n");//1000else if(r[i]==9) printf(" 农夫把羊带到北岸\n");//1001else if(r[i]==10) printf(" 农夫把白菜带到北岸\n");//1010else if(r[i]==11) printf(" 农夫把白菜带到北岸\n");//1011else if(r[i]==12) printf(" 农夫把狼带到北岸\n");//1100else if(r[i]==13) printf(" 只有白菜在南岸\n");//1101else if(r[i]==14) printf(" 农夫把狼带到北岸\n");//1110else if(r[i]==15) printf(" 农夫把羊带到北岸\n");//1111 putchar('\n');}printf("\n");}elseprintf("No solution.\n");}。

宽搜农夫过河问题

宽搜农夫过河问题

农夫过河问题宽搜(bfs)算法详解农夫过河问题(农夫、狼、羊和白菜的问题),描述如下:一个农夫,带着一只狼、一只羊、和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。

农夫的面前有一条小船,船小到只能容下他和一件物件。

另外,只能农夫会撑船。

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

但狼属于食肉动物,不吃白菜。

问农夫采取什么方案才能将所有的东西运过河?解题思路农夫过河问题的求解方法是使用广度优先搜索(BFS),即在搜索过程中总是最先搜索下面一步的所有可能状态,然后再进行考虑更后面的各种情况。

要实现广度优先搜索,一般采用队列结构。

把下一步所有可能达到的状态都列举出来,放在这个队列中,然后顺序取出来分别对其进行处理,处理过程中再把下一步的状态放在队列里。

在采用编程解决农夫过河的问题时,首先需要考虑以下几个问题:•程序中为了方便描述农夫过河过程中几个角色的位置(位于南岸还是北岸),最好的方法是用4 个二进制数,分别顺序表示农夫、狼、白菜和羊的位置。

在本节程序中,用二进制0 表示某角色在河的南岸,用 1 表示某角色在河的北岸。

例如,整数5(其二进制为0101),表示农夫和白菜在河的南岸,而狼和羊在北岸。

•为了方便获取各个角色当前所在的位置,程序中设置了如下 4 个函数。

其中,函数返回值为1,反之则表示角色在河的北岸://表示农夫状态的函数,返回0 ,表示农夫在南岸,反之在北岸。

int farmer(int location){return(0!=(location & 0x08));}//表示狼的状态的函数,返回0 ,表示农夫在南岸,反之在北岸int wolf(int location){return(0!=(location & 0x04));}//表示白菜状态的函数,返回0 ,表示农夫在南岸,反之在北岸int cabbage(int location){return(0!=(location & 0x02));}//表示羊状态的函数,返回0 ,表示农夫在南岸,反之在北岸int goat(int location){return(0!=(location & 0x01));}其中,location 为当前4 种角色所处的状态,其值为0(0000)到15(1111)之间的数。

数据结构课程设计报告(农夫过河)

数据结构课程设计报告(农夫过河)

目录引言 (2)1 问题描述 (2)基本要求 (2)2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性; (2)2.2设计一个算法求解农夫过河问题,并输出过河方案; (2)3 概要设计 (2)3.1数据结构的设计。

(2)3.1.1农夫过河问题的模型化 (2)3.1.2 算法的设计 (3)4、运行与测试 (5)5、总结与心得 (6)附录 (6)参考文献 (12)引言所谓农夫过河问题是指农夫带一只狼、一只羊和一棵白菜在河南岸, 需要安全运到北岸。

一条小船只能容下他和一件物品, 只有农夫能撑船。

问农夫怎么能安全过河, 当然狼吃羊, 羊吃白菜, 农夫不能将这两种或三种物品单独放在河的一侧, 因为没有农夫的照看, 狼就要吃羊, 而羊可能要吃白菜? 这类问题的实质是系统的状态问题, 要寻求的是从初始状态经一系列的安全状态到达系统的终止状态的一条路径。

1 问题描述一个农夫带一只狼、一棵白菜和一只羊要从一条河的南岸过到北岸,农夫每次只能带一样东西过河,但是任意时刻如果农夫不在场时,狼要吃羊、羊要吃白菜,请为农夫设计过河方案。

基本要求2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性;2.2设计一个算法求解农夫过河问题,并输出过河方案;3 概要设计3.1 数据结构的设计。

3.1.1农夫过河问题的模型化分析这类问题会发现以下特征:有一组状态( 如农夫和羊在南, 狼和白菜在北) ; 从一个状态可合法地转到另外几个状态( 如农夫自己过河或农夫带着羊过河) ; 有些状态不安全( 如农夫在北, 其他东西在南) ; 有一个初始状态( 都在南) ; 结束状态集( 这里只有一个, 都在北) 。

问题表示: 需要表示问题中的状态, 农夫等位于南P北( 每个有两种可能) 。

可以采用位向量, 4 个二进制位的0P1 情况表示状态, 显而易见, 共24= 16种可能状态。

从高位到低位分别表示农夫、狼、白菜和羊。

农夫过河实验报告——数据结构

农夫过河实验报告——数据结构

数据结构实验报告——实验四农夫过河的求解本实验的目的是进一步理解顺序表和队列的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。

一、【问题描述】一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。

他要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。

请求出农夫将所有的东西运过河的方案。

二、【数据结构设计】求解这个问题的简单的方法是一步一步进行试探,每一步搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。

要模拟农夫过河问题,首先需要对问题中每个角色的位置进行描述。

一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。

用0表示农夫或者某东西在河的南岸,1表示在河的北岸。

例如整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。

现在问题变成:从初始状态二进制0000(全部在河的南岸) 出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标,并且在序列中的每一个状态都可以从前一状态到达。

为避免瞎费功夫,要求在序列中不出现重复的状态。

实现上述求解的搜索过程可以采用两种不同的策略:一种是广度优先(breadth_first) 搜索,另一种是深度优先(depth_first) 搜索。

本书只介绍在广度优先搜索方法中采用的数据结构设计。

广度优先就是在搜索过程中总是首先搜索下面一步的所有可能状态,再进一步考虑更后面的各种情况。

要实现广度优先搜索,可以使用队列。

把下一步所有可能的状态都列举出来,放在队列中,再顺序取出来分别进行处理,处理过程中把再下一步的状态放在队列里……。

由于队列的操作遵循先进先出的原则,在这个处理过程中,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。

数据结构 农夫过河问题

数据结构 农夫过河问题

#include<iostream>using namespace std;#define VertexNum 16 //最大顶点数typedef struct // 图的顶点{int farmer; // 农夫int wolf; // 狼int sheep; // 羊int veget; // 白菜}Vertex;typedef struct{int vertexNum; // 图的当前顶点数Vertex vertex[VertexNum]; // 顶点向量(代表顶点)bool Edge[VertexNum][VertexNum]; // 邻接矩阵. 用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关}AdjGraph; // 定义图的邻接矩阵存储结构bool visited[VertexNum] = {false}; // 对已访问的顶点进行标记(图的遍历)int retPath[VertexNum] = {-1}; // 保存DFS搜索到的路径,即与某顶点到下一顶点的路径// 查找顶点(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++){if ( graph->vertex[i].farmer == farmer && graph->vertex[i].wolf == wolf&& graph->vertex[i].sheep == sheep && graph->vertex[i].veget == veget ) {return i; //返回当前位置}}return -1; //没有找到此顶点}// 判断目前的(F,W,S,V)是否安全bool isSafe(int farmer, int wolf, int sheep, int veget){//当农夫与羊不在一起时,狼与羊或羊与白菜在一起是不安全的if ( farmer != sheep && (wolf == sheep || sheep == veget) ){return false;}else{return true; // 安全返回true}}// 判断状态i与状态j之间是否可转换bool isConnect(AdjGraph *graph, int i, int j){int k = 0;if (graph->vertex[i].wolf != graph->vertex[j].wolf){k++;}if (graph->vertex[i].sheep != graph->vertex[j].sheep){k++;}if (graph->vertex[i].veget != graph->vertex[j].veget){k++;}// 以上三个条件不同时满足两个且农夫状态改变时,返回真, 也即农夫每次只能带一件东西过桥if (graph->vertex[i].farmer != graph->vertex[j].farmer && k <= 1){return true;}else{return false;}}// 创建连接图void CreateG(AdjGraph *graph){int i = 0;int j = 0;// 生成所有安全的图的顶点for (int farmer = 0; farmer <= 1; farmer++){for (int wolf = 0; wolf <= 1; wolf++){for (int sheep = 0; sheep <= 1; sheep++){for (int veget = 0; veget <= 1; veget++){if (isSafe(farmer, wolf, sheep, veget)){graph->vertex[i].farmer = farmer;graph->vertex[i].wolf = wolf;graph->vertex[i].sheep = sheep;graph->vertex[i].veget = veget;i++;}}}}}// 邻接矩阵初始化即建立邻接矩阵graph->vertexNum = i;for (i = 0; i < graph->vertexNum; i++){for (j = 0; j < graph->vertexNum; j++){// 状态i与状态j之间可转化,初始化为1,否则为0if (isConnect(graph, i, j)){graph->Edge[i][j] = graph->Edge[j][i] = true;}else{graph->Edge[i][j] = graph->Edge[j][i] = false;}}}return;}// 判断在河的哪一边char* judgement(int state){return ( (0 == state) ? "南岸" : "北岸" );}// 输出从u到v的简单路径,即顶点序列中不重复出现的路径void printPath(AdjGraph *graph, int start, int end){int i = start;cout << "farmer" << ", wolf" << ", sheep" << ", veget" << endl;while (i != end){cout << "(" << judgement(graph->vertex[i].farmer) << ", " << judgement(graph->vertex[i].wolf)<< ", " << judgement(graph->vertex[i].sheep) << ", " << judgement(graph->vertex[i].veget) << ")";cout << endl;i = retPath[i];}cout << "(" << judgement(graph->vertex[i].farmer) << ", " << judgement(graph->vertex[i].wolf)<< ", " << judgement(graph->vertex[i].sheep) << ", " << judgement(graph->vertex[i].veget) << ")";cout << endl;}// 深度优先搜索从u到v的简单路径//DFS--Depth First Searchvoid dfsPath(AdjGraph *graph, int start, int end){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);}}}int main(){AdjGraph graph;CreateG(&graph);int start = locate(&graph, 0, 0, 0, 0);int end = locate(&graph, 1, 1, 1, 1);dfsPath(&graph, start, end);if (visited[end]){printPath(&graph, start, end);return 0;}return -1;}。

农夫过河报告(最终版)

农夫过河报告(最终版)

农夫过河算法实验报告――数据结构项目课研究课题组长:崔俊组员:李琦、郑鸿飞、王琅辉、张育博15.12.29摘要农夫过河问题是应用广度优先搜索和深度优先搜索的典型问题,但这里我们应用了简单的数组,通过层层筛选的手段也解决了同样的问题,其中用到了部分广度优先搜索的思想。

、八■、-前言农夫过河问题描述:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。

他要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。

请求出农夫将所有的东西运过河的方案。

正文1∙问题抽象和数据组织农夫过河问题应该应用图的广度优先遍历或者深度优先遍历,但这里我们仅使用简单的线性表一一数组,通过多重的条件限制,达成目的。

这里我们同样用O和1代表农夫、狼、羊、白菜在左岸还是在右岸,并规定O在左,1在右,我们的目的便是从OOOO通过一系列变换到1111。

2.农夫过河算法源代码#in elude VStdio.h>#define MAX 16typedef StrUCt FWSV{int farmer;int wolf;int sheep;int vegetable;}Item;//函数原型//操作:筛选符合条件的安全的数组成员//操作前:无//操作后:返回安全数组的指针void SCree n( void);//操作:判断下一个数应该取安全数组中那个数//操作前:传递一个结构体数组成员//操作后:返回另一个结构体数组指针Item * judge(Item Fwsv);Item safe[MAX];int k = 0;int main (Void){SCree n();Item * n ext;Item first,sec On d,e nd;first = safe[0];end = safe[k];Prin tf("first:0000\n"); n ext = judge(first);void SCree n( void){int f = 0,w = 0,s = 0,v = 0;for(f = 0;f < 2;f++){for(w = 0;W < 2;w++){for(s = 0;S < 2;s++){for(v = 0;V < 2;v++){if (!(f != S && (S == W Il S == V))){safe[k].farmer = f;safe[k].wolf = w;safe[k].sheep = s;safe[k].vegetable = v;k++;// 用于计数safe[]中的总数}}}}}}Item * judge(Item FWSV){Item * n ext;Item COmPare[4];n ext = compare;int x1 = 0;int SUm = 0;if (Fwsv.farmer == 0){for (int X = 0;X < k;x++){ZZ把出现过的置零操作if(safe[x].farmer == Fwsv.farmer && safe[x].wolf == Fwsv.wolf &&safe[x].sheep == Fwsv.sheep && safe[x].vegetable == Fwsv.vegetable ){safe[x].farmer = 0;safe[x].wolf = 0;safe[x].sheep = 0; safe[x].vegetable = 0;}ZZ筛选出农夫状态值与之前相反的1变0 0变1if(safe[x].farmer == 1 && (safe[x].farmer + safe[x].wolf +safe[x].sheep + safe[x].vegetable != 4 )){COmPare[x1] = safe[x];x1++;}}for (int x2 = 0;x2 < 4;x2++)//删除状态值与农夫不同但是改变了的SUm = Fwsvfarmer + Fwsv.wolf + Fwsv.sheep + Fwsv.vegetable;if ((FWSV.farmer != Fwsv.wolf && COmPare[x2].wolf != Fwsv.wolf)||(Fwsv.farmer != Fwsv.sheep && COmPare[x2].SheeP != Fwsv.sheep){Il (Fwsv.farmer != Fwsv.vegetable && COmPare[x2].VegetabIe != Fwsv.vegetable)Il (Fwsv.farmer != Fwsv.vegetable && COmPare[x2].VegetabIe != Fwsv.vegetable)){COmPare[x2].farmer = 0;COmPare[x2].wolf = 0;COmPare[x2].SheeP = 0;COmPare[x2].VegetabIe = 0;}sum+=2;//对和的限制if(compare[x2].farmer + COmPare[x2].wolf + COmPare[x2].SheeP +COmPare[x2].VegetabIe != SUm){COmPare[x2].farmer = 0;COmPare[x2].wolf = 0;COmPare[x2].SheeP = 0;COmPare[x2].VegetabIe = 0;}}Printf(" -------------------------------------- ∖n");for(i nt x3 = 0;x3 < 4;x3++){if (COmPare[x3].farmer + COmPare[x3].wolf + COmPare[x3].SheeP +COmPare[x3].VegetabIe != 0){Printf(" 上数与:%d%d%d%d 连∖n",ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].veget abl );}{if (Fwsv.farmer == 1) {for (int y = 0;y V k;y++) {if(safe[y].farmer == Fwsv.farmer && safe[y].wolf == Fwsv.wolf && safe[y].sheep== Fwsv.sheep && safe[y].vegetable == Fwsv.vegetable ){safe[y].farmer = 0; safe[y].wolf = 0;safe[y].sheep = 0; safe[y].vegetable = 0; }if(safe[y].farmer== 0 && (safe[y].farmer + safe[y].wolfsafe[y].sheep + safe[y].vegetable != 0 )){ComPare[x1] = safe[y]; x1++; } }for (int x2 = 0;x2 < 4;x2++) {SUm = Fwsv.farmer + Fwsv.wolf + Fwsv.sheep + Fwsv.vegetable; if ((FWSV.farmer != Fwsv.wolf && COmPare[x2].wolf != Fwsv.wolf)Fwsv.sheep)Fwsv.vegetable)Fwsv.vegetable)){COmPare[x2].farmer = 0; COmPare[x2].wolf = 0; COmPare[x2].SheeP = 0; COmPare[x2].VegetabIe = 0; } }Printf(" for(i nt x3 = 0;x3 < 4;x3++)∣∣(Fwsv.farmer != Fwsv.sheep && COmPare[x2].SheeP!= Il (Fwsv.farmer!= Fwsv.vegetable && COmPare[x2].VegetabIe != Il (Fwsv.farmer!= Fwsv.vegetable&& COmPare[x2].VegetabIe!=∖n");if (ComPare[x3].farmer + ComPare[x3].Wolf + ComPare[x3].SheeP + ComPare[x3].VegetabIe != 0){Printf(" 上数与:%d%d%d%d 连∖n",ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetable);}}}return n ext;}3. 算法功能说明和流程描述首先我们定义了一个结构体Itemtypedef StrUCt FWSV{int farmer;int wolf;int sheep;int vegetable;}Item;Item 中包含了农夫(farmer ),狼(wolf ),羊(SheeP),白菜(VegetabIe ),用来表示农夫、狼、羊、白菜的状态,并作出规定当为0的时候表示在左岸,当为1的时候表示在右岸,我们的目标便是从0000的状态到1111的状态。

农夫过河数据结构

农夫过河数据结构

农夫过河数据结构郑州轻工业学院课程设计任务书题目农夫过河专业、班级计算机科学与技术学号姓名主要内容:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。

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

要求给出农夫将所有的东西运过河的方案。

基本要求:编写求解该问题的算法程序,并用此程序上机运行、调试,屏幕显示结果,能结合程序进行分析。

主要参考资料:数据结构严蔚敏完成期限: 2012/6/21指导教师签名:课程负责人签名:年月日郑州轻工业学院本科数据结构课程设计总结报告设计题目:农夫过河学生姓名:系别:计算机与通信工程学院专业:计算机科学与技术班级:计算机科学与技术学号:指导教师:2012年 6 月 21 日2一,设计题目问题描述:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。

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

要求给出农夫将所有的东西运过河的方案。

二,运行环境(软、硬件环境)VC6.0 Windows7系统三,算法设计的思想对于这个问题,我们需要先自动生成图的邻接矩阵来存储,主要方法是先生成各种安全状态结点,存放在顶点向量中;再根据判断两个结点间状态是否可以转换来形成顶点之间的所有边,并把它们保存在邻接矩阵中。

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

过河问题,数据结构

过河问题,数据结构

数据结构课程设计报告1.问题描述(第27题)有一人要将自己的兔子、蔬菜和狐狸等三件物品运过河。

但过河所用的船每次只能装其中的两件,而这三件物品之间又存在一定的制约关系:兔子不能单独和狐狸以及不能和蔬菜在一起,因为狐狸要吃兔子,兔子也能吃蔬菜。

试构造出问题的模型,并编程实现这一问题的求解。

2、模型表示农夫要把三件物品运过河,但三个物品之间又有一定的制约关系。

因此河的两岸,可以用几个状态来表示。

那么为了能够把物品安全的运过河,河两岸的状态可以表示为:用1表示蔬菜,2表示兔子,3表示狐狸,0表示移走了河的此岸河的彼岸(1,2,3) (0,0,0)(1,0,3) (0,2,0)(0,0,3) (1,2,0)(0,2,3) (1,0,0)(0,2,0) (1,0,3)(0,0,0) (1,2,3)为了能够把河两岸的状态正确的表示出来,那么首要解决的问题就是如何确定移走和带回。

设计一个函数来确定带回那个权值(1,2,3,0),这样可以形成河两岸的几种状态。

(1,2,0)、(0,2,3)、(1,2,3)在农夫不在的情况下均是不稳定状态需要移走或者带回。

兔子对于蔬菜和狐狸两个量均有影响。

而我们可以观察到(1,0,3)在农夫不在的情况下是个稳定的状态,从而可以确定移走三个物品的路径了:兔子过去;没有东西回来.白菜过去;兔子回来.狼过去;没有东西回来.兔子过去;没有东西回来.3、算法的思想描述通过对河两岸状态的判断,确定移走哪个、带回哪个。

因此这就需要一个功能函数int begin(int first,int second,int third,int number)来实现这个功能。

在实现此函数的过程中,对剩余量进行判断,用switch()选择性的语句。

河的此岸还剩三个的时候,直间返回中间量,即兔子;河的此岸还剩两个的时候,分三种情况:(1)有兔子、狼时,返回狼。

(2)不移走时,相当于回到初始状态,因为兔子变量对其他两个均有影响。

农夫过河问题算法设计与实现

农夫过河问题算法设计与实现

农夫过河问题算法设计与实现咱来唠唠农夫过河这个有趣的问题。

一、问题描述农夫要带着一只狼、一只羊和一棵白菜过河。

但是呢,船很小,每次农夫只能带一样东西过河。

而且啊,如果农夫不在,狼会吃羊,羊会吃白菜,这可就麻烦大了。

二、算法设计思路1. 初始状态- 河这边有农夫、狼、羊和白菜,河对岸啥都没有。

2. 第一步很关键- 农夫肯定不能先带狼或者白菜,为啥呢?因为如果先带狼过去,把羊和白菜留在这边,羊就会吃白菜;要是先带白菜过去,狼就会吃羊。

所以农夫得先带羊过河。

- 然后农夫自己返回。

这时候河这边有狼和白菜,河对岸有羊。

3. 第二步- 农夫再带狼或者白菜过河。

假设农夫带狼过河吧。

- 但是农夫不能把羊单独留在对岸啊,所以农夫得把羊再带回来。

这时候河这边有羊和白菜,河对岸有狼。

4. 第三步- 农夫把羊放下,带白菜过河。

- 然后农夫自己返回。

这时候河这边有羊,河对岸有狼和白菜。

5. 最后一步- 农夫再带羊过河,这样就都安全地到对岸啦。

三、算法实现(用简单的文字描述过程)1. 开始:- 农夫在起始岸,物品(狼、羊、白菜)也在起始岸,对岸为空。

2. 第一次过河:- 农夫带羊过河,此时起始岸有狼和白菜,对岸有羊和农夫。

- 农夫独自返回起始岸,此时起始岸有农夫、狼、白菜,对岸有羊。

3. 第二次过河:- 农夫带狼过河,此时起始岸有白菜,对岸有狼、羊和农夫。

- 农夫带羊返回起始岸,此时起始岸有农夫、羊、白菜,对岸有狼。

4. 第三次过河:- 农夫带白菜过河,此时起始岸有羊,对岸有狼、白菜和农夫。

- 农夫独自返回起始岸,此时起始岸有农夫、羊,对岸有狼、白菜。

5. 第四次过河:- 农夫带羊过河,此时起始岸为空,对岸有农夫、狼、羊、白菜,大功告成!你看,这样一步一步的,就像走迷宫一样,按照规则走,就能让农夫带着他的东西安全过河啦。

数据结构—农夫过河问题

数据结构—农夫过河问题

题目:一个农夫带着一匹狼、一只羊、一颗白菜要过河,只有一条船而且农夫每次最多只能带一个动物或物品过河,并且当农夫不在的时候狼会吃羊,羊会吃白菜,列出所有安全将所有动物和物品带过河的方案。

要求:广度优先搜索农夫过河解,并输出结果源代码:#include <stdio.h>#include <stdlib.h>typedef int DataType;struct SeqQueue{int MAXNUM;int f, r;DataType *q;};typedef struct SeqQueue *PSeqQueue; // 顺序队列类型的指针类型PSeqQueue createEmptyQueue_seq(int m)//创建一个空队列{PSeqQueue queue = (PSeqQueue)malloc(sizeof(struct SeqQueue)); if (queue != NULL){queue->q = (DataType*)malloc(sizeof(DataType) *m);if (queue->q){queue->MAXNUM = m;queue->f = 0;queue->r = 0;return (queue);}elsefree(queue);}printf("Out of space!!\n"); // 存储分配失败return NULL;}int isEmptyQueue_seq(PSeqQueue queue)//判断队列是否为空{return (queue->f == queue->r);}void enQueue_seq(PSeqQueue queue, DataType x)//入队{if ((queue->r + 1) % queue->MAXNUM == queue->f)printf("Full queue.\n");else{queue->q[queue->r] = x;queue->r = (queue->r + 1) % queue->MAXNUM;}}void deQueue_seq(PSeqQueue queue)// 删除队列头部元素{if (queue->f == queue->r)printf("Empty Queue.\n");elsequeue->f = (queue->f + 1) % queue->MAXNUM;}DataType frontQueue_seq(PSeqQueue queue)//取队头元素{if (queue->f == queue->r)printf("Empty Queue.\n");elsereturn (queue->q[queue->f]);}int farmer(int location)//判断农夫的位置 1000表示在北岸{return (0 != (location &0x08));}int wolf(int location)//判断狼的位置 0100表示在北岸{return (0 != (location &0x04));}int cabbage(int location)//判断白菜的位置 0010表示在北岸{return (0 != (location &0x02));}int goat(int location)//判断羊的位置 0001表示在北岸{return (0 != (location &0x01));}int safe(int location)//安全状态的判断{if ((goat(location) == cabbage(location)) && (goat(location) != farmer(location))) //羊与白菜不安全return 0;if ((goat(location) == wolf(location)) && (goat(location) != farmer(location)))//羊与狼不安全return 0;return 1; // 其他状态是安全的}void bin_print(int num)//将十进制数转换成二进制数输出{char tmp[4];int i;for (i = 0; i < 4; ++i){tmp[i] = num & 0x01;num >>= 1;}for (i = 3; i >= 0; --i)putchar((tmp[i] == 0)?'0':'1');return;}int main(){int i, movers, location, newlocation;int a=0;int r[16];int route[16]; //用于记录已考虑的状态路径PSeqQueue moveTo; //用于记录可以安全到达的中间状态moveTo = createEmptyQueue_seq(20); //创建空队列enQueue_seq(moveTo, 0x00); //初始状态进队列for (i = 0; i < 16; i++)route[i] = -1; //准备数组route初值route[0] = 0;while (!isEmptyQueue_seq(moveTo) && (route[15] == - 1)){location = frontQueue_seq(moveTo); //取队头状态为当前状态deQueue_seq(moveTo);for (movers = 1; movers <= 8; movers <<= 1)//考虑各种物品移动 if ((0 != (location & 0x08)) == (0 != (location & movers)))//判断农夫与移动的物品是否在同一侧{newlocation = location ^ (0x08 | movers);//计算新状态,代表把船上的(0x08|movers)从一个岸移到另一个岸;(0x08|movers)代表船上有农夫和movers代表的东西if (safe(newlocation) && (route[newlocation] == -1)) //新状态安全且未处理{route[newlocation] = location; //记录新状态的前驱 enQueue_seq(moveTo, newlocation); //新状态入队}}}// 打印出路径if (route[15] != -1)//到达最终状态{printf("The reverse path is : \n");for (location = 15; location >= 0; location = route[location]) {r[a]=location;a++;if (location == 0) break;}for(i=a-1;i>=0;i--){printf("%d ",r[i]);bin_print(r[i]);//用1表示北岸,0表示南岸,用四位二进制数的顺序依次表示农夫、狼、白菜、羊的位置if(r[i]==0) printf("开始\n");//0000else if(r[i]==1) printf(" 农夫独自返回南岸\n"); //0001else if(r[i]==2) printf(" 农夫带着羊返回南岸\n");//0010else if(r[i]==3) printf(" 白菜与羊共同在北岸,不安全\n"); //0011else if(r[i]==4) printf(" 只有狼在北岸,农夫独自返回南岸\n"); //0100else if(r[i]==5) printf(" 狼与羊共同在北岸,不安全\n");//0101else if(r[i]==6) printf(" 农夫独自返回南岸\n");//0110else if(r[i]==7) printf(" 狼、白菜和羊共同在北岸,不安全\n");// 0111else if(r[i]==8) printf(" 农夫独自去北岸\n");//1000else if(r[i]==9) printf(" 农夫把羊带到北岸\n");//1001else if(r[i]==10) printf(" 农夫把白菜带到北岸\n");//1010else if(r[i]==11) printf(" 农夫把白菜带到北岸\n");//1011else if(r[i]==12) printf(" 农夫把狼带到北岸\n");//1100else if(r[i]==13) printf(" 只有白菜在南岸\n");//1101else if(r[i]==14) printf(" 农夫把狼带到北岸\n");//1110else if(r[i]==15) printf(" 农夫把羊带到北岸\n");//1111 putchar('\n');}printf("\n");}elseprintf("No solution.\n");}。

农夫携物过河程序

农夫携物过河程序

题目内容:有一农夫要将自己的羊、蔬菜和狼等3件物品运过河。

但农夫过河时所用的船每次最多只能装英中的一件物品,而这3件物品之间又存在一左的制约关系:羊不能单独和狼以及不能和蔬菜在一起,因为狼要吃羊,羊也能吃蔬菜。

试构造出问题模式以编程实现这一问题的求解。

1、问题分析和任务定义:根据对象的状态分为过河(1)和不过河(0),此对象集合就构成了一个状态空间。

问题就是在这个状态空间内搜索一条从开始状态到结束状态的安全路径。

显然,其初始状态为四对象都不过河,结束状态为四对象全部过河。

这里用无向图来处理,并采用邻接矩阵存储。

对于农夫,狼,羊,蔬菜组成一个4位向量,即图的顶点(F,叭S, V),状态空间为16, 初始状态为(0000),目标为(1111)。

解决问题的方法是,找到所有的安全状态,并在其中搜索岀一条(0000)到(1111)的路径。

对当前对象是否安全的判断,若当农夫与羊不在一起时,狼与羊或羊与蔬菜在一起是不安全的,英他情况是安全的。

搜索一条可行路径时,采用深度优先搜索DFS_path,每个时刻探索一条路径,并记录访问过的合法状态,一直向前探视,直到疋不通时回溯。

显然,应该用数组来保存访问过的状态,以便回溯。

显然农夫每次状态都在改变,最多也就能带一件东西过河,故搜索条件是,在顶点(F, W, S, V)的转换中,狼,羊,蔬菜三者的状态不能大于一个,即只有一个发生改变或者都不变。

①数拯的输入形式和输入值的范用:本程序不需要输入数据,故不存在输入形式和输入值的范用。

②结果的输出形式:在屏幕上显示安全状态的转换,即一条安全路径。

2、数据结构的选择概要设计⑴数据结构的选择:本程序采用无向图处理。

#define MaxNumVertices 10 //最大顶点数typedef struct //图的顶点类型int Farmer, Wolf, Sheep, Veget; //存储农夫,狼,羊,蔬菜的状态}VexType;typedef struct//图的各项信息VexType VerticesList LMaxNumVertices]; //顶点向量(代表顶点)int Edge [MaxNumVertices] [MaxNumVertices];//邻接矩阵//用于存储图中的边,苴矩阵元素个数取决于顶点个数,与边数无关}AdjGraph;⑵为了实现上述程序的功能,需要:①生成所有安全的图的顶点:②査找顶点的位置:③判断目前(F, W. S, V)是否安全,安全返回1,否则返回0:④判断顶点i和顶点j之间是否可转换,可转换返回真,否则假:⑤深度优先搜索从u到v的简单路径; ⑥输出从u 到v的简单路径,即顶点序列中不重复出现的路径。

农夫过河问题(C++编写)

农夫过河问题(C++编写)

cout<<" **
------------------------
**\n";
cout<<" **
|
农夫过河问题
|
**\n";
cout<<" **
------------------------
**\n";
cout<<"
****************************************************************************\n";
1、问题描述
从前,一个农夫带着一只狼,一只羊和一棵白菜要河(注意该狼被农夫训服了,但还会 吃羊)。他要将所有东西安全的带到河的对岸,不幸的是河边只有一条船,只能装下农夫和 他的一样东西,并且农夫必须每次都随船过,因为只有他能撑船。在无人看管的情况下,狼 要吃羊,羊要吃白菜,因此,农夫不能在河的某边岸上单独留下狼和羊,也不能单独留下羊 和白菜。那么农夫如何才能使三样东西平安过河呢?
3)、如果上两个条件都不满,则可执行运输的动作,但每次都应考虑,该运 输情况以前是否执行过(即两岸以及船上的东西以时四者各自的状态,并递归的进行下一次运载。
5、系统测试
6、经验总结
解决实际问题时,应先分析实际问题,找出实际问题的所有约束条件, 然后对问题进行数学模型的抽象化,抓主要因素,省去一些不需要的因素,将其 抽象为数学问题,然后再从整体上设计算法,搭建程序的框架,最后一步步完善 细节,这样做,会使本来毫无头绪的问题变得清晰起来。
if (a[ferryTimes][i] == a[ferryTimes][3]) {
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

郑州轻工业学院课程设计任务书题目农夫过河专业、班级计算机科学与技术学号姓名主要内容:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。

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

要求给出农夫将所有的东西运过河的方案。

基本要求:编写求解该问题的算法程序,并用此程序上机运行、调试,屏幕显示结果,能结合程序进行分析。

主要参考资料:数据结构严蔚敏完成期限:2012/6/21指导教师签名:课程负责人签名:年月日郑州轻工业学院本科数据结构课程设计总结报告设计题目:农夫过河学生姓名:系别:计算机与通信工程学院专业:计算机科学与技术班级:计算机科学与技术学号:指导教师:2012年6 月21 日一,设计题目问题描述:一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。

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

要求给出农夫将所有的东西运过河的方案。

二,运行环境(软、硬件环境)VC6.0 Windows7系统三,算法设计的思想对于这个问题,我们需要先自动生成图的邻接矩阵来存储,主要方法是先生成各种安全状态结点,存放在顶点向量中;再根据判断两个结点间状态是否可以转换来形成顶点之间的所有边,并把它们保存在邻接矩阵中。

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

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

主函数的流程图:初始化图函数的流程图:DFSpath函数的流程图:五,算法设计分析我的第一感觉,它可能是一个含有三个结点的图的问题,但这样做,我们没法来表示这个过程。

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

如果我们用一个四元组(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种状态中,有些状态是不安全的,是不允许出现的,如(0,1,1,0)表示农夫和菜在南岸,而狼和羊在北岸,这样狼会吃掉羊。

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

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

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

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

图1 筛选后剩余的安全结点及其下标号图2 农夫、狼、羊和菜问题的状态图这样,原始问题就转换为在这个图中寻找一条从顶点(0,0,0,0)到顶点(1,1,1,1)的路径的问题,这就要选用深度优先搜索的方法。

六, 运行结果分析0000 1 0001 2 0010 3 0100 4 0101 5 1010 6 1011 7 1101 8 11109111110(0,0,0,0)(1,0,1,0)(0,0,1,0)(1,1,1,0)(0,1,0,0)(1,1,0,1)(0,1,0,1)(1,1,1,1)(1,0,1,1)(0,0,0,1)结果分析:这四个数字依次代表农夫,狼,羊,白菜,(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>#define VEX_NUM 10//声明一个最大值为VEX_NUM#define FALSE 0//0代表为假#define TRUE 1//1代表为真typedef struct{int Farmer,Wolf,Sheep,Veget;}VexType;//这个是图中每个顶点类型,包括四个数,0代表在南岸,1代表北岸typedef struct{int vexnum,e;//这个是图的顶点个数VexType vexs[VEX_NUM];//它是顶点向量,分别表示各个顶点的内容int adj[VEX_NUM][VEX_NUM];//这个是邻接矩阵,我用的是邻接矩阵的方法}AdjGraph;//这个是表示该图的结构体int visited[VEX_NUM];//这个是来表示是否访问过该顶点,0代表没有访问过,//1代表已经访问过int path[VEX_NUM];//这个数组是用来存储它的路径的,用来输出int safe(int F,int W,int S,int V)//这个函数来判断这个结点状态是否安全{if(F!=S&&(W==S||S==V))//这个状态表示,农夫和羊不在同一边,没有农夫//保护羊,防止狼吃羊,return 0;//也没有农夫去管制羊,防止羊吃掉白菜elsereturn 1;//否则就是安全的。

这时返回1}int connected(AdjGraph & G,int i,int j)//这个函数用来判断图的第i个和//第j个顶点是否可以经过一次过河来相互转换{int k;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++;//当羊的状态发生改变,k++if(G.vexs[i].Veget!=G.vexs[j].Veget)k++;//当白菜的状态发生改变,k++if(G.vexs[i].Farmer!=G.vexs[j].Farmer&&k<=1)//要想这两个顶点能发//生转换,人的状态必须发生改变,并且其余状态改变的物品小于等于1 return 1;//说明可以经过一次过河转换elsereturn 0;//否则就是不可以发生转换}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;//其余的返回-1,表示不存在}void Create(AdjGraph & G)//这个是用来创造图,包括处于安全状态结点的筛//选和邻接矩阵的初始化。

相关文档
最新文档