农夫过河问题状态空间表示

合集下载

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

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

数据结构课程设计报告(农夫过河)第一篇:数据结构课程设计报告(农夫过河)目录引言...................................................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.基本要求:(1)利用图的存储结构(2)图的搜索算法(3)求出农夫将所有的东西运过河的所有方案二、设计1. 设计思想(1)存储结构以邻接矩阵存储合理状态,用一个一维数组保存所有的方案;(2)主要算法基本思想人,狼,羊和白菜共有2的四次方16种状态(河岸的状态可由人的状态确定),去掉不允许出现的6种状态,10个状态对应矩阵的10个结点值,然后根据状态的连续改变初始化矩阵,接着就用递归的深度优先法搜索所有的路径,即求出过河的方案。

main2. 设计表示(1)函数调用关系图main→Judge→Initiate→DFS→Push→StackPop→Top→GetTop→printfpath→Ch(2)函数接口规格说明int Judge(int a,int b) //将16种状态通过a,b输入,去掉不允许的6种int GetTop(Path *path,int *m) //出栈int Push(Path *path,int m) //入栈int Top(Path *path ,int *m) //读出栈顶值void Initiate(AdjMGraph *G,int n)//邻接矩阵顶点数为n的邻接矩阵G的建立int DFS(AdjMGraph *G,Path *path,int x,int t) 图G中搜索的起始点为X,从t点开始搜索与x关联的顶点,搜索过的点入栈path。

int printfpath(Path *path) //复制出出栈path中所有值,用FA【】保存void Printf(AdjMGraph *G)//辅助:邻接矩阵输出,用于观察搜索的过程。

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

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

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

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

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

农夫过河

农夫过河

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

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

问题是他只有一条船,船小到只能容下他和一件物品,当然,船只有农夫能撑。

另外,因为狼能吃羊,而羊爱吃白菜,所以农夫不能留下羊和狼或者羊和白菜单独在河的一边,自己离开。

好在狼属于食肉动物,它不吃白菜。

请问农夫该采取什么方案,才能将所有的东西安全运过河呢?一、算法与数据结构的设计:要模拟农夫过河的问题,用四位二进制数顺序分别表示农夫、狼、白菜和羊的位置。

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

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

用整数location表示用上述方法描述的状态,函数返回值为真(1)表示所考察的人或物在河的北岸,否则在南岸。

二、算法的精化:用一个整数队列moveTo,把搜索过程中每一步所有可能达到的状态都保存起来。

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

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

route数组只需要使用16个元素。

Route的每一个元素初始化值均设置为-1,每当在队列加入一个新状态时,就把route中以该状态坐下标的元素的值改为达到这个状态的前一状态的下标值。

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

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

三、程序的实现:程序代码如下:#include<stdio.h>#include<malloc.h>#define MAXNUM 20typedef int DataType;struct SeqQueue /* 顺序队列类型定义*/{int f, r;DataType q[MAXNUM];};typedef struct SeqQueue *PSeqQueue; /* 顺序队列类型的指针类型*/PSeqQueue createEmptyQueue_seq(void){PSeqQueue paqu = (PSeqQueue)malloc(sizeof(struct SeqQueue));if (paqu == NULL)printf("Out of space!\n");elsepaqu->f = paqu->r = 0;return (paqu);}int isEmptyQueue_seq( PSeqQueue paqu ) /*判断paqu所指是否是空队列*/ {return paqu->f == paqu->r;}void enQueue_seq(PSeqQueue paqu, DataType x) /* 在队列中插入一元素x */ {if ((paqu->r + 1) % MAXNUM == paqu->f)printf("Full queue.\n");else{paqu->q[paqu->r] = x;paqu->r = (paqu->r + 1) % MAXNUM;}}void deQueue_seq(PSeqQueue paqu) /* 删除队列头部元素*/{if( paqu->f == paqu->r )printf( "Empty Queue.\n" );elsepaqu->f = (paqu->f + 1) % MAXNUM;}DataType frontQueue_seq( PSeqQueue paqu ) /* 对非空队列,求队列头部元素*/ {return (paqu->q[paqu->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) /* 若状态安全则返回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;int route[16]; /*记录已考虑的状态路径*/PSeqQueue moveTo;moveTo = createEmptyQueue_seq( );enQueue_seq(moveTo, 0x00);for (i = 0; i < 16; i++) route[i] = -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){printf("The reverse path is : \n");for(location = 15; location >= 0; location = route[location]){printf("The location is : %d\n",location);if (location == 0) return;}}elseprintf("No solution.\n");}int main() /*主函数*/{farmerProblem();return 0;}四、程序运行结果如下:The reverse path is :The location is :15The location is :6The location is :14The location is :2The location is :11The location is :1The location is :9The location is :0结果分析:从初始状态0到最后状态15的动作序列为:1.初始全部在南岸(0000),2农夫把羊带到北岸(1001),3.农夫独自回到南岸(0001),4.农夫把白菜带到北岸(1011),5.农夫带着羊回到南岸(0010),6.农夫把狼带到北岸(1110),7.农夫独自回到南岸(0110),8.农夫把羊带到北岸(1111)程序运行最后location结果为15(二进制为1111),即农夫和其他东西都安全运过了北岸。

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

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

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

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

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

人工智能课后习题第4章 参考答案

人工智能课后习题第4章 参考答案

第4章搜索策略参考答案4.5 有一农夫带一条狼,一只羊和一框青菜与从河的左岸乘船倒右岸,但受到下列条件的限制:(1) 船太小,农夫每次只能带一样东西过河;(2)如果没有农夫看管,则狼要吃羊,羊要吃菜。

请设计一个过河方案,使得农夫、浪、羊都能不受损失的过河,画出相应的状态空间图。

