农夫过河实验报告

合集下载

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

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

数据结构课程设计报告(农夫过河)第一篇:数据结构课程设计报告(农夫过河)目录引言...................................................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 数据结构的设计。

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

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

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

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

农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(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. 培养学生的观察、分析、总结能力。

二、实验原理动物行为学是研究动物在自然界中的行为规律和适应策略的学科。

通过观察小黄鸭过河的行为,可以了解其在不同环境下的适应能力,以及动物行为与环境因素之间的关系。

三、实验材料与工具1. 实验材料:小黄鸭、水桶、河岸、摄像机、记录表等。

2. 实验工具:摄像机、录音笔、计时器等。

四、实验方法1. 实验分组:将小黄鸭分为实验组和对照组,实验组过河,对照组在河岸观察。

2. 实验步骤:(1)将小黄鸭放入水桶中,观察其在水中的行为;(2)将水桶移至河岸,模拟小黄鸭过河的过程;(3)记录小黄鸭过河的时间、速度、路线等行为特点;(4)观察小黄鸭在过河过程中的适应能力,如游泳、潜水、攀爬等;(5)对实验数据进行统计分析。

五、实验结果与分析1. 实验结果(1)实验组小黄鸭过河的时间平均为10秒;(2)对照组小黄鸭在河岸观察的时间平均为15秒;(3)实验组小黄鸭在过河过程中,游泳、潜水、攀爬等行为均有出现。

2. 实验分析(1)实验组小黄鸭过河的时间较短,说明其具有较强的适应能力;(2)对照组小黄鸭在河岸观察的时间较长,说明其对过河环境不熟悉,适应能力较弱;(3)实验组小黄鸭在过河过程中,游泳、潜水、攀爬等行为的出现,表明其具有较强的适应环境的能力。

六、实验结论1. 小黄鸭在过河过程中具有较强的适应能力,能够通过游泳、潜水、攀爬等方式应对环境变化;2. 观察动物行为有助于了解其在自然界中的生存策略,为动物保护提供参考。

七、实验讨论1. 本实验结果表明,小黄鸭在过河过程中具有较好的适应能力,这与其在自然界中的生存环境密切相关;2. 实验过程中,对照组小黄鸭在河岸观察的时间较长,说明其在过河前需要一定的时间来熟悉环境,提高适应能力;3. 本实验为动物行为学研究提供了新的思路,有助于进一步了解动物在自然界中的生存策略。

农夫过河C语言课程设计

农夫过河C语言课程设计

农夫过河C语言课程设计一、课程目标知识目标:1. 理解C语言中基本的数据类型和语法结构;2. 学会使用C语言进行逻辑判断和循环控制;3. 掌握C语言中的函数定义和调用方法;4. 了解“农夫过河”问题的背景和解决方案。

技能目标:1. 能够运用C语言编写出解决“农夫过河”问题的程序;2. 培养逻辑思维和问题分析能力,将实际问题转化为程序代码;3. 提高编程实践能力,学会调试和修改代码,解决程序中的错误。

情感态度价值观目标:1. 激发学生对编程的兴趣,培养计算机科学素养;2. 培养学生面对问题积极思考、勇于探索的精神;3. 强调团队合作,学会与他人共同解决问题,培养沟通与协作能力。

分析课程性质、学生特点和教学要求:本课程为C语言编程课程,旨在让学生掌握C语言的基本知识,并通过解决实际问题,提高编程能力。

学生为初中生,具有一定的逻辑思维能力和数学基础。

教学要求注重实践,将理论教学与实际操作相结合,引导学生主动参与,培养其独立思考和解决问题的能力。

课程目标分解:1. 知识目标:通过讲解和实例演示,让学生掌握C语言的基本知识;2. 技能目标:通过编写“农夫过河”程序,提高学生的编程实践能力;3. 情感态度价值观目标:通过课程教学,激发学生对编程的兴趣,培养其积极思考、勇于探索的精神,以及团队合作能力。

二、教学内容1. C语言基础知识回顾:- 数据类型、变量、常量- 运算符、表达式、语句- 选择结构(if-else)- 循环结构(for、while、do-while)2. 函数定义与调用:- 函数的概念和作用- 函数的定义、声明和调用- 递归函数的原理和应用3. “农夫过河”问题分析:- 问题的描述和规则- 状态表示和状态空间- 搜索策略(深度优先、广度优先)4. 编程实践:- 设计“农夫过河”问题的算法- 编写C语言程序实现算法- 调试和优化程序5. 教学内容安排与进度:- 第一课时:C语言基础知识回顾,引入“农夫过河”问题- 第二课时:函数定义与调用,分析问题并设计算法- 第三课时:编写程序,实现“农夫过河”算法- 第四课时:调试优化程序,总结经验,展示成果教学内容关联教材章节:- 《C语言程序设计》第一章:C语言概述- 《C语言程序设计》第二章:数据类型与运算符- 《C语言程序设计》第三章:控制结构- 《C语言程序设计》第四章:函数- 《C语言程序设计》第十章:算法与程序设计实例教学内容注重科学性和系统性,结合教材章节,使学生能够在掌握C语言基础知识的基础上,学会解决实际问题,提高编程能力。

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

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

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

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

农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(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.前言课程研究项目是《数据结构》课程学习的重要方式之一,也是《数据结构》课程学习的重要组成部分之一。

农夫过河问题的求解

农夫过河问题的求解
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;

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

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

一、需求分析描述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."将狼带回起始岸语句。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

“数据结构与算法综合实验”课程设计报告题目:农夫过河问题学院计算机科学技术年级2014级专业计算机科学与技术学号********姓名高晗日期2016年3月30日星期三成绩评语黑龙江大学计算机科学技术学院、软件学院《数据结构与算法综合实验》报告1.系统概述(1)一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。

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

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

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

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

(2)为农夫过河问题抽象数据模型,体会数据模型在求解问题中的重要作用。

(3)掌握顺序表和队列的逻辑结构和存储结构。

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

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

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

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

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

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

(4)实验运行环境为VC++6.0.3.系统概要设计(1)数据结构设计要模拟农夫过河的问题,用四位二进制数顺序分别表示农夫,狼,羊,白菜的位置。

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

则问题的初始状态是整数(二进制数表示为0000);问题的终结状态是整数15(二进制表示为1111)。

用一个整数队列MoveTo把搜索过程中所有可能达到的状态都保存起来。

队列中的每一个元素表示一个可以到达的中间状态。

另外用一个整数数组route记录被访问过的状态,以及已经被发现的能够到达这些状态的前驱。

数组只需使用16个元素,每个元素的初始化值均为-1,每当队列中加入一个新状态时,数组中以该状态做下标的元素改为到达这一状态的前一状态的下标值。

所以数组的第i个元素不仅记录状态i是否被过,同时还保存该状态的前驱状态下标。

算法结束后可以利用route数组元素的值生成一个正确的状态路径。

系统状态转换结构如图1所示:图1系统状态转换结构图(2)软件结构设计农夫过河管理系统根据需求分析中的功能分析,可以提炼出主要有搜索功能,判断事物安全功能,输出过河方案功能。

而搜索功能又可以利用不同算法,如广度优先算法,深度优先算法等等。

判断事物安全功能需要将事物位置进行分析,通过位置分布的代码来判断当前状态是否安全,使用“与”位操作来考察狼和羊、羊和白菜是否在同一侧,且它们与农夫不一侧。

若是,该状态即为不安全状态,否则为安全状态。

若一个状态已经被访问过,或只有农夫一人从南岸过到北岸,则该状态被判为无效状态。

输出功能就是将过河方案在屏幕上进行显示。

系统软件结构如图1所示图1农夫过河管理系统软件模块结构图4.系统详细设计与实现(1)搜索算法设计搜索过程可利用广度优先搜索算法从初始状态二进制0000(全部在河的南岸)出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标,并且在序列中的每一个状态都可以从前一个状态得到。

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

(2)确定状态的安全有效性的功能模块设计通过位置分布的代码来判断当前状态是否安全,使用“与”位操作来考察狼和羊、羊和白菜是否在同一侧,且它们与农夫不一侧。

若是,该状态即为不安全状态,否则为安全状态。

若一个状态已经被访问过,或只有农夫一人从南岸过到北岸,则该状态被判为无效状态。

若状态安全且有效,则返回1,否则返回0。

该模块算法流程图如图2所示。

图2 确定状态的安全有效性的功能模块设计算法流程图(3)输出模块设计输出农夫过河问题的可行性方案时,可从目标状态(1111)开始,将其记入队列(或栈)中,然后再找出其前驱,记入队列(或栈)中,然后在找其前驱,…,直到找到的是开始状态(0000)为止。

要求输出时根据位置分布代码(即4位二进制数)各个位置上的0、1代码所表示的含义输出容易理解的文字。

5.系统测试对于该程序而言并没有实际输入,需要观察的就是输出结果。

对于该程序的测试及其测试用例如表3所示。

表3输出测试用例测试内容测试用例预期结果实际结果输出过河方案具体步骤无第0步:南岸农夫狼白菜羊北岸第1步:南岸狼白菜北岸农夫羊第2步:南岸农夫狼白菜北岸羊第3步:南岸狼北岸农夫羊白菜第4步:南岸农夫狼羊北岸白菜第5步:南岸羊北岸农夫狼白菜第6步:南岸农夫羊北岸狼白菜第7步:南岸北岸农夫狼白菜羊与预期结果相同6.小结(1)通过这2周的程序设计使我了解到了自己在数据结构方面的不足,也坚定了我学好编程的信心。

(2)采用广度优先的算法,利用数组只能记寻前一个前驱,导致另一个路径的丢失,不是很令人满意,所以采用第二种算法,深度优先算法,利用栈来记录路径前驱。

参考文献[1] 严蔚敏,李冬梅,吴伟民. 数据结构(C语言版)[M]. 北京:人民邮电出版社,2011:54-110.1.广度优先算法#include<iostream>#include<cstdlib>#define MAXNUM 20using namespace std;typedef struct //顺序队列类型定义{int f, r; //f表示头,r 表示尾int q[MAXNUM];//顺序队}SqQueue ,*SqQueuePtr;SqQueuePtr createEmptySQueue()//创建空队列{SqQueuePtr squeue = new SqQueue;if(squeue == NULL){cout<<"申请内存失败"<<endl;exit(0);}squeue->f=squeue->r=0;return squeue;}bool isEmptyQueue(SqQueuePtr squeue)//判断是否空队列{return (squeue->f==squeue->r);}void enQueue(SqQueuePtr squeue,int x)//向队列中插入元素x {if((squeue->r+1)%MAXNUM==squeue->f){cout<<"队列已满"<<endl;}elsesqueue->q[squeue->r]=x;squeue->r=(squeue->r+1)%MAXNUM;}}void deQueue(SqQueuePtr squeue)//出对{if(isEmptyQueue(squeue))cout<<"对列为空"<<endl;elsesqueue->f=(squeue->f+1)%MAXNUM;}int getHead(SqQueuePtr squeue)//对非空队列,求队列头部元素{if(squeue->f != squeue->r)return squeue->q[squeue->f];}bool farmerLocation(int location) //判断农夫位置对0做与运算,还是原来的数字,用来判断位置{return 0 != (location & 0x08);}bool wolfLocation(int location) //判断狼位置{return 0 != (location & 0x04);}bool cabbageLocation(int location) //判断白菜位置{return 0 != (location & 0x02);}bool goatLocation(int location) //判断羊的位置{return 0 !=(location & 0x01);}/* 其中一共有两种状态是不安全的:狼和羊单独在一起;羊和白菜单独在一起*/bool isSafe(int location) // 若状态安全则返回true{if ((goatLocation(location) == cabbageLocation(location)) //羊和白菜单独在一起&& (goatLocation(location) !=farmerLocation(location)) )return 0;if ((goatLocation(location) == wolfLocation(location))&& (goatLocation(location) !=farmerLocation(location)))//狼和羊单独在一起return 0;return 1; //其他状态是安全的}void farmerProblem(){int movers, i, location, newlocation;int route[16]; //记录已考虑的状态路径int print[MAXNUM];SqQueuePtr moveTo;moveTo = createEmptySQueue();//新的队列判断路径enQueue(moveTo, 0x00); //初始状态为0for (i = 0; i < 16; i++)route[i] = -1; //-1表示没有记录过路径route[0]=0;while (!isEmptyQueue(moveTo)&&(route[15]== -1))//队列不为空,路径未满时循环{location = getHead(moveTo); //从队头出队,location表示位置,0为北岸,1为南岸deQueue(moveTo);//已出队的删除for (movers = 1; movers <= 8; movers<<= 1)//向左移位,movers分别0001,0010,0100,1000, //也就是依次判断过河的可行性{if ((0 != (location & 0x08)) == (0 != (location & movers)))//判断农夫和要移动的物品是否在同岸{newlocation = location^(0x08|movers);//过岸if (isSafe(newlocation) && (route[newlocation] == -1))//判断是否安全,以及路径是否可用{route[newlocation] = location;enQueue(moveTo, newlocation);//记录路径并入队,位置改变}}}}/* 打印路径*/if(route[15] != -1){cout<<"过河步骤是: "<<endl;cout<<"\t\t南岸\t\t\t北岸"<<endl;i=7;for(location = 15; location >= 0; location = route[location]){print[i]=location;i--;if (location == 0)break;}for(int j=i+1;j<=7;j++){cout<<"第"<<j<<"步:";switch(print[j]){case 0: cout<<"\t\t农夫狼白菜羊\t\t\t"<<endl;break;case 1: cout<<"\t\t农夫狼白菜\t\t羊"<<endl;break;case 2: cout<<"\t\t农夫狼羊\t\t白菜"<<endl;break;case 4: cout<<"\t\t农夫白菜羊\t\t\t狼"<<endl;break;case 6: cout<<"\t\t农夫羊\t\t狼白菜"<<endl;break;case 9: cout<<"\t\t狼白菜\t\t\t农夫羊"<<endl;break;case 11: cout<<"\t\t狼\t\t\t农夫羊白菜"<<endl;break;case 13: cout<<"\t\t白菜\t\t\t农夫狼羊"<<endl;break;case 14: cout<<"\t\t羊\t\t\t农夫狼白菜"<<endl;break;case 15: cout<<"\t\t\t\t\t农夫狼羊白菜"<<endl;break;}}}}int main(){farmerProblem();return 0;}2.深度优先算法#include<iostream>#include<cstdlib>#define MAXNUM 20using namespace std;int solutionCout=0;typedef struct{int *base;//栈底指针int *top;//栈顶指针int stacksize;//栈可用的最大容量}SqStack;void createEmptyStack(SqStack &S)//构造一个空栈S{S.base=new int[MAXNUM];if(!S.base){cout<<"申请内存失败"<<endl;exit(0);}S.top=S.base;//初始为空栈S.stacksize = MAXNUM;}void Push(SqStack &S,int x)//插入一个元素x {if(S.top-S.base==S.stacksize)//栈满{cout<<"栈满";}*S.top++=x;}void Pop(SqStack &S)//出栈{if(S.top==S.base)//栈空{cout<<"栈空";}--S.top;}int getTop(SqStack S)//取栈顶元素{return *(S.top-1);}void print(SqStack S)//打印路径{int *p=S.base;solutionCout++;int print[MAXNUM];int i=0;while(!(p==S.top)){print[i]=*p;i++;p++;}cout<<"方案"<<solutionCout<<"过河步骤是: "<<endl;cout<<"\t\t南岸\t\t\t北岸"<<endl;for(int j=0;j<i;j++){cout<<"第"<<j<<"步:";switch(print[j]){case 0: cout<<"\t\t农夫狼白菜羊\t\t\t"<<endl;break;case 1: cout<<"\t\t农夫狼白菜\t\t羊"<<endl;break;case 2: cout<<"\t\t农夫狼羊\t\t白菜"<<endl;break;case 4: cout<<"\t\t农夫白菜羊\t\t狼"<<endl;break;case 6: cout<<"\t\t农夫羊\t\t狼白菜"<<endl;break;case 9: cout<<"\t\t狼白菜\t\t\t农夫羊"<<endl;break;case 11: cout<<"\t\t狼\t\t\t农夫羊白菜"<<endl;break;case 13: cout<<"\t\t白菜\t\t\t农夫狼羊"<<endl;break;case 14: cout<<"\t\t羊\t\t\t农夫狼白菜"<<endl;break;case 15: cout<<"\t\t\t\t\t农夫狼羊白菜"<<endl;break;}}}bool farmerLocation(int location) //判断农夫位置对0做与运算,还是原来的数字,用来判断位置{return 0 != (location & 0x08);}bool wolfLocation(int location) //判断狼位置{return 0 != (location & 0x04);}bool cabbageLocation(int location) //判断白菜位置{return 0 != (location & 0x02);}bool goatLocation(int location) //判断羊的位置{return 0 !=(location & 0x01);}/* 其中一共有两种状态是不安全的:狼和羊单独在一起;羊和白菜单独在一起*/bool isSafe(int location) // 若状态安全则返回true{if ((goatLocation(location) == cabbageLocation(location)) //羊和白菜单独在一起&& (goatLocation(location) !=farmerLocation(location)) )return 0;if ((goatLocation(location) == wolfLocation(location))&& (goatLocation(location) !=farmerLocation(location)))//狼和羊单独在一起return 0;return 1; //其他状态是安全的}int isAppeared(SqStack S,int location)//判断路径是否出现过,出现返回0;没有出现返回1{int *p=S.base;while (!(p==S.top)){if(*p==location)return 0;p++;}}void farmerProblem(SqStack S,int location){if(location == 15){print(S);return;}int newlocation,movers;for (movers = 1; movers <= 8; movers<<= 1)//向左移位,movers分别0001,0010,0100,1000,//也就是依次判断过河的可行性{if ((0 != (location & 0x08)) == (0 != (location & movers)))//判断农夫和要移动的物品是否在同岸{newlocation = location^(0x08|movers);//过岸if (isSafe(newlocation) && isAppeared(S,newlocation))//判断是否安全,以及路径是否可用{Push(S,newlocation);//新路径入栈farmerProblem(S,newlocation);//以新路径为当前状态递归寻找下一可行路径Pop(S);//已找到的可行路径出战}}}}int main(){SqStack S;int location=0;createEmptyStack(S);//创建辅助空栈Push(S,location);//首先将0000压入栈farmerProblem(S,location);}。

相关文档
最新文档