农夫过河问题(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、要求:基本要求:1.要求利用C\C++语言来完成系统的设计;2.突出C语言的函数特征(以多个函数实现每一个子功能)或者C++语言面向对象的编程思想;3.画出功能模块图;4.进行简单界面设计,能够实现友好的交互;5.具有清晰的程序流程图和数据结构的详细定义;6.熟练掌握C语言或者C++语言的各种操作。
创新要求:在基本要求达到后,可进行创新设计,如系统用户功能控制,改进算法的实现,实现友好的人机交互等等三、问题描述和求解方法:1 、问题描述要求设计实现农夫过河问题(农夫带着一只狼,一只养,一棵白菜,一次只能带一个东西)如何安全过河。
2 、问题的解决方案:可以用栈与队列、深度优先搜索算法及广度优先搜索算法相应的原理去解决问题。
1)实现四个过河对象(农夫、白菜、羊和狼)的状态,可以用一个四位二进制数来表示,0表示未过河,1表示已经过河了。
2)过河的对象必须与农夫在河的同一侧,可以设计函数来判断。
3)防止状态往复,即农夫将一个东西带过去又带回来的情况发生,需将所有可能的状态进行标定。
4)可用深度优先搜索算法及广度优先搜索算法去解题。
四、解题过程1.分析程序的功能要求,划分程序功能模块。
2.画出系统流程图。
3.代码的编写。
定义数据结构和各个功能子函数。
4.程序的功能调试。
5.完成系统总结报告以及使用说明书五、进度安排此次课程设计时间为一周,分以下几个阶段完成:1.选题与搜集资料:每人选择一题,进行课程设计课题的资料搜集。
2.分析与概要设计:根据搜集的资料,进行程序功能与数据结构分析,并选择合适的数据结构、并在此基础上进行实现程序功能的算法设计。
数据结构实验-农夫过河问题
农夫过河问题一、实验目的掌握广度优先搜索策略,并用队列求解农夫过河问题二、实验内容问题描述:一农夫带着一只狼,一只羊和一颗白菜,身处河的南岸,他要把这些东西全部运到北岸,遗憾的是他只有一只小船,小船只能容下他和一件物品。
这里只能是农夫来撑船,同时因为狼吃羊、羊吃白菜、所以农夫不能留下羊和狼或羊和白菜在河的一边,而自己离开;好在狼属肉食动物,不吃白菜。
农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(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;}实验结果:四、实验总结。
农夫过河问题回溯法python实现
农夫过河问题是经典的逻辑谜题,在这个问题中,农夫需要把一只狼、一只羊和一棵白菜一起带过河。
然而,农夫只有一条小船,而且小船只能容纳农夫和另外一样东西。
而且,如果农夫不在场的话,狼会吃羊,羊会吃白菜。
所以农夫需要想办法把它们一一带过河,而且又不能让狼吃羊或者羊吃白菜。
这个问题看似简单,实际上需要一定的逻辑推理和计划安排才能成功通过。
回溯法是一种常用于解决这类问题的算法。
在计算机科学中,回溯法常常用于解决组合优化问题,它通过不断地尝试所有可能的步骤,直到找到解决方案为止。
在农夫过河问题中,回溯法可以帮助我们列举所有的可能方案,然后找出最优的解决方案。
下面我们将使用Python语言来实现农夫过河问题的回溯法解决方案。
1. 定义问题的状态空间在农夫过河问题中,我们可以定义每一种状态为(农夫位置, 狼位置, 羊位置, 白菜位置)。
其中,农夫位置、狼位置、羊位置和白菜位置均可取值为"左岸"或"右岸"。
(左岸, 左岸, 左岸, 左岸)代表所有的物品都在左岸,而农夫则准备过河。
2. 定义可行动作根据问题的描述,我们可以定义农夫可以采取的可行动作。
具体来说,农夫可以选择带一样东西过河,也可以选择不带东西过河。
我们可以定义可行动作为("不带东西过河"), ("狼过河"), ("羊过河"), ("白菜过河")。
3. 实现回溯法接下来,我们可以使用递归的方式来实现回溯法。
具体来说,我们可以定义一个递归函数backtrack(state, path),其中state表示当前的状态,path表示从起始状态到当前状态的路径。
在递归函数中,我们首先判断是否已经找到了解决方案,如果是,则输出路径并返回;否则,我们尝试所有可行的动作,递归地调用backtrack函数,直到找到解决方案为止。
4. 完整代码实现下面是使用Python语言实现农夫过河问题的回溯法解决方案的完整代码:```pythondef is_valid(state):if state[1] == state[2] and state[0] != state[1]:return Falseif state[2] == state[3] and state[0] != state[2]:return Falsereturn Truedef backtrack(state, path):if state == ('右岸', '右岸', '右岸', '右岸'):print(path)returnactions = [(0, 0), (1, 0), (0, 1), (1, 1)]for i in range(4):new_state = tuple((state[j] if j < 3 else '左岸' if state[j] == '右岸' else '右岸') for j in range(4))if 0 in actions[i] and is_valid(new_state):backtrack(new_state, path + [(actions[i], new_state)])elif is_valid(new_state) and is_valid(tuple([new_state[j] if j != k else state[j] for j in range(4) for k in range(3, 4)])):backtrack(new_state, path + [(actions[i], new_state)])if __name__ == "__m本人n__":initial_state = ('左岸', '左岸', '左岸', '左岸')backtrack(initial_state, [])```在上面的代码中,我们首先定义了一个辅助函数is_valid,该函数用于判断当前状态是否合法。
农夫过河问题
农夫过河问题
一、先分析农夫过河的情景:1.他走到了小桥上,遇见了大象;2.他看见小桥很窄,不能通过大象,于是下来,又看见了小兔子;3.小兔子让他再回去把自己带来的萝卜给小猴子送去;4.他想了想,就决定去找乌龟帮忙。
二、农夫为什么要这样做?我们可以用图中所示的几种方法来解答:(1)如果你是农夫,你会怎么办呢?(2)我们在学习时也常常有这样的问题,面对某个复杂的问题,总是从多角度考虑它,然后得出最佳的解决方案。
比如我们要学好数学,需要同学之间互相讨论交流,取长补短,共同进步。
三、根据刚才提供的信息和已经确立的条件,你认为哪些条件更重要?请写出两点理由并说明原因。
四、结合生活实际谈谈应该怎样正确处理人与人之间的关系。
数据结构课程设计-农夫过河-实验报告.
一、需求分析描述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."将狼带回起始岸语句。
农夫过河问题的求解
//从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");}。
农夫过河问题
农夫过河问题1. 题目描述:一个农夫带着一只狼,一只羊和一筐菜,欲从河的左岸坐船到右岸,由于船太小,农夫每次只能带一样东西过河,并且没有农夫看管的话,狼会吃掉羊,羊会吃菜。
设计一个方案,使农夫可以无损失的过河2. 题目分析:假设人、狼、菜、羊都在河岸a,要到b 河岸去。
题中的食物链关系为: 菜→羊→狼 所以,第一次人只能带羊到b 河岸; 回到a 时,人不能再将刚带过来的羊带回去,所以人是空手回到a 的; 在a 河岸,人有两个选择选择一:(1) 带狼到b,人再回到a 时,因为不能把狼和羊同时留下,所以只能带走羊;AA 羊 A B羊狼 菜 怎么办呢 B 羊 B 狼 菜 菜 狼(2) 再次回到a 后,人再到b 时,不能把羊和菜同时留下,所以只能带走菜; (3) 再次回到a 时,因为狼和菜可以同时留下,所以优先选择空手过河;到a 后发现只剩下羊,所以带羊过河。
选择二:(1) 带菜到b,人再回到a 时,因为不能把菜和羊同时留下,所以只能带走羊;(2) 再次回到a 后,人再到b 时,不能把羊和狼同时留下,所以只能带走狼;狼 羊 羊 A菜 B 羊 狼 A B 狼 AB 狼 AB 羊菜 菜 菜(3) 再次回到a 时,因为狼和菜可以同时留下,所以优先选择空手过河;到a 后发现只剩下羊,所以带羊过河。
解:用四元组S 表示状态,即S =(L ,J ,M ,N )其中L :农夫 J :狼 M :羊 N :菜用0表示在左岸岸,1表示在右岸,即S=(0,0,0,0) 目标G =(1,1,1,1)定义操作符L (i )表示农夫带东西到右岸:i=0 农夫自己到右岸;i=1 农夫带狼到右岸;i=2 农夫带羊到右岸;i=3 农夫带菜到右岸;定义操作符R (i )表示农夫带东西到左岸:i=0 农夫自己到左岸;i=1 农夫带狼到左岸;i=2 农夫带羊到左岸;i=3 农夫带菜到左岸;约束状态如下:(1,0,0,1)狼、羊在左岸;(1,1,0,0)羊、菜在左岸;(0,1,1,0)狼、羊在右岸;(0,0,1,1)羊、菜在右岸;(1,0,0,0)狼、羊、菜在左岸;(0,1,1,1)狼、羊、菜在右岸;羊 A B狼 菜。
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++过河问题是一个经典的编程问题,它涉及到如何使用C++编
程语言来解决一个具体的逻辑问题。
该问题通常涉及到一些具体的
规则和限制,玩家需要根据这些规则和限制来设计算法并编写代码
来解决问题。
通常来说,C++过河问题可以描述为,有一条河,河中间有一些
障碍物,玩家需要帮助一些人(或者动物)通过河流。
通常情况下,会有一些规则限制,比如每次只能让一定数量的人或者动物过河,
或者某些人或者动物之间有特定的关系需要考虑。
为了解决这个问题,首先需要分析问题的规则和限制,然后设
计一个合适的算法来解决问题。
通常情况下,可以使用递归、动态
规划或者其他算法来解决这类问题。
在C++中,可以利用类、函数、循环等编程语言特性来实现相应的算法。
在C++中,可以使用类来表示人或者动物,使用函数来模拟过
河的过程,使用循环来实现多次过河的操作。
需要考虑的因素包括
每次过河的合法性、过河的步骤、过河的最优方案等。
另外,需要注意的是,在实际编写代码的过程中,需要考虑边界条件、异常情况以及代码的可读性和可维护性。
可以使用合适的数据结构来存储和管理过河的状态,以及使用合适的算法来实现过河的逻辑。
总的来说,C++过河问题是一个典型的逻辑问题,需要结合C++编程语言的特性和算法设计来解决。
通过合理的分析和设计,可以编写出高效、健壮的C++代码来解决这类问题。
夫妻过河问题源码
function y=boat()m=input('输入夫妻对数: ');k=input('输入船的最大容量: ');for i=1:m+1A=[m,i-1];B{i}=A; %B表示可取状态endfor i=m+2:2*mA=[i-(m+1),i-(m+1)];B{i}=A;endfor i=2*m+1:3*m+1A=[0,i-(2*m+1)];B{i}=A;end%下面的for语句是根据参数k算出所有决策d,用C表示.t=1;for u=0:1:kfor v=0:1:kif u+v>=1&u+v<=kC{t}=[u,v];t=t+1;endendendD{1,1}=[m,m]; % D{1,1}表示初始状态.w=1; % w控制是否能够迭代成功.h=1; % h控制元素的个数.j=2; % j表示迭代的次数.x=0; % x是用来剔除掉不在允许状态集合中的元素.y=0; % y是防止重复剔除同一个元素.l=0; % l使用来标记元素是否被剔除.z(1)=0;z(2)=1; % z(j)表示上一步迭代后所剩下的所有元素.while w>0% p表示可以进行下一步迭代的所有元素.for p=z(j-1)+1:z(j)% q表示每一个元素要经过k*(k+3)/2种决策迭代.for q=1:k*(k+3)/2D{h+1,j}=D{p,j-1}+(-1)^(j-1).*C{q};h=h+1;l=1;%下面的for语句是核查迭代结果是否在允许状态集合B中.for e=1:3*m+1if D{h,j}==B{e}x=1;break;endendif x==0h=h-1;y=1;l=0;end%下面的if语句是剔除掉本次迭代过程中出现的重复元素. if j>2&y==0for i=z(j)+1:h-1if D{h,j}==D{i,j};h=h-1;l=0;break;endendend%下面的if语句是剔除掉以前重复的元素.if j>2&y==0if j==3for i=z(1)+1:z(2)if D{h,j}==D{i,j-2}h=h-1;l=0;break;endendelsefor i=z(j-2)+1:z(j-1)if D{h,j}==D{i,j-2}h=h-1;l=0;break;endendendendif l==1for g=1:j-1D{h,g}=D{p,g};endendif l==1&D{h,j}==[0,0]w=-1;%w=-1表示可以在有限的步骤下安全过河.break;endx=0;y=0;l=0;endif w==-1;%w=-1表示可以在有限的步骤下安全过河.break;endendj=j+1;z(j)=h;if z(j)==z(j-1)w=-2;%w=-2表示不可以在有限的步骤下安全过河.break;endendif w==-1for g=1:j-1D{h,g}endendif w==-2disp('不能按规定过河');end。
农夫过河C语言课程设计
农夫过河C语言课程设计一、教学目标本课程的学习目标包括以下三个方面:1.知识目标:学生需要掌握C语言的基本语法、数据类型、运算符、控制结构、函数等核心知识,理解C语言的编程思想和方法,能够独立编写简单的C语言程序。
2.技能目标:学生能够熟练使用C语言编程工具,掌握代码的调试和运行方法,具备自主学习和解决问题的能力。
3.情感态度价值观目标:培养学生对计算机科学的兴趣和热情,提高学生逻辑思维和抽象思维能力,培养学生良好的编程习惯和团队合作精神。
二、教学内容本课程的教学内容主要包括以下几个部分:1.C语言基本语法:数据类型、变量、常量、运算符、表达式等。
2.控制结构:顺序结构、分支结构、循环结构等。
3.函数:函数的定义、调用、参数传递、返回值等。
4.数组和字符串:一维数组、多维数组、字符串的基本操作等。
5.指针:指针的概念、指针的运算、指针与数组、指针与函数等。
6.结构体和联合体:结构体的定义、使用、联合体的定义和使用等。
7.文件操作:文件的打开、关闭、读写等基本操作。
三、教学方法本课程采用多种教学方法,以激发学生的学习兴趣和主动性:1.讲授法:教师讲解C语言的基本语法、概念和原理,引导学生理解并掌握相关知识。
2.案例分析法:通过分析实际案例,让学生了解C语言在实际编程中的应用,提高学生的编程能力。
3.实验法:学生动手编写C语言程序,进行调试和运行,培养学生的实际编程能力。
4.讨论法:学生分组讨论问题,共同解决问题,培养学生的团队合作精神和沟通能力。
四、教学资源本课程所需的教学资源包括:1.教材:《C程序设计语言》(K&R)或《C语言程序设计》(谭浩强)。
2.参考书:《C Primer Plus》、《C和指针》等。
3.多媒体资料:课件、教学视频、编程实例等。
4.实验设备:计算机、编程环境(如Visual Studio、Code::Blocks等)。
5.在线资源:编程、论坛、博客等,供学生自主学习和交流。
农夫过河问题算法设计与实现
农夫过河问题算法设计与实现咱来唠唠农夫过河这个有趣的问题。
一、问题描述农夫要带着一只狼、一只羊和一棵白菜过河。
但是呢,船很小,每次农夫只能带一样东西过河。
而且啊,如果农夫不在,狼会吃羊,羊会吃白菜,这可就麻烦大了。
二、算法设计思路1. 初始状态- 河这边有农夫、狼、羊和白菜,河对岸啥都没有。
2. 第一步很关键- 农夫肯定不能先带狼或者白菜,为啥呢?因为如果先带狼过去,把羊和白菜留在这边,羊就会吃白菜;要是先带白菜过去,狼就会吃羊。
所以农夫得先带羊过河。
- 然后农夫自己返回。
这时候河这边有狼和白菜,河对岸有羊。
3. 第二步- 农夫再带狼或者白菜过河。
假设农夫带狼过河吧。
- 但是农夫不能把羊单独留在对岸啊,所以农夫得把羊再带回来。
这时候河这边有羊和白菜,河对岸有狼。
4. 第三步- 农夫把羊放下,带白菜过河。
- 然后农夫自己返回。
这时候河这边有羊,河对岸有狼和白菜。
5. 最后一步- 农夫再带羊过河,这样就都安全地到对岸啦。
三、算法实现(用简单的文字描述过程)1. 开始:- 农夫在起始岸,物品(狼、羊、白菜)也在起始岸,对岸为空。
2. 第一次过河:- 农夫带羊过河,此时起始岸有狼和白菜,对岸有羊和农夫。
- 农夫独自返回起始岸,此时起始岸有农夫、狼、白菜,对岸有羊。
3. 第二次过河:- 农夫带狼过河,此时起始岸有白菜,对岸有狼、羊和农夫。
- 农夫带羊返回起始岸,此时起始岸有农夫、羊、白菜,对岸有狼。
4. 第三次过河:- 农夫带白菜过河,此时起始岸有羊,对岸有狼、白菜和农夫。
- 农夫独自返回起始岸,此时起始岸有农夫、羊,对岸有狼、白菜。
5. 第四次过河:- 农夫带羊过河,此时起始岸为空,对岸有农夫、狼、羊、白菜,大功告成!你看,这样一步一步的,就像走迷宫一样,按照规则走,就能让农夫带着他的东西安全过河啦。
农夫过河c语言详细
一、问题需求分析一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。
他要把这些东西全部运到北岸。
问题是他面前只有一条小船,船小到只能容下他和一件物品,另外只有农夫能撑船。
另外,因为狼能吃羊,而羊爱吃白菜,所以农夫不能留下羊和白菜或者狼和羊单独在河的一边,自己离开。
请问农夫该采取什么方案才能将所有的东西运过河呢?二、算法选择求解这个问题的最简单的方法是一步一步进行试探,每一步都搜索所有可能的选择,对前一步合适的选择再考虑下一步的各种方案。
用计算机实现上述求解的搜索过程可以采用两种不同的策略:一种是广度优先(breadth_first) 搜索,另一种是深度优先(depth_first) 。
广度优先:u 广度优先的含义就是在搜索过程中总是首先搜索下面一步的所有可能状态,然后再进一步考虑更后面的各种情况。
u 要实现广度优先搜索,一般都采用队列作为辅助结构。
把下一步所有可能达到的状态都列举出来,放在这个队列中,然后顺序取出来分别进行处理,处理过程中把再下一步的状态放在队列里……。
u 由于队列的操作遵循先进先出的原则,在这个处理过程中,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。
三、算法的精化要模拟农夫过河问题,首先需要选择一个对问题中每个角色的位置进行描述的方法。
一个很方便的办法是用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。
例如用0表示农夫或者某东西在河的南岸,1表示在河的北岸。
因此整数5(其二进制表示为0101) 表示农夫和白菜在河的南岸,而狼和羊在北岸。
四、算法的实现完成了上面的准备工作,现在的问题变成:从初始状态二进制0000(全部在河的南岸) 出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸) 为最终目标,并且在序列中的每一个状态都可以从前一状态通过农夫(可以带一样东西)划船过河的动作到达。
为避免不必要的瞎费功夫,要求在序列中不应该出现重复的状态。
农夫过河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;}。
小学趣味数学:农夫过河
小学趣味数学:农夫过河
◆您现在正在阅读的小学趣味数学:农夫过河文章内容由收集!本站将为您提供更多的精品教学资源!小学趣味数学:农夫过河从前,一个农夫带了一只狗,一只兔子和一棵青菜,来到河边,他要把这三件东西带过河去。
那儿仅有一只很小的旧船,农夫最多只能带其中的一样东西上船,否则就有沉船的危险。
刚开始,他带了菜上船,回头一看,调皮的狗正在欺侮胆小的兔子。
他连忙把菜放在岸上,带着狗上船,但贪嘴的兔子又要吃鲜嫩的青菜,农夫只好又回来。
他坐在岸边,看着这三件东西,静静地思索了一番,终于想出了一个渡河的办法。
小朋友,你知道农夫是怎么做的吗?
答案分析
狗要咬兔子,兔子要吃青菜。
所以,关键是要在渡河的任何一个步骤中,把兔子和狗,兔子和青菜分开,才能免受损失。
农夫可以先带兔子到对岸,然后空手回来。
第二步,带狗到对岸,但把兔子带回来。
第三步,把兔子留下,带菜到对岸,空手回来。
最后,带兔子到对岸。
这样三件东西都带过河去了,一件也没有遭受损失。
精心整理,仅供学习参考。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
cout<<"\t 农夫使三样东西平安过河方法为:"<<endl<<endl;
Ferry(0);
}
for (i = 0; i < ferryTimes; i++) {
if (a[i][3] == 0) {
cout<<"\t\t\t 载"<<name[b[i]]<<"到对岸"<<endl; } else {
cout<<"\t\t\t 载"<<name[b[i]]<<"回本岸"<<endl; } } cout<<endl; return; } //狼单独和羊在一起以及羊和白菜单独在一起的情况 if (a[ferryTimes][1] != a[ferryTimes][3] && (a[ferryTimes][2] == a[ferryTimes][1] || a[ferryTimes][0] == a[ferryTimes][1])) { return; }
3)、如果上两个条件都不满,则可执行运输的动作,但每次都应考虑,该运 输情况以前是否执行过(即两岸以及船上的东西以及各自位置和以前完全相同),
如果没被执行过,则可以保存此时四者各自的状态,并递归的进行下一次运载。
5、系统测试
6、经验总结
解决实际问题时,应先分析实际问题,找出实际问题的所有约束条件, 然后对问题进行数学模型的抽象化,抓主要因素,省去一些不需要的因素,将其 抽象为数学问题,然后再从整体上设计算法,搭建程序的框架,最后一步步完善 细节,这样做,会使本来毫无头绪的问题变得清晰起来。
7、参考文献
《C++程序设计》 《数据结构》 《算法设计与分析》
程序代码如下: #include <iostream> #include <stdlib.h> #include <string.h> using namespace std; const int MAXTIMES = 20; int a[MAXTIMES][4];//存放农夫,狼,羊,白菜的位置,用 0 表示本岸,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 次运载时船上运载的东西(因为农夫每次都必须在船上,所以不用记录,除非穿 上只有农夫一人)。
1、问题描述
从前,一个农夫带着一只狼,一只羊和一棵白菜要河(注意该狼被农夫训服了,但还会 吃羊)。他要将所有东西安全的带到河的对岸,不幸的是河边只有一条船,只能装下农夫和 他的一样东西,并且农夫必须每次都随船过,因为只有他能撑船。在无人看管的情况下,狼 要吃羊,羊要吃白菜,因此,农夫不能在河的某边岸上单独留下狼和羊,也不能单独留下羊 和白菜。那么农夫如何才能使三样东西平安过河呢?
} } //若没有出现,则将运载后抵达另一岸的结果记录下来,并进行下一次运载 for (i = 0; i <= 3; i++) {
b[ferryTimes] = i; a[ferryTimes + 1][0] = a[ferryTimes][0]; a[ferryTimes + 1][1] = a[ferryTimes][1]; a[ferryTimes + 1][2] = a[ferryTimes][2]; a[ferryTimes + 1][3] = 1 - a[ferryTimes][3];
//用于判断此种情况在前 searchTimes 次运载过程中是否已经出现过,若出现过则不用 记录
for (i = 0; i < ferryTimes; i++) {
for(int j = 0; j < 4; j++) {
if(a[ferryTimes][j] != a[i][j]) {
break; } } if(j == 4) { return;
如此一来,是否全部过河的问题就转化为判断 a[i][0],a[i][1],a[i][2], a[i][3]是否全为 1 了,即相加之和是否为 4 的问题了;而四者中的两者是否能 在一起的问题就转化它们各自的 a[i][j]是否相等的问题了。
4、系统详细设计
创建一个数组 a[MAXTIMES][4]用于存放农夫,狼,羊,白菜的位置,用 0 表示本岸,1 表示对岸 ;
if (a[ferryTimes][i] == a[ferryTimes][3]) {
a[ferryTimes + 1][i] = a[ferryTimes + 1][3]; Ferry(ferryTimes + 1); } } }
void main()
{
cout<<"\n
****************************************************************************\n";
char *name[] = {"狼", "羊", "白菜", "农夫自己"}; int b[MAXTIMES]; //用于存放狼,羊,白菜,农夫的编号; 0: 狼,1:羊,2:白菜,3:农夫
void Ferry(int ferryTimes) //ferryTimes 为渡河次数 {
int i; if (a[ferryTimes][0] + a[ferryTimes][1] + a[ferryTimes][2] + a[ferryTimes][3] == 4) //都到达 对岸 {
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 语句判断是否全部到达对岸,如果是,则直接输出结果, 否则,考虑第二个问题;
cout<<" **
------------------------
**\n";
cout<<" **
|
农夫过河问题
|
**; **
------------------------
**\n";
cout<<"
****************************************************************************\n";