题示:(1) 用四元组(农夫,狼,羊,菜)表示状态,其中每个元素都为0或1,用0表示在左岸,用1表示在右岸。

(2) 把每次过河的一种安排作为一种操作,每次过河都必须有农夫,因为只有他可以划船。

解:第一步,定义问题的描述形式用四元组S=(f,w,s,v)表示问题状态,其中,f,w,s和v分别表示农夫,狼,羊和青菜是否在左岸,它们都可以取1或0,取1表示在左岸,取0表示在右岸。

第二步,用所定义的问题状态表示方式,把所有可能的问题状态表示出来,包括问题的初始状态和目标状态。

由于状态变量有4个,每个状态变量都有2种取值,因此有以下16种可能的状态:S0=(1,1,1,1),S1=(1,1,1,0),S2=(1,1,0,1),S3=(1,1,0,0)S4=(1,0,1,1),S5=(1,0,1,0),S6=(1,0,0,1),S7=(1,0,0,0)S8=(0,1,1,1),S9=(0,1,1,0),S10=(0,1,0,1),S11=(0,1,0,0)S12=(0,0,1,1),S13=(0,0,1,0),S14=(0,0,0,1),S15=(0,0,0,0)其中,状态S3,S6,S7,S8,S9,S12是不合法状态,S0和S15分别是初始状态和目标状态。

第三步,定义操作,即用于状态变换的算符组F由于每次过河船上都必须有农夫,且除农夫外船上只能载狼,羊和菜中的一种,故算符定义如下:L(i)表示农夫从左岸将第i样东西送到右岸(i=1表示狼,i=2表示羊,i=3表示菜,i=0表示船上除农夫外不载任何东西)。

由于农夫必须在船上,故对农夫的表示省略。

农夫过河问题

农夫过河问题
{
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;//边个数

农夫携物过河程序

农夫携物过河程序

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

逻辑学教授的3个得意门生ABC,前一晚在酒吧喝多了,结果第二天3人集体迟到。

教授说:“作为对你们迟到的惩罚,你们3人必须比其他同学多做一道作业,完成了这道作业才可以离开教室。

”这道附加的作业是一道帽子题,教授给每人戴了顶帽子,帽子不是红色就是白色,不是白色就是红色。

每人都能看见其他2人帽子的颜色,却不能看见自己帽子的颜色。

每人都看到其他2人帽子的颜色后,每思考5分钟为一轮,谁猜出自己帽子的颜色了就可以说出来并离开。

教授还说:“你们3人中至少有1人戴了红色帽子。


第一轮下来,A说:“我没猜出来。

”B说“我也没猜出来”C说:“我也猜不出。


第二轮下来,还是没人能猜出自己帽子的颜色。

第三轮,3人都猜出了自己帽子的颜色。

问:ABC三人头顶都是什么颜色的帽子?然后用谓词逻辑写出推理过程。

最一般合一及归结反演相关
已知w={P(f(x,g(A,y)),z), P(f(x,z),z),求MGU
令δ0=ε,w0=w,因w中含有两个表达式,因此δ0不是最一般合一
差异集D0={g(A,y)/z}
δ1=δ0ºD0={g(A,y)/z}
w1={P(f(x,g(A,y)),g(A,y)), P(f(x,g(A,y)),g(A,y))
w1中仅含有一个表达式,所以δ1就是最一般合一。

证明G是否是F1、F2的逻辑结论。

F1:(∀x)(P(x)→(Q(x)∧R(x)))
F2:(∃x)(P(x)∧S(x))
G: (∃x)(S(x)∧R(x))
F1: ¬P(x)∨(Q(x)∧R(x)) ⇒ (¬P(x)∨Q(x)) ∧ (¬P(x)∨R(x))
F2: P(x)∧S(x)
¬G: ¬(∃x)(S(x)∧R(x)) ⇒ (∀x)(¬(S(x)∧R(x))) ⇒ ¬S(x)∨¬R(x)
子句集:
1 ¬P(x)∨Q(x)
2 ¬P(x)∨R(x)
3 P(x)
4 S(x)
5 ¬S(x)∨¬R(x)
其中2与3规约,4与5归结,其结果再归结得到空子句,证明G是F1与F2的结论。

农夫过河问题
(1)农夫每次只能带一样东西过河
(2)如果没有农夫看管,狼吃羊,羊吃菜
要求:
设计一个过河方案,使得农夫、狼、羊、菜都能过河,画出相应的状态空间图。

四元组S表示状态,即S=(农夫,狼,羊,菜)
用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,X)狼、羊在左岸;
(1,X,0,0)羊、菜在左岸;
(0,1,1,X)狼、羊在右岸;
(0,X,1,1)羊、菜在右岸;
(0,0,0,0)
/ L(2)
(1,0,1,0)
/ R(0)
(0,0,1,0)
/ L(1) \ R(3)
(1,1,1,0) (1,0,1,1)
/ R(2) \ R(2) (0,1,0,0) (0,0,0,1)
\ L(3) / L(1)
(1,1,0,1)
\ R(0)
(0,1,0,1)
\ L(2)
(1,1,1,1)
解一:
1.带羊过河 (1,0,1,0)
2.农夫回来 (0,0,1,0)
3.带狼过河 (1,1,1,0)
4.带羊回来 (0,1,0,0)
5.带菜过河 (1,1,0,1)
6.农夫回来 (0,1,0,1)
7.带羊过河 (1,1,1,1)
解二:
1.带羊过河 (1,0,1,0)
2.农夫回来 (0,0,1,0)
3.带菜过河 (1,0,1,1)
4.带羊回来 (0,0,0,1)
5.带狼过河 (1,1,0,1)
6.农夫回来 (0,1,0,1)
7.带羊过河 (1,1,1,1)。

相关文档
最新文档