农夫过河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;}实验结果:四、实验总结。
农夫过河问题(数据结构课设)
#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("问题:农夫过河。
农夫过河问题(C++编写)
cout<<" **
------------------------
**\n";
cout<<" **
|
农夫过河问题
|
**\n";
cout<<" **
------------------------
**\n";
cout<<"
****************************************************************************\n";
1、问题描述
从前,一个农夫带着一只狼,一只羊和一棵白菜要河(注意该狼被农夫训服了,但还会 吃羊)。他要将所有东西安全的带到河的对岸,不幸的是河边只有一条船,只能装下农夫和 他的一样东西,并且农夫必须每次都随船过,因为只有他能撑船。在无人看管的情况下,狼 要吃羊,羊要吃白菜,因此,农夫不能在河的某边岸上单独留下狼和羊,也不能单独留下羊 和白菜。那么农夫如何才能使三样东西平安过河呢?
3)、如果上两个条件都不满,则可执行运输的动作,但每次都应考虑,该运 输情况以前是否执行过(即两岸以及船上的东西以时四者各自的状态,并递归的进行下一次运载。
5、系统测试
6、经验总结
解决实际问题时,应先分析实际问题,找出实际问题的所有约束条件, 然后对问题进行数学模型的抽象化,抓主要因素,省去一些不需要的因素,将其 抽象为数学问题,然后再从整体上设计算法,搭建程序的框架,最后一步步完善 细节,这样做,会使本来毫无头绪的问题变得清晰起来。
if (a[ferryTimes][i] == a[ferryTimes][3]) {
农夫携物过河问题
农夫携物过河问题源程序:#include "iostream.h"#include "malloc.h"#define Max 10 //最大顶点数typedef struct //图顶点类型{int R,H,T,C;}Ding;typedef struct //图结点类型{int DingS; //顶点个数Ding DXL[Max]; //顶点向量int Juzhen[Max][Max];//图的邻接矩阵用于存储图的边,矩阵元素个数取决于顶点个数}Tu;int Biaozhi[Max]; //标志数组int Lujing[Max]; //存储路径数组void Chushihua(int A[]) //初始化标志数组函数{int i;for(i=0;i<Max;i++) //标志数组置0Biaozhi[i]=0;}int Chazhao(Tu *G,int R,int H,int T,int C)//查找顶点(R,L,Y,C)在顶点向量中的位置函数{int i;for(i=0;i<G->DingS;i++)if(G->DXL[i].R==R && G->DXL[i].H==H && G->DXL[i].T==T && G->DXL[i].C==C) return(i); //存在则返回当前位置return (-1); //没有找到此顶点}int Anquan(int R,int H,int T,int C)//判断目前的(R,L,Y,C)是否安全函数{if(R!=T && (H==T||T==C))return (0);//农夫与羊不在一起且狼与羊或羊与白菜在一起时不安全,返回0elsereturn (1); //安全时返回1}int Guohe(Tu *G,int i,int j)//判断状态i与状态j之间是否可交换函数{int k=0;if(G->DXL[i].H!=G->DXL[j].H)k++;if(G->DXL[i].T!=G->DXL[j].T)k++;if(G->DXL[i].C!=G->DXL[j].C)k++;if(G->DXL[i].R!=G->DXL[j].R && k<=1)//以上三个条件不同时满足两个且农夫状态改变时可交换,即农夫每次只能带一件东西过河 return(1); //可交换时elsereturn(0); //不可交换时}Tu *Shengcheng(Tu *G) //生成图的邻接矩阵及顶点向量函数{int i,j,R,H,T,C;i=0;for(R=0;R<=1;R++) //生成所有安全的图的顶点for(H=0;H<=1;H++)for(T=0;T<=1;T++)for(C=0;C<=1;C++)if(Anquan(R,H,T,C)){G->DXL[i].R=R;G->DXL[i].H=H;G->DXL[i].T=T;G->DXL[i].C=C;i++;}G->DingS=i; //为图顶点数目赋值for(i=0;i<G->DingS;i++) //初始化邻接矩阵for(j=0;j<G->DingS;j++)if(Guohe(G,i,j))G->Juzhen[i][j]=G->Juzhen[j][i]=1; //i与j可转化初始化为1elseG->Juzhen[i][j]=G->Juzhen[j][i]=0; //i与j不可转化初始化为0return G;}void Bianli(Tu *G,int u,int v)//用深度优先遍历搜索从u到v的简单路径函数{int j,k=0;Biaozhi[u]=1; //标记已访问过的顶点for(j=0;j<G->DingS;j++)if(G->Juzhen[u][j] && !Biaozhi[j] && !Biaozhi[v]){Lujing[u]=j; //存储路径Bianli(G,j,v); //递归遍历以后的结点 }}void ShuchuWL(Tu *G,int k,int l)//用文字描述每一步骤的含义函数{switch(k) //k为顶点向量编号{ //不同编号的文字含义case 0: cout<<"人狐兔菜都在本岸!"<<endl; break;case 1: if(l==6){ cout<<"人带兔回本岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 2: if(l==5){ cout<<"人空手回本岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 3: if(l==8){ cout<<"人带兔回本岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 4: if(l==7){ cout<<"人空手回本岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 5: if(l==0){ cout<<"人带兔到对岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 6: if(l==2){ cout<<"人带菜到对岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 7: if(!G->DXL[l].H) //在该路径中菜被带到对岸{ cout<<"人带狐到对岸!"<<endl; break;} if(!G->DXL[l].C) //在该路径中狐被带到对岸{ cout<<"人带菜到对岸!"<<endl; break;}case 8: if(l==2){ cout<<"人带狐到对岸!"<<endl; break;} else{ cout<<"路径错误!"<<endl; break;}case 9: if(l==4){ cout<<"人带兔到对岸!"<<endl;cout<<"恭喜您已过河完毕!"<<endl<<endl;break;} else{ cout<<"路径错误!"<<endl; break;}}}void Shuchu(Tu *G,int u,int v)//用顶点向量描述过河路径函数{int k,l;k=u;l=u;cout<<"路径为:"<<endl; //输出找到的路径while(k!=v){ShuchuWL(G,k,l); //用文字表述l=k; //用l记录路径中当前步骤的前一步骤 k=Lujing[k];}ShuchuWL(G,k,l); //用文字表述Chushihua(Biaozhi); //将标志数组置0,便于查找其他的路径}void Zaichazhao(Tu *G,int v) //再查找其他路径函数{int i=0,j;while(i<G->DingS){if(!Biaozhi[Lujing[i]]) //在没被访问过的结点中再查找i=i;for(j=Lujing[i]+1;j<G->DingS;j++)//查找当前结点的上一次邻接点以后的结点{if(G->Juzhen[i][j]!=0 && !Biaozhi[j] && !Biaozhi[v])//当前结点的上一次邻接点以后的结点存在时,从此进行深度遍历{Lujing[i]=j;Bianli(G,i,v);}else{Biaozhi[Lujing[i]]=1;i++;}//当前结点的上一次邻接点以后的结点不存在时,从下一结点再查找}}}void main() //主函数{int i,j;Tu *G;G=(Tu *)malloc(sizeof(Tu)); //申请空间G=Shengcheng(G); //生成邻接矩阵Chushihua(Biaozhi); //初始化标志矩阵i=Chazhao(G,0,0,0,0); //查找(0,0,0,0)的位置j=Chazhao(G,1,1,1,1); //查找(1,1,1,1)的位置Bianli(G,i,j); //查找i到j的路径if(Biaozhi[j])Shuchu(G,i,j); //输出路径Zaichazhao(G,j); //再查找其他路径 if(Biaozhi[j])Shuchu(G,i,j); //输出路径}。
农夫过河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;}实验结果:四、实验总结。
农夫过河c程序
#include<iostream.h>#define MaxNumVertices 10//最大顶点数typedef enum {FALSE,TRUE}Boolean;typedef struct//图的顶点类型{int Farmer,Wolf,Sheep,Veget;}VexType;typedef struct{int VertexNum,CurrentEdges;//图的当前顶点数和边数VexType VerticesList[MaxNumVertices];//顶点向量(代表顶点)int Edge[MaxNumVertices][MaxNumVertices];//邻接矩阵//用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关}AdjGraph;//定义图的邻接矩阵存储结构Boolean visited[MaxNumVertices];//对已访问的顶点进行标记(图的遍历)int path[MaxNumVertices];//保存DFS搜索到的路径,即与某顶点到下一顶点的路径int locate(AdjGraph *G,int F,int W,int S,int V)//查找顶点(F,W,S,V)在顶点向量中的位置{int i;for(i=0;i<G->VertexNum;i++){if(G->VerticesList[i].Farmer==F && G->VerticesList[i].Wolf==W &&G->VerticesList[i].Sheep==S && G->VerticesList[i].Veget==V)return(i);//返回当前位置}return (-1);//没有找到此顶点}int is_safe(int F,int W,int S,int V)//判断目前的(F,W,S,V)是否安全{if(F!=S && (W==S||S==V))return (0);//当农夫与羊不在一起时,狼与羊或羊与白菜在一起是不安全的else//否则安全return (1);//安全返回1}int is_connected(AdjGraph *G,int i,int j)//判断状态i与状态j之间是否可转换{int k=0;if(G->VerticesList[i].Wolf!=G->VerticesList[j].Wolf)k++;if(G->VerticesList[i].Sheep!=G->VerticesList[j].Sheep)k++;if(G->VerticesList[i].Veget!=G->VerticesList[j].Veget)k++;if(G->VerticesList[i].Farmer!=G->VerticesList[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->VerticesList[i].Farmer=F;G->VerticesList[i].Wolf=W;G->VerticesList[i].Sheep=S;G->VerticesList[i].Veget=V;i++;}G->VertexNum=i;for(i=0;i<G->VertexNum;i++)//邻接矩阵初始化即建立邻接矩阵for(j=0;j<G->VertexNum;j++)if(is_connected(G,i,j))G->Edge[i][j]=G->Edge[j][i]=1;//状态i与状态j之间可转化,初始化为1,否则为0elseG->Edge[i][j]=G->Edge[j][i]=0;return;}void print_path(AdjGraph *G,int u,int v)//输出从u到v的简单路径,即顶点序列中不重复出现的路径{int k;k=u;while(k!=v){cout<<"("<<G->VerticesList[k].Farmer<<","<<G->VerticesList[k].Wolf <<","<<G->VerticesList[k].Sheep<<","<<G->VerticesList[k].Veget<<")"; cout<<endl;k=path[k];}cout<<"("<<G->VerticesList[k].Farmer<<","<<G->VerticesList[k].Wolf <<","<<G->VerticesList[k].Sheep<<","<<G->VerticesList[k].Veget<<")"; cout<<endl;}void DFS_path(AdjGraph *G,int u,int v)//深度优先搜索从u到v的简单路径//DFS--Depth First Search{int j;visited[u]=TRUE;//标记已访问过的顶点for(j=0;j<G->VertexNum;j++)if(G->Edge[u][j] && !visited[j] && !visited[v]){path[u]=j;DFS_path(G,j,v);}}void main(){cout<<"农夫蔬菜兔子狐狸的位置变化依次为:"<<endl; int i,j;AdjGraph graph;CreateG(& graph);for(i=0;i<graph.VertexNum;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);return;}。
农夫过河问题(c++编写)(word文档良心出品)
1、问题描述从前,一个农夫带着一只狼,一只羊和一棵白菜要河(注意该狼被农夫训服了,但还会吃羊)。
他要将所有东西安全的带到河的对岸,不幸的是河边只有一条船,只能装下农夫和他的一样东西,并且农夫必须每次都随船过,因为只有他能撑船。
在无人看管的情况下,狼要吃羊,羊要吃白菜,因此,农夫不能在河的某边岸上单独留下狼和羊,也不能单独留下羊和白菜。
那么农夫如何才能使三样东西平安过河呢?2、需求分析1)、农夫必须把狼,羊,白菜全部都载过河,且一次只能载一个;2)、要求狼和羊不能单独在一起,羊和白菜也不能单独在一起,即要么羊单独在河的一边,要么羊和农夫在一起。
3、系统概述设计对于上述情况,可以将河的两岸抽象成成数学问题,即将河的本岸抽象成数字‘0’,将对岸抽象成‘1’;且将狼,羊,白菜,农夫,分别抽象成数字‘0’,‘1’,‘2’,‘3’。
而用数组a[i][j](取值只能为0和1)表示第i次运载是,j (j=0,1,2,3。
分别表示狼,羊,白菜,农夫)所在的位置。
而用b[i]表示第i 次运载时船上运载的东西(因为农夫每次都必须在船上,所以不用记录,除非穿上只有农夫一人)。
如此一来,是否全部过河的问题就转化为判断a[i][0],a[i][1],a[i][2],a[i][3]是否全为1了,即相加之和是否为4的问题了;而四者中的两者是否能在一起的问题就转化它们各自的a[i][j]是否相等的问题了。
4、系统详细设计创建一个数组a[MAXTIMES][4]用于存放农夫,狼,羊,白菜的位置,用0表示本岸,1表示对岸;b[MAXTIMES]用于存放狼,羊,白菜,农夫的编号; 0: 狼,1:羊,2:白菜,3:农夫;编写一个递归函数Ferry(int ferryTimes),其中ferryTimes为渡河次数,在函数中,应考虑3个问题:1)、用a[ferryTimes][0] + a[ferryTimes][1] + a[ferryTimes][2] + a[ferryTimes][3] == 4语句判断是否全部到达对岸,如果是,则直接输出结果,否则,考虑第二个问题;2)、狼和羊是否单独在一起,羊和白菜是否单独在一起,用语句a[ferryTimes][1] != a[ferryTimes][3] && (a[ferryTimes][2] == a[ferryTimes][1] || a[ferryTimes][0] == a[ferryTimes][1])来实现;3)、如果上两个条件都不满,则可执行运输的动作,但每次都应考虑,该运输情况以前是否执行过(即两岸以及船上的东西以及各自位置和以前完全相同),如果没被执行过,则可以保存此时四者各自的状态,并递归的进行下一次运载。
宽搜农夫过河问题
农夫过河问题宽搜(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)之间的数。
农夫过河问题
/*这道题要用c语言解决农夫带狼、白菜、羊过河的经典问题,*用到了队列及广度优先的算法,并且用到了一些位操作……*还把问题的描述转换成了数学模型,用数学符号表示问题的解*例如:15 (二进制1111)表示:农夫、狼、白菜、羊都在* 11 (二进制1011)表示:农夫、白菜、羊都在*详细的解释是在《算法与数据结构——c语言描述(第三版)》P112 *我在理解后多加了中文的操作描述,并输出*/#include <stdio.h>#include<stdlib.h>#include <malloc.h>typedef int DataType;struct Node;typedef struct Node *PNode;struct Node{DataType info;PNode link;};struct LinkQueue{PNode f;PNode r;};typedef LinkQueue * PLinkQueue;//链接队列类型的指针PLinkQueue creaEmptyQueue_link(void)//创建空队列{PLinkQueue plqu;plqu=(PLinkQueue) malloc(sizeof(struct LinkQueue));if(plqu != NULL){plqu ->f=NULL;//头元素的结点指针plqu ->r =NULL;//尾元素的结点指针}return plqu;}int isEmptyQueue_link(PLinkQueue plqu){return (plqu->f==NULL);}int enQueue_link(PLinkQueue plqu, DataType x)//入队操作{PNode p;p=(PNode)malloc(sizeof(struct Node));if(p == NULL) return 0;else{p->info=x;p->link=NULL;if(plqu->f == NULL)//插入前是空队列plqu->f=p;else plqu->r->link=p;plqu->r=p;//修改队尾指针return 1;}}int deQueue_link(PLinkQueue plqu)//出队操作{PNode p;if(plqu->f == NULL)return 0;else{p=plqu->f;plqu->f=p->link;free(p);}return 1;}DataType frontQueue_link(PLinkQueue plqu)//取出队列头部结点的数值{if(plqu->f == NULL)return -1;//注意这里返回的数值不严谨,请根据具体情况做出改变else return (plqu->f->info);}/*判断农夫、狼。
数据结构课程设计-农夫过河-实验报告.
一、需求分析描述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."将狼带回起始岸语句。
C语言-人狼羊菜问题-最容易看懂的解决方法及代码
C语⾔-⼈狼⽺菜问题-最容易看懂的解决⽅法及代码题⽬描述:农夫需要把狼、⽺、菜和⾃⼰运到河对岸去,只有农夫能够划船,⽽且船⽐较⼩,除农夫之外每次只能运⼀种东西,还有⼀个棘⼿问题,就是如果没有农夫看着,⽺会偷吃菜,狼会吃⽺。
请考虑⼀种⽅法,让农夫能够安全地安排这些东西和他⾃⼰过河。
想这个问题⼀连想了好⼏天,本⼈没有系统的学过算法,有些概念也不是很清楚,只因解决问题为⽬标。
尝试过图论解决,但⽤floyed算法只能算出最短路径值,如何输出过程,⼀直没想出好的解决⽅法。
然后看了下⾯这篇⽂章,尝试抛弃图论,⽤树的思想来解决这个问题。
建议阅读下⾯代码时,先看看这篇⽂章。
在写代码时,本⼈采⽤了上述⽂章中的思想,⼜借鉴了图论中存储结点的⼀些⽅法。
我觉得这样写应该⾮常容易看懂了。
具体思路见代码。
1 #include <stdio.h>2#define INF 99993//8个动作4char *action[8]={"农夫单独过河","农夫带狼过河","农夫带⽺过河","农夫带菜过河",5"农夫单独返回","农夫带狼返回","农夫带⽺返回","农夫带菜返回"};6//10种状态7char *state[10]={"⼈狼⽺菜","⼈狼⽺","⼈狼菜","⼈⽺菜","⼈⽺","狼菜","狼","⽺","菜","空"};89//状态转换规则:GA[i][j]=k 表⽰【状态i】可以通过【动作k】转换到【状态j】,GA[i][j]=INF表⽰不可直接转换10int GA[10][10]={INF,INF,INF,INF,INF, 2,INF,INF,INF,INF,11 INF,INF,INF,INF,INF,INF, 2, 1,INF,INF,12 INF,INF,INF,INF,INF, 0, 3,INF, 1,INF,13 INF,INF,INF,INF,INF,INF,INF, 3, 2,INF,14 INF,INF,INF,INF,INF,INF,INF, 0,INF, 2,156,INF, 4,INF,INF,INF,INF,INF,INF,INF,16 INF, 6, 7,INF,INF,INF,INF,INF,INF,INF,17 INF, 5,INF, 7, 4,INF,INF,INF,INF,INF,18 INF,INF, 5, 6,INF,INF,INF,INF,INF,INF,19 INF,INF,INF,INF, 6,INF,INF,INF,INF,INF};2021//记录每⼀步的动作22int record_action[20];23//记录每⼀步动作后的状态24int record_state[20];2526//搜索从第step步开始、第i个结点到第n个结点的过程(step从0算起)27void search(int i,int n,int step)28 {29int k;//动作30int j;//可能要转换到的状态31if(i==n)32 {33for(k=0;k<step;k++)34 printf("step %d: %s,左岸还剩 %s\n",k+1,action[record_action[k]],state[record_state[k]]);35 printf("step count:%d\n\n",step);36return;37 }38//查找在当前【状态i】下能转换到的【其它状态j】,并且【状态j】不能在之前出现过39//查找时可能会出现多个 j,所以这是⼀个多叉树40for(k=0;k<8;k++)41 {42for(j=0;j<10;j++)43if(GA[i][j]!=INF&&GA[i][j]==k)//判断状态i能否通过动作k转换到状态j44 {45int m;46//下⾯这个循环是判断状态j在之前是否出现过47for(m=0;m<step;m++)48if(j==record_state[m])break;49if(m<step)continue;50//如果j满⾜前⾯所有条件,则记录这⼀步51 record_action[step]=k; //第step步所使⽤的动作52 record_state[step]=j; //第step步所转换的状态53 search(j,n,step+1); //继续搜索下⼀步54 }55 }5657 }58int main()59 {60 search(0,9,0);61return0;62 }。
C++基于人工智能搜索策略解决农夫过河问题示例
C++基于⼈⼯智能搜索策略解决农夫过河问题⽰例本⽂实例讲述了C++基于⼈⼯智能搜索策略解决农夫过河问题。
分享给⼤家供⼤家参考,具体如下:问题描述⼀农夫带着⼀头狼,⼀只⽺和⼀个⽩菜过河,⼩船只能⼀次装载农夫和⼀样货物,狼会吃⽺,⽺会吃⽩菜,只有农夫在时才安全。
现欲让所有物品包括农夫都安全过道河对岸,求最佳答案。
状态空间⽤16*4的矩阵:a[16][4],存放每⼀步的状态,第⼀列表⽰农夫的状态,第⼆列表⽰菜的状态,第三列表⽰⽺的状态,第四列表⽰狐狸的状态,数组a⾥⾯的元素只为0或1,0代表在左岸,1代表在右岸。
初始状态a[0][0]=a[0][1]=a[0][2]=a[0][3]=0,⽬标状态是矩阵的某⼀⾏全为1。
操作规则1. 农夫做往返运动,即第i步中,a[i][0] = i%2。
2. 每次农夫过河,可以选择带⼀件货物,也可以选择不带。
3. 在农夫不在场的情况下,狼和⽺不能在⼀起,⽺和⽩菜不能在⼀起。
搜索策略为了避免重复,我们将搜索过的状态放到set中,之后避开搜索这个状态即可。
我们使⽤深度优先搜索。
搜索过程为:农夫做往返运动,当农夫从左岸到右岸时,优先选择带货物过河,当农夫从右岸到左岸时,优先选择不带货物过河。
做出选择之后,前进⼀步,看看是否达到⽬标状态,如果没有达到,则农夫继续往返,知道搜索到⽬标状态,或者找不到解为⽌。
C++代码实现#include <iostream>#include <cstring>#include <string>#include <set>using namespace std;void search(int i);int a[16][4];set<int> s;int b[16];string ss[2];string t[4];int k;int level;int count1(int a[])//将当前状态转化为10进制数{return a[0]*8+a[1]*4+a[2]*2+a[3];}void show(int a[])//显⽰结果函数{cout<<" 左边:";for(int i=1;i<=3;i++)if(a[i]==0)cout<<t[i]<<" ";cout<<" ";cout<<"右边:";for(int i=1;i<=3;i++)if(a[i]==1)cout<<t[i]<<" ";cout<<endl<<endl;}void bringSomething(int i)//假设农夫会带⾛某个东西{for(int j=1;j<=3;j++){if(a[i][j]==a[i][0])//若j原来和农夫同⼀个位置,则农夫有可能将j带⾛。
c语言课课程设计农夫过河
c语言课课程设计农夫过河一、教学目标本章节的教学目标旨在让学生掌握C语言的基本语法和编程思想,通过“农夫过河”的案例,培养学生解决实际问题的能力。
具体目标如下:1.知识目标:学生能理解C语言的基本数据类型、运算符、控制结构等语法知识。
2.技能目标:学生能运用C语言编写简单的程序,解决实际问题。
3.情感态度价值观目标:培养学生热爱编程,勇于探索,积极解决问题的精神。
二、教学内容本章节的教学内容以“农夫过河”案例为主线,贯穿C语言的基本语法和编程思想。
教学大纲如下:1.C语言简介:介绍C语言的历史、特点和应用领域。
2.基本数据类型和运算符:讲解整型、浮点型、字符型数据及其运算符。
3.控制结构:讲解顺序结构、分支结构、循环结构。
4.函数:讲解函数的定义、声明和调用。
5.数组和指针:讲解一维、二维数组以及指针的概念和应用。
6.农夫过河案例:利用所学知识编写程序,解决农夫过河问题。
三、教学方法本章节采用多种教学方法,以激发学生的学习兴趣和主动性:1.讲授法:讲解C语言的基本语法和编程思想。
2.案例分析法:通过分析“农夫过河”案例,引导学生运用所学知识解决问题。
3.实验法:让学生动手编写程序,加深对知识的理解和运用。
4.讨论法:分组讨论,培养学生的团队协作能力和沟通能力。
四、教学资源为了支持教学内容和教学方法的实施,丰富学生的学习体验,我们将提供以下教学资源:1.教材:《C语言程序设计》2.参考书:《C语言 Primer》3.多媒体资料:教学PPT、视频教程4.实验设备:计算机、编程环境5.在线资源:编程论坛、开源项目、在线教程等。
五、教学评估本章节的教学评估将采取多元化方式,以全面、客观、公正地评估学生的学习成果。
评估方式包括:1.平时表现:考察学生在课堂上的参与度、提问回答、团队协作等情况。
2.作业:布置课后编程作业,检查学生对知识的掌握和运用能力。
3.考试:期末进行C语言编程考试,检验学生的综合运用能力。
农夫过河2(c语言)
农夫过河2(c语言)// farmerProblem.c// 用队列解决农夫过河问题#include#includetypedef 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)// 在队尾插入元素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){//判断农夫的位置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){// 若状态安全则返回trueif ((goat(location) == cabbage(location)) && (goat(location) != farmer(location)))return (0);// 羊吃白菜if ((goat(location) == wolf(location)) && (goat(location) != farmer (location)))return (0);// 狼吃羊return (1); // 其他状态是安全的}main(){int i, movers, location, newlocation;int route[16]; //用于记录已考虑的状态路径PSeqQueue moveT o; //用于记录可以安全到达的中间状态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); //计算新状态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]) {printf("The location is : %d/n", location);if (location == 0)exit(0);}}elseprintf("No solution./n");//问题无解}。
基于C++的农夫过河问题算法设计与实现方法
基于C++的农夫过河问题算法设计与实现⽅法本⽂实例讲述了基于C++的农夫过河问题算法设计与实现⽅法。
分享给⼤家供⼤家参考,具体如下:问题描述:⼀个农夫带着—只狼、⼀只⽺和—棵⽩菜,⾝处河的南岸。
他要把这些东西全部运到北岸。
他⾯前只有⼀条⼩船,船只能容下他和—件物品,另外只有农夫才能撑船。
如果农夫在场,则狼不能吃⽺,⽺不能吃⽩菜,否则狼会吃⽺,⽺会吃⽩菜,所以农夫不能留下⽺和⽩菜⾃⼰离开,也不能留下狼和⽺⾃⼰离开,⽽狼不吃⽩菜。
请求出农夫将所有的东西运过河的⽅案。
实现上述求解的搜索过程可以采⽤两种不同的策略:⼀种⼴度优先搜索,另⼀种深度优先搜索。
这⾥介绍在⼴度优先搜索⽅法中采⽤的数据结构设计。
程序源码:/************************************************ 农夫过河问题(P64 队列的应⽤)* 约定:⽤四位⼆进制数分别顺序表⽰农夫、狼、⽩菜和⽺的状态* 即:{dddd} <=> {Farmer, Wolf, Cabbage, Goat} 其中:d={0,1}* 说明:0表⽰在东岸 1表⽰在西岸,初始状态为0000,终⽌状态为1111************************************************/#include<stdio.h>#include<stdlib.h>#define MAXSIZE 16typedef int EntryType;typedef struct queue{EntryType data[MAXSIZE];int front,rear; //front队头,rear队尾}SeqQueue, * SeqQueuePtr;// 创建空队列SeqQueuePtr create_sequeue(void){SeqQueuePtr pque;pque = (SeqQueuePtr)malloc(sizeof(SeqQueue));if(pque){pque->front = 0;pque->rear = 0;}else{printf("Error: malloc() failed, out of memory!\n");}return(pque);}int is_queEmpty(SeqQueuePtr pque){return( pque->front == pque->rear );}int is_queFull(SeqQueuePtr pque){return( (pque->rear+1)%MAXSIZE == pque->front);}// ⼊队int enqueue(SeqQueuePtr pque, EntryType x){if(is_queFull(pque)){printf("Queue Overflow Error: trying to add an element onto a full queue\n");return 1;}else{pque->data[pque->rear] = x;pque->rear = (pque->rear + 1) % MAXSIZE;return 0;}}// 队⾸元素出队(返回0表⽰出队异常,出队操作前队列为空)int dequeue(SeqQueuePtr pque, EntryType * e){if(is_queEmpty(pque)){printf("Empty Queue.\n");return 0;}else{*e = pque->data[pque->front];pque->front = (pque->front + 1) % MAXSIZE;return 1;}}int is_farmer_crossed(int state){return ((state & 0x08) != 0);}int is_wolf_crossed(int state){return ((state & 0x04) != 0);}int is_cabbage_crossed(int state){return ((state & 0x02) != 0);}int is_goat_crossed(int state){return ((state & 0x01) != 0);}// 若状态相容(安全)则返回1,否则返回0int is_safe(int state){if((is_goat_crossed(state) == is_cabbage_crossed(state)) &&(is_goat_crossed(state) != is_farmer_crossed(state))) // ⽺菜同岸且农夫不在场return(0);if((is_goat_crossed(state) == is_wolf_crossed(state)) &&(is_goat_crossed(state) != is_farmer_crossed(state))) // 狼⽺同岸且农夫不在场return(0);return(1);}void river_crossing_problem(){int route[16]; // 记录已经考虑过的状态int state; // 记录当前时刻的状态(状态编号的⼆进制形式即状态本⾝)int aftercross; // 记录渔夫当前的选择(渡河对象)会导致的结果状态int passenger; // 临时变量,⽤于表达农夫的选择(对应⼆进制位为1表⽰选中该乘客)int results[16]={0}; // 输出结果int counter, i;SeqQueuePtr states_que; //states_que = create_sequeue(); // 创建“状态”队列enqueue(states_que,0x00); // 初始状态0000⼊队for(int i = 0; i < 16; i++){route[i] = -1;}//route[0] = 0;while(!is_queEmpty(states_que) && (route[15] == -1)){if( !dequeue(states_que, &state) ){printf("Error: dequeue() - the queue is empty\n");}// 依次考虑农夫可能的选择:携带⽺、⽩菜和狼,以及农夫只⾝渡河for( passenger = 1; passenger<= 8; passenger <<= 1 ){// 由于农夫总是在过河,随农夫过河的也只能是与农夫同侧的东西if(((state & 0x08) != 0) == ((state & passenger) != 0)){// 如果农夫与当前乘客在河岸的同⼀侧aftercross = state^( 0x08|passenger ); // 渡河后的情况if(is_safe(aftercross) && (route[aftercross] == -1)){// 如果渡河后状态安全,则将其状态⼊队route[aftercross] = state; // 将当前状态的索引记录到路径数组中(下标索引为后续状态值) enqueue(states_que, aftercross);}}}//end for()}//end while()// 输出过河策略:0表⽰在东岸 1表⽰在西岸,初始状态为0000,终⽌状态为1111if(route[15] != -1){//printf("The reverse path is:\n");counter = 0;for(state = 15; state != 0; state = route[state]){//printf("The state is: %d \n",state);results[counter] = state;counter++;//if(state == 0) return;}for(i = 0; i< counter; i++){state= results[i];aftercross = results[i+1];if(state & 0x08){printf("农夫从东岸到西岸:");}else{printf("农夫从西岸到东岸:");}switch(state^aftercross ){case 12:printf("把狼带过河\n");break;case 10:printf("把菜带过河\n");break;case 9:printf("把⽺带过河\n");break;default:printf("什么也不带\n");break;}}}else{printf("No solution for this problem.\n");}}int main(void){river_crossing_problem();system("pause");return 0;}运⾏结果:希望本⽂所述对⼤家C++程序设计有所帮助。
农夫过河
农夫过河#include <stdio.h>enum type {farmer=1,wolve,sheep,vegitable};void pass(int);void come(int);int main(){int thiss[]={1,2,3,4};int thats[]={0,0,0,0};int i,j,k,bk;int p,q,r;int temp;int n;int flag=thiss[0]+thiss[1]+thiss[2]+thiss[3];printf("%d ",flag);while (flag){for (i=1;i<4;i++){n=1;temp=thiss[i];thiss[i]=0;n++;for (j=1;j<4;j++){if (thiss[j]==sheep){for (k=1;k<4;k++)if (thiss[k]==wolve||thiss[k]==vegitable){n--;break;}if (n<2)break;}}if (n==2){thiss[0]=0;pass(temp);for (p=0;p<3;p++)if (thats[p]==0){thats[p]=temp;thats[3]=1;break;}break;}else{thiss[i]=temp;}} //travel riverfor (q=0;q<3;q++){if (thats[q]==sheep){for (r=0;r<3;r++)if (thats[r]==wolve||thats[r]==vegitable){for (bk=1;bk<4;bk++)if (thiss[bk]==0){//thiss[0]=1;thiss[bk]=thats[q];thiss[0]=1;come(thats[q]);thats[q]=0;thats[3]=0;break;}break;}break;}}if (r>=3||q >=3){thiss[0]=1;thats[3]=0;come(1);}flag=thiss[0]+thiss[1]+thiss[2]+thiss[3];if(flag==1){pass(1);break;}}printf("%d\n",p);return 0;}void pass(int c){switch(c){case 2:puts("farmer and wolve pass ");break;case 3:puts("farmer and sheep pass ");break;case 4:puts("farmer and vegitable pass ");break;default:puts("framer come only");break;}}void come(int c){switch (c){case 1:puts("farmer come only");case 2:puts("farmer and wolve come ");break;case 3:puts("farmer and sheep come ");break;case 4:puts("farmer and vegitable come ");break;}}。
农夫过河问题的求解
实验报告4题目:编制一个演示农夫过河问题的求解的程序班级:生物信息10级(1)姓名:李沙沙学号:2010446013 完成日期:2012.01一、需求分析1.本演示程序中,是解决农夫、狼、羊和白菜过河问题。
一个农夫带着一只狼,一只羊和一些菜过河,河边只有一条木船,由于船太小,只能装下农夫和他的一样东西,在无人看管的情况下。
狼要吃羊,羊要吃菜,请问农夫如何菜能使三样东西平安过河?2.演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令;相应的输入数据(滤去输入中的非法字符)和运算结果显示在其后。
3.程序执行的命令包括:1)构造集合1;2)构造集合2;3)求并集;4)求交集;5)求差集;6)结束。
“构造集合1”和“构造集合2”时,需以字符串的形式键入集合元素。
4.测试数据(1)Set1=“magazine”,Set2=“paper”,Set1∪Set2=“aegimnprz”, Set1∩Set2=“ae”,Set1-Set2=“gimnz”;(2)Set1=“012oper4a5tion89”, Set2=“error data”,Set1∪Set2=“adeinoprt”, Set1∩Set2=“aeort”, Set1-Set2=“inp”。
二、程序的模块结构本程序包含四个模块:1)主程序模块:void main(){初始化;dc{接受命令;处理命令;}while(“命令”=“退出”);}2)集合单元模块――实现集合的抽象数据类型;3)有序表单元模块――实现有序表的抽象数据类型;4)结点结构单元模块――定义有序表的结点结构。
各模块之间的调用关系如下:主程序模块集合单元模块有序表单元模块结点结构单元模块三、祥细设计1.元素类型、结点类型和指针类型typedef char ElemType;//元素类型typedef struct NodeType {ElemType data;NodeType *LinkType; // 结点类型,指针类型Status MakeNode(LinkType &p, ElemType e){//分配由p指向的数据元素为e、后继为“空”的结点,并返回TRUE,//若分配失败,则返回FALSEp=(Link Type)malloc(sixeof(Node Type));if(!p)return FALSE;p->data=e;p->next=NULL; return TRUE;}void freeNode(LinkType &p){ //释放p所指结点}Link Type Copy(LinkType p){//复制生成和指针p所指结点有同值元素的新结点并返回,//若分配空间失败,则返回空指针。
C语言:顺序结构
} 19
• 程序应该具备良好的人机交互能力。 • 即输入输出都要直观,让用户看得懂。
课堂练习:先画出流程图,再写代码
从键盘中接收两个整数,分别存入整形变量a,b当中。 要求计算并打印(和、差、乘、商,分别存在变量w,x,y,z中再输出): (1)a与b的和; (2) a与b的差; (3) a与b的乘积; (4) a与b的商(假设b不为0,但考虑商可能有小数)。
名称 起止框
N-S图 成
立a=>ma x
a>b 不成立
b=>ma x
输入、输出框 处理框 判断框
流程
Y a>b N
图 a=>max
b=>max
流程线
伪代码例子:
(再次回顾)三种结构
• 计算机解决问题只有以下三种思路:
A
Y 条件P N
条件假P N
Y
B
A
B
A
顺序结构
选择结构
循环结构
编写C程序计算圆的周长
(1)打开冰箱门; (2)把大象推进冰箱; (3)关上冰箱门。
顺序结构
2. 小莉和小红今年都30岁,有很多男性追求者,请设计一个算法,帮 小莉和小红从众多追求者中,找到合适约会的结婚对象。
小莉家庭经济一般:如果总资产有500万以上或者是博士,见面;否则,不见。 小红家庭经济好,是外貌协会:如果长得高且帅,见面;否则,不见。
什么是算法
程序=算法+数据结构
1、算法的概念:为解决某一个问题而采取的方法和步骤。 2、算法的五大特性:
⑴有穷性:有限步骤内结束 ⑵确定性:不能产生歧义 ⑶可行性 ⑷0个或多个输入:从外界获取必要信息 ⑸1个或多个输出:算法必须有结果
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<iostream.h>
#define MaxNumV ertices 10 //最大顶点数
typedef enum {FALSE,TRUE}Boolean;
typedef struct //图的顶点类型
{
int Farmer,Wolf,Sheep,V eget;
}V exType;
typedef struct
{
int V ertexNum,CurrentEdges; //图的当前顶点数和边数
V exType V erticesList[MaxNumV ertices]; //顶点向量(代表顶点)
int Edge[MaxNumV ertices][MaxNumV ertices];//邻接矩阵
//用于存储图中的边,其矩阵元素个数取决于顶点个数,与边数无关}AdjGraph; //定义图的邻接矩阵存储结构
Boolean visited[MaxNumV ertices]; //对已访问的顶点进行标记(图的遍历)int path[MaxNumV ertices];
//保存DFS搜索到的路径,即与某顶点到下一顶点的路径
int locate(AdjGraph *G,int F,int W,int S,int V)
//查找顶点(F,W,S,V)在顶点向量中的位置
{
int i;
for(i=0;i<G->V ertexNum;i++){
if(G->V erticesList[i].Farmer==F && G->V erticesList[i].Wolf==W && G->V erticesList[i].Sheep==S && G->V erticesList[i].V eget==V)
return(i); //返回当前位置
}
return (-1); //没有找到此顶点
}
int is_safe(int F,int W,int S,int V)//判断目前的(F,W,S,V)是否安全
{
if(F!=S && (W==S||S==V))
return (0);
//当农夫与羊不在一起时,狼与羊或羊与白菜在一起是不安全的
else //否则安全
return (1); //安全返回1
}
int is_connected(AdjGraph *G,int i,int j)
//判断状态i与状态j之间是否可转换
{
int k=0;
if(G->V erticesList[i].Wolf!=G->V erticesList[j].Wolf)
k++;
if(G->V erticesList[i].Sheep!=G->V erticesList[j].Sheep)
k++;
if(G->V erticesList[i].V eget!=G->V erticesList[j].V eget)
k++;
if(G->V erticesList[i].Farmer!=G->V erticesList[j].Farmer && k<=1)
//以上三个条件不同时满足两个且农夫状态改变时,返回真
//也即农夫每次只能带一件东西过桥
return(1);
else
return(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->V erticesList[i].Farmer=F;
G->V erticesList[i].Wolf=W;
G->V erticesList[i].Sheep=S;
G->V erticesList[i].V eget=V;
i++;
}
G->V ertexNum=i;
for(i=0;i<G->V ertexNum;i++) //邻接矩阵初始化即建立邻接矩阵for(j=0;j<G->V ertexNum;j++)
if(is_connected(G,i,j))
G->Edge[i][j]=G->Edge[j][i]=1;
//状态i与状态j之间可转化,初始化为1,否则为0
else
G->Edge[i][j]=G->Edge[j][i]=0;
return;
}
void print_path(AdjGraph *G,int u,int v)
//输出从u到v的简单路径,即顶点序列中不重复出现的路径
{
int k;
k=u;
while(k!=v)
{
cout<<"("<<G->V erticesList[k].Farmer<<","<<G->V erticesList[k].Wolf <<","<<G->V erticesList[k].Sheep<<","<<G->V erticesList[k].V eget<<")";
cout<<endl;
k=path[k];
}
cout<<"("<<G->V erticesList[k].Farmer<<","<<G->V erticesList[k].Wolf <<","<<G->V erticesList[k].Sheep<<","<<G->V erticesList[k].V eget<<")";
cout<<endl;
}
void DFS_path(AdjGraph *G,int u,int v)
//深度优先搜索从u到v的简单路径
//DFS--Depth First Search
{
int j;
visited[u]=TRUE; //标记已访问过的顶点
for(j=0;j<G->V ertexNum;j++)
if(G->Edge[u][j] && !visited[j] && !visited[v])
{
path[u]=j;
DFS_path(G,j,v);
}
}
void main()
{
cout<<"农夫蔬菜兔子狐狸的位置变化依次为:"<<endl;
int i,j;
AdjGraph graph;
CreateG(& graph);
for(i=0;i<graph.V ertexNum;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);
return;
}。