数据结构实验报告
——实验四农夫过河的求解
本实验的目的是进一步理解顺序表和队列的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。
一、【问题描述】
一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。请求出农夫将所有的东西运过河的方案。
二、【数据结构设计】
求解这个问题的简单的方法是一步一步进行试探,每一步搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。
要模拟农夫过河问题,首先需要对问题中每个角色的位置进行描述。一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。用0表示农夫或者某东西在河的南岸,1表示在河的北岸。例如整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。
现在问题变成:从初始状态二进制0000(全部在河的南岸) 出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标,并且在序列中的每一个状态都可以从前一状态到达。为避免瞎费功夫,要求在序列中不出现重复的状态。
实现上述求解的搜索过程可以采用两种不同的策略:一种是广度优先(breadth_first) 搜索,
另一种是深度优先(depth_first) 搜索。本书只介绍在广度优先搜索方法中采用的数据结构设计。
广度优先就是在搜索过程中总是首先搜索下面一步的所有可能状态,再进一步考虑更后面的各种情况。要实现广度优先搜索,可以使用队列。把下一步所有可能的状态都列举出来,放在队列中,再顺序取出来分别进行处理,处理过程中把再下一步的状态放在队列里……。由于队列的操作遵循先进先出的原则,在这个处理过程中,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。这样,具体算法中就需要用一个整数队列moveTo,它的每个元素表示一个可以安全到达的中间状态。另外还需要一个数据结构记录已被访问过的各个状态,以及已被发现的能够到达当前这个状态的路径。由于在这个问题的解决过程中需要列举的所有状态(二进制0000 -1111)一共16种,所以可以构造一个包含16个元素的整数顺序表来实现。顺序表的第i个元素记录状态i是否已被访问过,若已被访问过则在这个顺序表元素中记入前驱状态值,把这个顺序表叫做route。route 的每个分量初始值均为-1。route的一个元素具有非负值表示这个状态已访问过,或是正被考虑。最后可以利用route顺序表元素的值建立起正确的状态路径。于是得到农夫过河问题的广度优先算法。
1
在具体应用时,采用链队和顺序队均可,为叙述的方便,不妨设为使用顺序队。
三、【功能(函数)设计】
1、确定农夫、狼、羊和白菜位置的功能模块。
用整数location表示上述四位二进制描述的状态,由于采用四位二进制的形式表示农夫、狼、白菜和羊,所以在要使用位操作的“与”操作来考察每个角色所在位置的代码是0还是1。函数返回值为真表示所考察的角色在河的北岸,否则在南岸。例如某个状态和1000做“与”操作后所得结果为0,则说明农夫的位置上的二进制数为0,即农夫在南岸,如果所得结果为1,则说明农夫的位置上的二进制数为1,即农夫在北岸。狼、羊和白菜的处理办法以此类推。可以如下设计函数:
int farmer(int location) {
return (0 != (location & 0x08));
}
int wolf(int location) {
return (0 != (location & 0x04));
}
int cabbage(int location) {
return (0 != (location & 0x02));
}
int goat(int location) {
return (0 !=(location & 0x01));
}
2、确定安全状态的功能模块。
此功能模块通过位置分布的代码来判断当前状态是否安全。若状态安全返回1,状态不安全返回0。可以如下设计函数:
int safe(int location) // 若状态安全则返回1
{ if((goat(location) = = cabbage(location)) &&(goat(location)!=farmer(location))) return (0); // 羊吃白菜
if((goat(location) = = wolf(location)) && (goat(location)!= farmer(location)))
return (0); // 狼吃羊
return (1); // 其他状态是安全的
}
3、将各个安全状态还原成友好的提示信息的功能模块。
由于程序中route表中最终存放的是整型的数据,如果原样输出不利于最终用户理解问题的解决方案,所以要把各个整数按照4位二进制的各个位置上的0、1代码所表示的含义输出容易理解的文字。
4、输出路径
将二进制的表示转化为文字表示输出,输出过河的各个步骤
2
四、【界面设计】
如果能力和时间允许,可以使用动画设计将运送的过程演示出来。一般情况下可以使用最终的状态表描述出来就可以了。
五、【编码实现】
#include
#include
#define MAXNUM 20
typedef struct //顺序队列类型定义
{
int f, r; //f表示头,r 表示尾
int q[MAXNUM];//顺序队
}SeqQueue ,*PSeqQueue;
PSeqQueue createEmptyQueue_seq( ) //创建队列
{
PSeqQueue paqu = new SeqQueue;
if (paqu == NULL)
cout<<"Out of space!"< else paqu->f=paqu->r=0; return (paqu); } int isEmptyQueue_seq( PSeqQueue paqu ) //判断paqu 所指是否是空队列 { return paqu->f==paqu->r; } void enQueue_seq(PSeqQueue paqu,int x) //在队列中插入一元素x { if ((paqu->r+1)%MAXNUM==paqu->f) cout<<"队列已满."< else { paqu->q[paqu->r]=x; paqu->r=(paqu->r+1)%MAXNUM; } } 3 void deQueue_seq(PSeqQueue paqu) //删除队列头部元素 { if( paqu->f==paqu->r) cout<<"队列为空"< else paqu->f=(paqu->f+1)%MAXNUM; } int frontQueue_seq( PSeqQueue paqu ) //对非空队列,求队列头部元素 { return (paqu->q[paqu->f]); } int farmer(int location) //判断农夫位置对0做与运算,还是原来的数字,用来判断位置{ return 0 != (location & 0x08); } int wolf(int location) //判断狼位置 { return 0 != (location & 0x04); } int cabbage(int location) //判断白菜位置 { return 0 != (location & 0x02); } int goat(int location) //判断羊的位置 { return 0 !=(location & 0x01); } int safe(int location) // 若状态安全则返回true { 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 farmerProblem( ) { int movers, i, location, newlocation; 4 int route[16]; //记录已考虑的状态路径 int print[MAXNUM]; PSeqQueue moveTo; moveTo = createEmptyQueue_seq( );//新的队列判断路径 enQueue_seq(moveTo, 0x00); //初始状态为0 for (i = 0; i < 16; i++) route[i] = -1; //-1表示没有记录过路径 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);//或运算 if (safe(newlocation) && (route[newlocation] == -1))//判断是否安全,以及路径是否可用 { route[newlocation] = location; enQueue_seq(moveTo, newlocation); } } } } /* 打印出路径*/ if(route[15] != -1) { cout<<"过河步骤是: "< i=0; for(location = 15; location >= 0; location = route[location]) { 5 print[i]=location; i++; if (location == 0) break; } int num=i-1; int temp[20][4]; int j; for(i=num;i>=0;i--) { for(j=3;j>=0;j--) { temp[num-i][j]=print[i]%2; print[i]/=2; temp[0][j]=0; temp[num+1][j]=1; } } for(i=1;i<=num;i++) { cout<<"\t\t\tNO . "< if(i%2==1) { if(temp[i][3]!=temp[i-1][3]) cout<<"农夫带羊过南岸"; if(temp[i][2]!=temp[i-1][2]) cout<<"农夫带白菜过南岸"; if(temp[i][1]!=temp[i-1][1]) cout<<"农夫带狼过南岸"; if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-1][2]&&temp[i][1]==temp[i- 1][1]) cout<<"农夫自己过南岸"; } else if(i%2==0) { if(temp[i][3]!=temp[i-1][3]) cout<<"农夫带羊回北岸"; if(temp[i][2]!=temp[i-1][2]) 6 cout<<"农夫带白菜回北岸"; if(temp[i][1]!=temp[i-1][1]) cout<<"农夫带狼回北岸"; if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-1][2]&&temp[i][1]==temp[i-1][1]) cout<<"农夫自己回北岸"; } cout< } } else cout<<"No solution."< } int main() /*主函数*/ { farmerProblem(); return 0; } 六、【运行与测试】 程序应在屏幕上得出如下结果: 过河步骤是: NO . 1 农夫带羊过南岸 NO . 2 农夫自己回北岸 NO . 3 农夫带白菜过南岸 NO . 4 农夫带羊回北岸 NO . 5 农夫带狼过南岸 NO . 6 农夫自己回北岸 NO . 7 农夫带羊过南岸 7 实验1: Prolog语言程序设计 人工智能(AI)语言是一类适应于人工智能和知识工程领域的、具有符号处理和逻辑推理能力的计算机程序设计语言。能够用它来编写求解非数值计算、知识处理、推理、规划、决策等具有智能的各种复杂问题。 Prolog是当代最有影响的人工智能语言之一,由于该语言很适合表达人的思维和推理规则,在自然语言理解、机器定理证明、专家系统等方面得到了广泛的应用,已经成为人工智能应用领域的强有力的开发语言。 尽管Prolog语言有许多版本,但它们的核心部分都是一样的。Prolog的基本语句仅有三种,即事实、规则和目标三种类型的语句,且都用谓词表示,因而程序逻辑性强,方法简捷,清晰易懂。另一方面,Prolog是陈述性语言,一旦给它提交必要的事实和规则之后,Prolog就使用内部的演绎推理机制自动求解程序给定的目标,而不需要在程序中列出详细的求解步骤。 一、实验目的 1、加深学生对逻辑程序运行机理的理解。 2、掌握Prolog语言的特点、熟悉其编程环境。 3、为今后人工智能程序设计做好准备。 二、实验内容 1、编写一个描述亲属关系的Prolog程序,然后再给予出一些事实数据,建立一个小型演绎数据库。 提示:可以以父亲和母亲为基本关系(作为基本谓词),再由此来描述祖父、祖母、兄弟、姐妹以及其他所属关系。 2、编写一个路径查询程序,使其能输出图中所有路径。 提示:程序中的事实描述了下面的有向图,规则是图中两节点间通路的定义。 e 3、一个雇主在发出招聘广告之后,收到了大量的应聘申请。为了从中筛选出不量的候选人,该雇主采用下列判据:申请者必须会打字、开车,并且住在伦敦。 (a)用Prolog规则表述这个雇主的选择准则。 (b)用Prolog事实描述下列申请者的情况: 史密斯住在剑桥,会开车但不会打字。 布朗住在伦敦,会开车也会打字。 简住在格拉斯哥,不会开车但会打字。 埃文斯住在伦敦,会开车也会打字。 格林住在卢顿,会开车也会打字。 (c)要求Prolog提供一个候选人名单。 4、实现递归谓词remove(X,Y,Z),它用于从表Y中除去所有整型数X的倍数值后得到新表Z。例如,对于询问 remove(2,[3,4,5,6,7,8,9,10],Z). 的回答为: Z=[3,5,7,9] 三、实验建议 1、首先运行Prolog安装目录中PROGRAM目录下的示例程序,对Prolog功能有一个感性认识。 (1)HANOI.PRO 实现汉诺塔演示的程序。 程序运行界面如图所示。 郑州轻工业学院 课程设计任务书 题目农夫过河 专业、班级计算机科学与技术 学号姓名 主要内容: 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不能吃白菜。要求给出农夫将所有的东西运过河的方案。基本要求: 编写求解该问题的算法程序,并用此程序上机运行、调试,屏幕显示结果,能结合程序进行分析。 主要参考资料: 数据结构严蔚敏 完成期限:2012/6/21 指导教师签名: 课程负责人签名: 年月日 郑州轻工业学院 本科 数据结构课程设计总结报告 设计题目:农夫过河 学生姓名: 系别:计算机与通信工程学院 专业:计算机科学与技术 班级:计算机科学与技术 学号: 指导教师: 2012年6 月21 日 一,设计题目 问题描述: 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不能吃白菜。要求给出农夫将所有的东西运过河的方案。 二,运行环境(软、硬件环境) VC6.0 Windows7系统 三,算法设计的思想 对于这个问题,我们需要先自动生成图的邻接矩阵来存储,主要方法是先生成各种安全状态结点,存放在顶点向量中;再根据判断两个结点间状态是否可以转换来形成顶点之间的所有边,并把它们保存在邻接矩阵中。在建立了图的邻接矩阵存储结构后,利用递归深度优先搜索求出从顶点(0,0,0,0)到顶点(1,1,1,1)的一条简单路径,这样做只能搜到一种合理方法,因为深度优先搜索遍历一个图的时候每一个结点只能被访问一次。 四,算法的流程图 要写算法的流程图,必须要先很了解自己的函数结构,我先在纸上手动的把整个过程在纸上画一遍,了解它的大体流程,然后把各个函数给分开,下面是我自己根据我的代码中画的各个函数画的流程图,希望老师满意。 主函数的流程图: . 西华大学实验报告(计算机类) 开课学院及实验室:实验时间:年月日 一、实验目的 通过练习让学生对数据库、数据库和表的关系、数据词典、参照完整性和视图有较好的理解和掌握。 二、内容与设计思想 实验内容: 1.数据库设计器 2.数据库的创建 3.设定数据词典 4.参照完整性的设置 5.视图的创建和修改 三、使用环境 Windos XP操作系统;Visual ProFox 6.0 四、核心代码及调试过程 例3-27创建项目管理器SBGL,要求添入数据库sbsj,并查看该数据库。 图一 图二、“项目管理器”的数据选项卡 图三、“项目管理器”中的数据库与数据库表 例3-28从sbsj数据库所属的sb和zz两个表中抽取编号、名称和增值3个字段。,组成名称 为“我的视图”的SQL视图。 open database sbsj create sql view 我的视图; as select sb.编号,sb.名称,zz.增值from sb,zz where sb.编号=zz.编号 如有你有帮助,请购买下载,谢谢! 例3-29根据例3-28的查询要求,用视图设计器建立视图1,然后修改其中车床的增值来更新zz表原来的增值 图一、视图设计器-视图1 图二、视图设计器-视图1 图三、增值表 图四 图五、视图设计器更新源表数据 19.根据图3.30所示数据库sbsj的永久关系,若利用参照完整性生成器来删除sb。dbf的第一个记录,对其他3个表会否产生影响,是分级、限制和忽略3中情况来说明。 图一、数据库设计器 图二、sbsj.dbc“永久关系的参照完整性生成器” 级联:相关子表中的记录将自动删除 限制:子表有相关记录,在父表中删除记录就会产生“触发器失败”的提示信息 忽略:父表删除记录,与子表记录无关 五、总结 (自己写一些收获和体会) 通过这次上机练习让我学会了怎样在数据库中添加项目管理器、表的数据完整性的概念以及视图的各种操作,让我更容易的掌握理论知识的难点和一些基本命令的使用方法,以及一些平时在课堂上不注意的问题。在上机练习的过程中需要对每个细节都要留心,认真做好每一步这样才不至于出错,这就加强了平时不注意的问题得到回应,从而加深了细节问题的处理方式。在上机的学习之后更加了解了数据库表及其数据完整性是vfp重要的一个对象,命令熟练操作直接关系到数据库的成败。 第三次的上机操作,我了解了命令的使用方式对于建立数据库表及其数据完整性很重要,要学好各种命令以及数据库表及其数据完整性的使用方法,还需在多做习题加强学习。 六、附录 邻接矩阵的实现 1. 实验目的 (1)掌握图的逻辑结构 (2)掌握图的邻接矩阵的存储结构 (3)验证图的邻接矩阵存储及其遍历操作的实现2. 实验内容 (1)建立无向图的邻接矩阵存储 (2)进行深度优先遍历 (3)进行广度优先遍历3.设计与编码MGraph.h #ifndef MGraph_H #define MGraph_H const int MaxSize = 10; template int vertexNum, arcNum; }; #endif MGraph.cpp #include 农夫过河问题状态图及程序 一、问题需求分析 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。问题是他面前只有一条小船,船小到只能容下他和一件物品,另外只有农夫能撑船。另外,因为狼能吃羊,而羊爱吃白菜,所以农夫不能留下羊和白菜或者狼和羊单独在河的一边,自己离开。请问农夫该采取什么方案才能将所有的东西运过河呢? 二、算法选择 求解这个问题的最简单的方法是一步一步进行试探,每一步都搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。 用计算机实现上述求解的搜索过程可以采用两种不同的策略:一种是广度优先(breadth_first) 搜索,另一种是深度优先(depth_first) 。 广度优先: u 广度优先的含义就是在搜索过程中总是首先搜索下面一步的所有可能状态,然后再进一步考虑更后面的各种情况。u 要实现广度优先搜索,一般都采用队列作为辅助结构。把下一步所有可能达到的状态都列举出来,放在这个队列中, 然后顺序取出来分别进行处理,处理过程中把再下一步的状态放在队列里……。 u 由于队列的操作遵循先进先出的原则,在这个处理过程中,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。 三、算法的精化 要模拟农夫过河问题,首先需要选择一个对问题中每个角色的位置进行描述的方法。一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。例如用0表示农夫或者某东西在河的南岸,1表示在河的北岸。因此整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。 四、算法的实现 完成了上面的准备工作,现在的问题变成: 从初始状态二进制0000(全部在河的南岸) 出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸) 为最终目标,并且在序列中的每一个状态都可以从前一状态通过农夫(可以带一样东西)划船过河的动作到达。 1:实验要求 1.1实验目的 掌握图的遍历问题,运用图的遍历算法解决复杂问题。掌握并应用邻接存储结构和图的深度遍历问题。培养学习使用图的相关知识解决实际问题的能力。 1.2实验内容问题描述 问题描述:农夫携带一只狼,一只羊,一棵白菜从和的左岸到达河的右岸,由于船只较小,农夫每次只能携带一样过河,在无人看管的情况下狼吃羊,羊吃白菜。 1.3:实验输出要求 要求输出农夫携带所有东西安全过河的步骤。 2:程序设计分析 2.1:实验内容分析 农夫需要多次驾船往返于河的左右两岸,农夫每次过河都会使农夫,狼,羊,白菜的位置发生变化。利用四元组(农夫,狼,羊,白菜)来表示各自所处于河的左岸右岸的位置,0表示河的左岸,1表示河的右岸。初始状态时(0,0,0,0)都处在河的左岸,终态是(1,1,1,1)四者都处在河的右岸。 共有16种状态,但其中有些状态不安全,删除不安全的状态,将安全的状态按照合理的过河步骤联系起来. (0,0,0,0) (1,0,1,0) (0,0,1,0) (1,1,1,0) (1,0,1,1) (0,1,0,0) (0,0,0,1) (1,1,0,1) (0,1,0,1) (1,1,1,1) 安全过河状态图 2.2主要函数模块算法分析 1:栈的相关函数 PSeqStack Init_SeqStack(void) //栈的初始化 int Empty_SeqStack(PSeqStack s) //判断栈是否为空栈非空1表示栈空 void Push_SeqStack(PSeqStack s,int x) //入栈 int Pop_SeqStack(PSeqStack s,int *x) //出栈 int Size_SeqStack(PSeqStack s) //顺序栈中元素的个数 void Destroy_SeqStack(PSeqStack *S) //销毁栈 2,:求结点直接后继结点个数的函数 int CountAdjoin(MGraph *G,int u) 3:查找状态(f,w,s,v)在无向图中的位置的函数 int located(MGraph *G,int f,int w,int s,int v) 4:结点值安全状态判断函数 int if_safe(int f,int w,int s,int v) 5:判断农夫过河的两个状态是否是相邻的函数 int if_connected(MGraph *G,int i,int j) 6:创建农夫过河状态的无向图 void Creat_MGraph(MGraph *G) 7:广优度先遍历遍历所有从状态下标u到状态下标v的路径函数 void BFS_path(MGraph *G,int u,int v) 8:输出所有从状态下标为u到状态下标为v的所有简单路径 void print_path(MGraph *G,int u,int v) 2.3部分函数源代码 path[u][m] 为状态下标u的直接后继状态下标 m表示状态下标u的直接后继结点个数:int path[MaxVertexNum][MaxVertexNum]; 主要结构:typedef struct { int farmer; int wolf; int sheep; int vegetable; 数据结构实验报告 ——实验四农夫过河的求解本实验的目的是进一步理解顺序表和队列的逻辑结构和存储结构,进一步提高使用理论知识指导解决实际问题的能力。 一、【问题描述】 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。请求出农夫将所有的东西运过河的方案。 二、【数据结构设计】 求解这个问题的简单的方法是一步一步进行试探,每一步搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。 要模拟农夫过河问题,首先需要对问题中每个角色的位置进行描述。一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。用0表示农夫或者某东西在河的南岸,1表示在河的北岸。例如整数5(其二进制表示为0101)表示农夫和白菜在河的南岸,而狼和羊在北岸。 现在问题变成:从初始状态二进制0000(全部在河的南岸)出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标,并且在序列中的每一个状态都可以从前一状态到达。为避免瞎费功夫,要求在序列中不出现重复的状态。 实现上述求解的搜索过程可以采用两种不同的策略:一种是广度优先(breadth_first)搜索, 另一种是深度优先(depth_first)搜索。本书只介绍在广度优先搜索方法中采用的数据结构设计。 广度优先就是在搜索过程中总是首先搜索下面一步的所有可能状态,再进一步考虑更后面的各种情况。要实现广度优先搜索,可以使用队列。把下一步 图实验 一,邻接矩阵的实现 1.实验目的 (1)掌握图的逻辑结构 (2)掌握图的邻接矩阵的存储结构 (3)验证图的邻接矩阵存储及其遍历操作的实现 2.实验内容 (1)建立无向图的邻接矩阵存储 (2)进行深度优先遍历 (3)进行广度优先遍历 3.设计与编码 #ifndef MGraph_H #define MGraph_H const int MaxSize = 10; template “数据结构与算法综合实验”课程设计报告题目:农夫过河问题 学院计算机科学技术 年级2014级 专业计算机科学与技术 学号20142060 姓名高晗 日期2016年3月30日星期三 成绩 评语 黑龙江大学 计算机科学技术学院、软件学院 《数据结构与算法综合实验》报告 1.系统概述 (1)一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。他面前只有一只小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,但是狼不吃白菜。要求给出农夫将所有东西运过河的方案。 (2)为农夫过河问题抽象数据模型,体会数据模型在求解问题中的重要作用。 (3)掌握顺序表和队列的逻辑结构和存储结构。 2.系统需求分析 (1)针对实现整个过程需要多步,不同步骤中各个事物所处位置不同的情况,可定义一个结构体来实现对四个对象狼、羊、白菜和农夫的表示。对于起始岸和目的岸,可以用0或者1来表示,以实现在程序设计中的简便性。 (2)题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,进行下一步试探。这就需要使用循环或者递归算法,避免随机盲目运算且保证每种情况均试探到,不接受非法输入。 (3)题目要求求出农夫带一只羊,一条狼和一颗白菜过河的办法,所以依次成功返回运算结果后,需要继续运算,直至求出结果,即给出农夫的过河方案。输出界面要求具有每一步中农夫所带对象及每步之后各岸的物体,需要定义不同的数组来分别存储上述内容,并使界面所示方案清晰简洁。 (4)实验运行环境为VC++6.0. 3.系统概要设计 (1)数据结构设计 要模拟农夫过河的问题,用四位二进制数顺序分别表示农夫,狼,羊,白菜的位置。用0表示农夫或某种东西在河的南岸,1表示在河的北岸。则问题的初 本科实验报告 课程名称:数据结构 实验项目:线性结构、树形结构、图结构、查找、排序实验地点: 专业班级:学号: 学生姓名: 指导教师: 2011年12 月24 日 实验项目:线性结构 实验目的和要求 熟练掌握线性结构的基本操作在顺序表和链式表上的实现。 二、实验内容和原理 设顺序表递增有序,编写一个程序,将x插入,使之仍然有序。 三、主要仪器设备 使用的计算机:Nopated++ 四、操作方法与实验步骤 #include A[n]=x; } else { while(A[i] Lab05.队列的操作及应用 【实验目的和要求】 1.掌握队列的顺序表示和链表表示下的基本操作; 2.深入理解深度优先搜索和广度优先搜索的思想并能正确描述其算法; 3.会应用广度优先搜索算法解决较复杂的问题。 【实验内容】 1.编写一个C源程序,其中包含顺序表示的空队列的创建、判断队列是否为空、进队、出队、取队列头部元素等操作。 2.编写一个C源程序,其中包含链表表示的空队列的创建、判断队列是否为空、进队、出队、取队列头部元素等操作。 3. 简述深度优先搜索和广度优先搜索的思想,并给出具体的算法步骤。 4.应用广度优先搜索算法求解农夫过河问题。 【实验仪器与软件】 1.CPU主频在1GHz以上,内存在512Mb以上的PC; 2.VC6.0,Word 2003及以上版本。 实验讲评: 实验成绩: 评阅教师: 2012 年月日 Lab05.队列的操作及应用 一、顺序表示的队列基本操作 1.顺序表示的队列操作基本源程序 #include 课程设计题目:农夫过河 一.问题描述 一个农夫带着一只狼、一只羊和一箩白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。过河有以下规则: (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) 附件2: 北京理工大学珠海学院实验报告 ZHUHAI CAMPAUS OF BEIJING INSTITUTE OF TECHNOLOGY 实验题目图及其应用实验时间 2011.5.10 一、实验目的、意义 (1)熟悉图的邻接矩阵(或邻接表)的表示方法; (2)掌握建立图的邻接矩阵(或邻接表)算法; (3)掌握图的基本运算,熟悉对图遍历算法; (4)加深对图的理解,逐步培养解决实际问题的编程能力 二、实验内容及要求 说明1:学生在上机实验时,需要自己设计出所涉及到的函数,同时设计多组输入数据并编写主程序分别调用这些函数,调试程序并对相应的输出作出分析;修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。 具体要求: (1)建立图的邻接矩阵(或邻接表); (2)对其进行深度优先及广度优先遍历。 三、实验所涉及的知识点 1.创建一个图: CreateUDN(MGraph &G) 2.查找v顶点的第一个邻接点: FirstAdjVex(MGraph G,int v) 3. 查找基于v顶点的w邻接点的下一个邻接点: NextAdjVex(MGraph G,int v,int w) 4.图的矩阵输出: printArcs(MGraph G) 5:顶点定位: LocateVex(MGraph G,char v) 6. 访问顶点v输出: printAdjVex(MGraph G,int v) 7. 深度优先遍历: DFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)) 8. 广度优先遍历BFSTraverse(MGraph G,Status (*Visit)(MGraph G,int v)) 9. DFS,从第v个顶点出发递归深度优先遍历图G: DFS(MGraph G,int v) 四、实验记录 1.对顶点的定位其数组下标,利用了找到之后用return立即返回,在当图顶点 多的情况下节省了搜索时间,程序如下 //对顶点v定位,返回该顶点在数组的下标索引,若找不到则返回-1 int LocateVex(MGraph G,char v){ for (int i=0;i *******大学 实验报告| | 实验名称PROLOG语言练习与编程上机实验 课程名称人工智能及应用 | | 专业班级:*******学生姓名:****** 学号:*******成绩: 指导教师:*******实验日期: 一、实验目的及要求 1、熟悉并掌握prolog的编程环境、prolog语言的回溯、递归技术和表处理技 术; 2、运用prolog及其相关技术,编写并调试求解农夫过河和模式搜索问题的程 序。要求实验报告中包括:程序及其注释和说明、程序运行结果。 二、所用仪器、设备 PC台式机和prolog编译软件 三、实验原理 1、prolog本身自带推理机,其回溯、递归技术和表处理技术可简化复杂问 题求解。 2、prolog的跟踪、设断点对于调试程序是非常有用的。 四、求解的问题与程序 农夫过河问题 opposite(s,n). opposite(n,s). safe_goat(X,_,X,_). safe_cabbage(X,_,_,X). safe_goat(F,X,Y,_):-opposite(X,Y). safe_cabbage(F,_,X,Y):-opposite(X,Y). is_peaceful(F,W,G,C):-safe_goat(F,W,G,C),safe_cabbage(F,W,G,C). transform(location(X,W,G,C),location(Y,W,G,C)):-opposite(X,Y). transform(location(X,X,G,C),location(Y,Y,G,C)):-opposite(X,Y). transform(location(X,W,X,C),location(Y,W,Y,C)):-opposite(X,Y). transform(location(X,W,G,X),location(Y,W,G,Y)):-opposite(X,Y). member(X,[X|_]). member(X,[_|T]):-member(X,T). legal_states(location(F0,W0,G0,C0),location(F,W,G,C),States,X):- transform(location(F0,W0,G0,C0),location(F1,W1,G1,C1)), 农夫过河 教学目标 1、知识与能力:通过农夫过河的数学逻辑问的题,探讨研究找到解决问题的办法和养成自己动脑动手的解决问题的能力。 2、过程与方法:通过以角色扮演的形式让学生自己动脑动手寻找答案和探讨解决问题的方法。 3、态度价值观:知道数学有很多有趣的东西,培养爱科学的情感。教师准备 1. 数学课件。 2、做“狼、羊、白菜、农夫”头饰。 3、准备四张纸分别写上“狼、羊、白菜、农夫”。 教学过程 一、谈话导入 介绍我国著名的数学家华罗庚爷爷。 数学家华罗庚生平介绍,主要科学业绩,对数学的贡献等等。介绍华罗庚爷爷的话。“数学本身,也是无穷的美妙,认为数学枯燥,是不正确的,就像站在花园外面,说花园枯燥无味一样,只要你踏进大门,随时会发现数学有许多有趣的东西。”数学并不是几个数字算来算去,它的学问大着呢。下面这道题能引起你的兴趣吗? 二、创设情境 1、出示数学问题:有一个农夫带一匹狼、一只羊和一棵白菜过河(从河的东岸到西岸)。如果没有农夫看管,则狼要吃羊,羊要吃白菜。 但是船很小,只够农夫带一样东西过河。 2、图片演示。(一条河;一边是对岸;另一边是河岸,有农夫、狼、羊、白菜) 三、探究学习 1、以小组表演形式(演示出河的位置)和讨论形式解题 第一步是什么?必须是什么?(农夫和羊先过河) 第二步是什么?(农夫自己回来) 第三步是什么? 2、全班学生汇报交流 问题的突破口在——狼与白菜能够共存!农夫、狼、羊、白菜和船组成了这个系统。系统中各要素是一个整体,都依赖农夫过河;最大的问题是“船很小,只够农夫带一样东西过河”和“没有农夫看管,则狼要吃羊,羊要吃白菜”的冲突。我们联系已知条件,做了一系列的分析实验,但是比较其他方案不能实现所有要素都安全过河。最后得出以上方案。 具体描述如下: 第一步:把羊带过河,坐船返回; 第二步:把狼带过河,带羊返回; 第三步:将羊放在这一岸后,带白菜过河; 第四步:坐船返回,把羊带过河。 或者: 第一步:把羊带过河,坐船返回; 数据结构教程 上机实验报告 实验七、图算法上机实现 一、实验目的: 1.了解熟知图的定义和图的基本术语,掌握图的几种存储结构。 2.掌握邻接矩阵和邻接表定义及特点,并通过实例解析掌握邻接 矩阵和邻接表的类型定义。 3.掌握图的遍历的定义、复杂性分析及应用,并掌握图的遍历方 法及其基本思想。 二、实验内容: 1.建立无向图的邻接矩阵 2.图的深度优先搜索 3.图的广度优先搜索 三、实验步骤及结果: 1.建立无向图的邻接矩阵: 1)源代码: #include "" #include "" #define MAXSIZE 30 typedef struct { char vertex[MAXSIZE]; ertex=i; irstedge=NULL; irstedge; irstedge=p; p=(EdgeNode*)malloc(sizeof(EdgeNode)); p->adjvex=i; irstedge; irstedge=p; } } int visited[MAXSIZE]; ertex); irstedge; ertex=i; irstedge=NULL; irstedge;irstedge=p; p=(EdgeNode *)malloc(sizeof(EdgeNode)); p->adjvex=i; irstedge; irstedge=p; } } typedef struct node { int data; struct node *next; }QNode; ertex); irstedge;ertex); //输出这个邻接边结点的顶点信息 visited[p->adjvex]=1; //置该邻接边结点为访问过标志 In_LQueue(Q,p->adjvex); //将该邻接边结点送人队Q } 扬州大学信息工程学院 《数据结构》 ---课程设计报告 题目:农夫过河 班级:网络1501 学号:1524 姓名:王 指导教师:王 一、课程题目 一个农夫带着一只狼,一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。 二、需求分析 求出农夫将所有的东西运过河的方案。 三、概要设计 求解这个问题的简单的方法是一步一步进行试探,每一步搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。要模拟农夫过河问题,首先需要对问题中每个角色的位置进行描述。一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。用0表示农夫或者某东西在河的南岸,1表示在河的北岸。例如整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。现在问题变成:从初始状态二进制0000(全部在河的南岸) 出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标,并且在序列中的每一个状态都可以从前一状态到达。为避免瞎费功夫,要求在序列中不出现重复的状态。 四、详细设计 实现上述求解的搜索过程可以采用策略广度优先(breadth_first) 搜索。广度优先就是在搜索过程中总是首先搜索下面一步的所有可能状态,再进一步考虑更后面的各种情况。要实现广度优先搜索,可以使用队列。把下一步所有可能的状态都列举出来,放在队列中,再顺序取出来分别进行处理,处理过程中把再下一步的状态放在队列里。由于队列的操作遵循先进先出的原则,在这个处理过程中,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。这样,具体算法中就需要用一个整数队列moveTo,它的每个元素表示一个可以安全到达的中间状态。另外还需要一个数据结构记录已被访问过的各个状态,以及已被发现的能够到达当前这个状态的路径。由于在这个问题的解决过程中需要列举的所有状态(二进制0000 -1111)一共16种,所以可以构造一个包含16个元素的整数顺序表来实现。顺序表的第i个元素记录状态i是否已被访问过,若已被访问过则在这个顺序表元素中记入前驱状态值,把这个顺序表叫做route。route的每个分量初始值均为-1。route的一个元素具有非负值表示这个状态已访问过,或是正被考虑。最后可以利用route顺序表元素的值建立起正确的状态路径。于是得到农夫过河问题的广度优先算法。在具体应用时,采用链队和顺序队均可,为叙述的方便,不妨设为使用顺序队。 模块划分 1、void BA() //农夫从B岸到A岸 2、void xu() //初始化三样东西的位置 3、void f() //判断农夫的位置 4、int g() //判断羊的位置 5、void huan () //农夫返回 6、void AB() //农夫从A岸到B岸 目录 引言 (2) 1 问题描述 (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 概要设计 3.1 数据结构的设计。 3.1.1农夫过河问题的模型化 分析这类问题会发现以下特征: 有一组状态( 如农夫和羊在南, 狼和白菜在北) ; 从一个状态可合法地转到另外几个状态( 如农夫自己过河或农夫带着羊过河) ; 有些状态不安全( 如农夫在北, 其他东西在南) ; 有一个初始状态( 都在南) ; 结束状态集( 这里只有一个, 都在北) 。 问题表示: 需要表示问题中的状态, 农夫等位于南P北( 每个有两种可能) 。可以采用位向量, 4 个二进制位的0P1 情况表示状态, 显而易见, 共24= 16种可能状态。从高位到低位分别表示农夫、狼、白菜和羊。0000( 整数0) 表示都在南岸, 目标状态1111( 即整数15) 表示都到了北岸。有些状态0011,0101, 0111, 0001, 1100, 1001 是不允许出现的, 因为这些状态是不安全状态。根据上述条件可以画出系统的状态图如图1 所示。 图1 系统状态转换图 其中双向的箭头表示状态可逆, 即农夫可以带 着某种东西过去, 也可以带着该东西回来。箭头上的字母表示农夫所携带的东西: f( farmer) , w(wolf) , g(goat) , c( cabbage) 分别表示农夫自己、农夫携带狼、农夫携带羊、农夫携带菜过河。现在的问题转化为: 找一条合法路径( 相邻状态之间的转移合法) , 从开始状态到某个结束状态, 途中不经过不安全状态。 附录A 实验报告 课程:数据结构(c语言)实验名称:图的建立、基本操作以及遍历系别:数字媒体技术实验日期: 12月13号 12月20号 专业班级:媒体161 组别:无 姓名:学号: 实验报告内容 验证性实验 一、预习准备: 实验目的: 1、熟练掌握图的结构特性,熟悉图的各种存储结构的特点及适用范围; 2、熟练掌握几种常见图的遍历方法及遍历算法; 实验环境:Widows操作系统、VC6.0 实验原理: 1.定义: 基本定义和术语 图(Graph)——图G是由两个集合V(G)和E(G)组成的,记为G=(V,E),其中:V(G)是顶点(V ertex)的非空有限集E(G)是边(Edge)的有限集合,边是顶点的无序对(即:无方向的,(v0,v2))或有序对(即:有方向的, 无向图中顶点V i的度TD(V i)是邻接矩阵A中第i行元素之和有向图中, 顶点V i的出度是A中第i行元素之和 顶点V i的入度是A中第i列元素之和 邻接表 实现:为图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(有向图中指以Vi为尾的弧) 特点: 无向图中顶点Vi的度为第i个单链表中的结点数有向图中 顶点Vi的出度为第i个单链表中的结点个数 顶点Vi的入度为整个单链表中邻接点域值是i的结点个数 逆邻接表:有向图中对每个结点建立以Vi为头的弧的单链表。 图的遍历 从图中某个顶点出发访遍图中其余顶点,并且使图中的每个顶点仅被访问一次过程.。遍历图的过程实质上是通过边或弧对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用的存储结构。图的遍历有两条路径:深度优先搜索和广度优先搜索。当用邻接矩阵作图的存储结构时,查找每个顶点的邻接点所需要时间为O(n2),n为图中顶点数;而当以邻接表作图的存储结构时,找邻接点所需时间为O(e),e 为无向图中边的数或有向图中弧的数。 实验内容和要求: 选用任一种图的存储结构,建立如下图所示的带权有向图: 要求:1、建立边的条数为零的图;人工智能实验一指导
农夫过河数据结构
数据库和数据结构实验报告
数据结构实验报告图实验
农夫过河问题状态图及程序
农夫过河和骑士周游(数据结构课程设计)教学内容
农夫过河实验报告――数据结构
数据结构实验报告图实验
农夫过河实验报告
华仔数据结构实验报告
LAB05+队列的操作及应用
农夫过河问题
数据结构图及其应用实验报告+代码
PROLOG实验报告
趣味数学教案—农夫过河
数据结构图实验报告
数据结构课程设计农夫过河问题
数据结构课程设计报告(农夫过河)
数据结构实验报告(图)