人狼羊草过河问题数学建模

合集下载

渡河问题

渡河问题
渡河问题
一个人带了一只狼、一只山羊和一棵白菜想 要渡河。河上有一只独木船,每次除人外只 能带一样东西,另外如果人不在时狼就要吃 山羊,羊就要吃白菜。问应该怎样安排渡河, 才能做到既把所有东西都带过河,而且在河 上来回的次数又最少? 设M代表人,W代表狼,S代表山羊,V代表 白菜。
渡河问题
算法思想: 用集合表示在某岸上的所有情况(16种): [MWSV] [MWS] [MWV] [MSV] [WSV] [MW] [MS] [MV] [WS] [WV] [SV] [M] [S] [V] [空] 剩下的10种情况,按若甲经过一次渡河可变成乙, 那么就在甲与乙之间连一条边,由此得到如下图G: MWSV MWS MWV MSV 找一条连接顶点MWSV与空,并且包含边数最少的路.

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

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

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

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

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

数学建模人狼羊菜问题

数学建模人狼羊菜问题

一,论文题目人,狼,羊,菜渡河问题二,摘要将人狼羊菜依次用一个四维向量表示,对每一分量按二进制法则进行运算,将可行状态与转移状态表示出来,将这种运算方法设计为Matlab语言,进行计算机的计算,最终求得所得结果。

三,问题的重述一个摆渡人希望用一条小船把一只狼,一只羊和一篮白菜从一条河的左岸渡到右岸去,而船小只能容纳人,狼,羊,菜中的两个,绝不能在无人看守的情况下,留下狼和羊或羊和白菜在一起,求应怎样渡河才能把狼羊白菜都运过去?四,模型的假设、符号约定和名词解释我们可以用四维向量来表示状态,其中第一分量表示人,第二分量表示狼,第三分量表示羊,第四分量表示菜;当人或物在此岸时相应分量取1,在对岸时则取0。

根据题意,人不在场时,狼要吃羊,羊要吃菜,因此,人不在场时,不能将狼与羊,羊与菜留在河的任一岸。

例如,状态(0,1,1,0)表示人和菜在对岸,而狼和羊在此岸,这时人不在场的情况下狼要吃羊,因此,这个状态是不可行的。

我们通过穷举法将所有可行的状态列举出来,可行的状态有(1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(1,0,1,0)(0,1,0,1),(0,1,0,0),(0,0,1,0),(0,0,0,1),(0,0,0,0)可行状态共有十种。

每一次的渡河行为改变现有的状态。

用1 表示过河,0 表示未过河。

例如,(1,1,0,0)表示人带狼过河。

状态转移只有四种情况,用如下的向量表示。

(1,0,0,0),(1,1,0,0),(1,0,1,0),(1,0,0,1)五,模型的建立、模型求解、模型的结果和检验将可取状态及可取运载分别编成矩阵。

共分为五个m文件,一个主文件xduhe.m数,分别为:1、duhe(L,B,M,s)函数。

用来实现渡河总思路。

思路为:将起始矩阵A分别与可取运载相加(使用二进制法则),判断相加后的矩阵C是否是【0,0,0,0】,如果是,则渡河成功。

否则,用fuhe(C,M) 函数判断C是否是可取状态,如果是,则打印并将C与初始矩阵合并成新矩阵,继续调用duhe.m函数。

数学建模期末考试A试的题目与答案

数学建模期末考试A试的题目与答案

华南农业大学期末考试试卷(A 卷)2012-2013学年第 二 学期 考试科目:数学建模考试类型:(闭卷)考试 考试时间: 120 分钟学号 姓名 年级专业一、(满分12分) 一人摆渡希望用一条船将一只狼,一只羊,一篮白菜从河岸一边带到河岸对面,由于船的限制,一次只能带一样东西过河,绝不能在无人看守的情况下将狼和羊放在一起;羊和白菜放在一起,怎样才能将它们安全的带到河对岸去? 建立多步决策模型,将人、狼、羊、白菜分别记为i = 1,2,3,4,当i 在此岸时记x i = 1,否则为0;此岸的状态下用s =(x 1,x 2,x 3,x 4)表示。

该问题中决策为乘船方案,记为d = (u 1, u 2, u 3, u 4),当i 在船上时记u i = 1,否则记u i = 0。

(1) 写出该问题的所有允许状态集合;(3分)(2) 写出该问题的所有允许决策集合;(3分)(3) 写出该问题的状态转移率。

(3分)(4) 利用图解法给出渡河方案. (3分)解:(1) S={(1,1,1,1), (1,1,1,0), (1,1,0,1), (1,0,1,1), (1,0,1,0)} 及他们的5个反状(3分)(2) D = {(1,1,0,0), (1,0,1,0), (1,0,0,1), (1,0,0,0)} (6分)(3) s k+1 = s k + (-1) k d k (9分)(4)方法:人先带羊,然后回来,带狼过河,然后把羊带回来,放下羊,带白菜过去,然后再回来把羊带过去。

或: 人先带羊过河,然后自己回来,带白菜过去,放下白菜,带着羊回来,然后放下羊,把狼带过去,最后再回转来,带羊过去。

(12分)1、 二、(满分12分) 在举重比赛中,运动员在高度和体重方面差别很大,请就下面两种假设,建立一个举重能力和体重之间关系的模型:(1) 假设肌肉的强度和其横截面的面积成比例。

6分(2) 假定体重中有一部分是与成年人的尺寸无关,请给出一个改进模型。

人狼羊菜渡河问题(含Matlab程序)

人狼羊菜渡河问题(含Matlab程序)

人、狼、羊、菜安全渡河问题安全渡河问题又称作“人狼羊菜”问题,其具体描述为:一个人带着一条狼、一只羊、一筐白菜过河但由于船太小,人一次只能带一样东西乘船过河。

狼和羊、羊和白菜不能单独留在同岸,否则羊或白菜会被吃掉。

该问题可使用图论中的最短路算法进行求解。

问题分析根据题意,人不在场时,狼要吃羊,羊要吃菜,因此,人不在场时,不能将狼与羊、羊与菜留在河的任一岸。

可用四维向量v=(m,n,p,q)来表示状态,m表示人,n代表狼,p代表羊,q代表白菜,且m,n,p,q ∈{0,1},0代表在对岸,1代表在此岸。

例如,状态(0,1,1,0)表示人和菜在对岸,而狼和羊在此岸,这时人不在场,狼要吃羊,因此,这个状态是不可行的。

通过穷举法将所有可行的状态列举出来,可行的状态有(1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(1,0,1,0),(0,1,0,1),(0,1,0,0),(0,0,1,0),(0,0,0,1),(0,0,0,0)。

可行状态共有十种。

每一次的渡河行为改变现有的状态。

现构造赋权图G=(V,E,W),其中顶点集V={v1,…, v10}中的顶点(按照上面的顺序编号)分别表示上述10个可行状态,当且仅当对应的两个可行状态之间存在一个可行转移时两顶点之间才有边连接,并且对应的权重取为1,当两个顶点之间不存在可行转移时,可以把相应的权重取为∞。

因此问题变为在图G中寻找一条由初始状态(1,1,1,1)出发,经最小次数转移到达最终状态(0,0,0,0)的转移过程,即求从状态(1,1,1,1)到状态(0,0,0,0)的最短路径。

该问题难点在于计算邻接矩阵,由于摆渡一次就改变现有状态,为此再引入一个四维状态转移向量,用它来反映摆渡情况。

用1表示过河,0表示未过河。

例如,(1,1,0,0)表示人带狼过河。

状态转移只有四种情况,用如下向量表示:(1,0,0,0),(1,1,0,0),(1,0,1,0),(1,0,0,1)现在规定状态向量与转移向量之间的运算为0+0=0,1+0=1,0+1=1,1+1=0通过上面的定义,如果某一个可行状态加上转移向量得到的新向量还属于可行状态,则这两个可行状态对应的顶点之间就存在一条边。

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

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

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

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

农夫怎么才能把所有的东西安全运过河呢?实验要求如下:(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表示船上除农夫外不载任何东西)。

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

狼羊过河问题

狼羊过河问题

狼、羊、菜过河问题1.模型建立用0-1将人、狼、羊、菜河这边的所有状态表示出来(其中状态1代表在河这边,状态0代表在河对岸),共有16种状态。

由题设条件知,状态(0,1,1,0),(0,0,1,1)(0,1,1,1,)是不允许的,从而对应状态(1,0,0,1)(1,1,0,0)(1,0,0,0,)也是不允许的。

最后得到10种状态。

将它们分别标号如下:1(1 1 1 1)2(1 0 1 1)3(0 0 0 1)4(1 1 0 1)5(1 1 1 0)6(1 0 1 0)7(0 1 0 1)8(0 1 0 0)9(0 0 1 0)10(0 0 0 0)然后将各状态能够相互转移的状态用1表示,不能相互转移的状态用无穷大inf表示,得到关于这10种状态的一个10*10的邻接矩阵。

利用Floyd算法,在matlab上运行,即可找出该过河问题的最佳答案。

所得的邻接矩阵如下:[inf inf inf inf inf inf 1 inf inf infinf inf 1 inf inf inf inf inf 1 infinf 1 inf 1 inf inf inf inf inf infinf inf 1 inf inf inf 1 1 inf infinf inf inf inf inf inf inf 1 1 infinf inf inf inf inf inf inf inf 1 11 inf inf 1 inf inf inf inf inf infinf inf inf 1 1 inf inf inf inf infinf 1 inf inf 1 1 inf inf inf infinf inf inf inf inf 1 inf inf inf inf ]利用Floyd算法:function [D,path]=floyd(a)n=size(a,1);D=a;path=zeros(n,n);for i=1:nfor j=1:nif D(i,j)~=infpath(i,j)=j;endendendfor k=1:nfor i=1:nfor j=1:nif D(i,k)+D(k,j)<D(i,j)D(i,j)=D(i,k)+D(k,j);path(i,j)=path(i,k);endendendendfunction [L,R]=router(D,path,1,10)L=zeros(0,0);R=s;while 1if s==tL=fliplr(L);L=[0,L];returnendL=[L,D(s,t)];R=[R,path(s,t)];s=path(s,t);End输入a=[inf inf inf inf inf inf 1 inf inf infinf inf 1 inf inf inf inf inf 1 infinf 1 inf 1 inf inf inf inf inf infinf inf 1 inf inf inf 1 1 inf infinf inf inf inf inf inf inf 1 1 infinf inf inf inf inf inf inf inf 1 11 inf inf 1 inf inf inf inf inf infinf inf inf 1 1 inf inf inf inf infinf 1 inf inf 1 1 inf inf inf infinf inf inf inf inf 1 inf inf inf inf ]得到:D =2 43 24 6 1 35 74 2 1 2 2 2 3 3 1 33 1 2 1 3 3 2 2 2 42 2 1 2 2 4 1 13 54 2 3 2 2 2 3 1 1 36 2 3 4 2 2 5 3 1 11 32 13 5 2 24 63 3 2 1 1 3 2 2 2 45 1 2 3 1 1 4 2 2 27 3 4 5 3 1 6 4 2 2path =7 7 7 7 7 7 7 7 7 73 3 3 3 9 9 3 3 9 94 2 2 4 4 2 4 4 2 27 3 3 3 8 3 7 8 3 38 9 8 8 8 9 8 8 9 99 9 9 9 9 9 9 9 9 101 4 4 4 4 4 1 4 4 44 4 4 45 5 4 4 5 52 2 2 2 5 6 2 5 2 66 6 6 6 6 6 6 6 6 6L =0 1 2 3 4 5 6 7R =1 7 4 32 9 6 10可得到过河的状态转移为:1---7---4---3---2---9---6---10即人将羊送到河对岸,回来再将狼送到河对岸,在对岸将羊拉回来,再将菜送到河对岸,回来时再和羊一起到河对岸,人狼羊菜全部过河,问题得到解决。

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

数学建模——题目:过河问题一(人狼羊草)摘要 (3)一、问题的提出 (3)二、问题分析及假设 (4)三、模型的参数及符号 (5)四、模型及解 (5)五、计算机编程法(C语言) (10)六、参考文献 (14)摘要在本次数学建模中,我们主要讨论的是人狼羊草问题:一位渔民带了狼、羊、草,准备过河。

可是小船每次只能容下渔民和一件物品。

渔民不在时,狼会吃羊、羊会吃草。

要求我们设计一个方案,使农夫可以无损失的过河。

此过河问题可以视为一个多步决策过程,确定每一步的决策,达到过河的目标。

而且,我们假设人不在时,狼或羊在农夫不在时不会自己跑掉或被人牵走且农夫会划船。

于是我们得到一下集中状态:狼羊草人/, /狼羊草人,狼羊人/草,草/狼羊人,狼草人/羊,羊/狼草人,羊草人/狼,狼/羊草人,羊人/狼草,狼草/羊人。

题目要求找出“狼羊草人/”到“/狼羊草人”的路径,本论文根据题目要求而讨论了人、狼、羊、草怎样安全过河的模型。

提出了算法和计算机编程法两种解决问题的方法,并且通过计算机编程法得出了一种方法。

一、问题的提出人、狼、羊、草均需过河,船需要人划,最多载一物。

人不在时,狼吃羊、羊吃草,问如何过河?这个问题可以简单的解释为:一位渔民带了狼、羊、草,准备过河。

可是小船每次只能容下渔民和一件物品。

另有一条件为,渔民不在时,狼会吃羊、羊会吃草。

也就是说,狼与羊、羊与草、或狼羊草不能单独在一起。

现要求为过河人提出某种过河的方法,使人、狼、羊、草都安全度过河且方法最简单为宜二、问题分析及假设过河问题相当于状态的转移。

初状态是人,狼,羊,草均在此岸,目标终状态是人,狼,羊,草均在对岸。

(此岸)状态向量:用四维向量(人,狼,羊,草)表示人,狼,羊,草各自的状态,记“在此岸”时各分量为“1”,否则记为“0”。

例如:(1,1,1,1)表示人,狼,羊,草均在此岸,(0,0,0,0)表示人,狼,羊,草均在对岸。

允许状态向量:满足系统限定条件的状态向量。

穷举所有允许状态向量如下:(1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(1,0,1,0),(0,1,0,1),(0,0,0,1),(0,0,1,0)(0,1,0,0),(0,0,0,0)。

运载状态向量:用四维向量(人,狼,羊,草)表示他们各自被运载的情况,记“被运载”时各分量为“1”,否则记为“0”。

例如:(1,1,0,0)表示被运载的是人和狼,又如(1,0,1,0)表示被运载的是人和羊。

允许运载向量:满足系统限定条件下的运载向量。

穷举所有允许运载向量如下:(1,0,0,0),(1,1,0,0),(1,0,1,0),(1,0,0,1)。

转移:一允许状态向量逻辑加以允许运载向量。

状态转移方程:原状态⊕运载=现状态运算规则:1+1=0,1+0=1,0+1=1,0+0=0。

允许运载方式:若可取状态向量 + 可取运载向量 = 可取状态向量,则此运载为可取运载方式,其中“+”为按上述运算规则定义的运算符。

三、模型的参数及符号(1)S:表示所有允许状态向量的集合S={(1,1,1,1),(1,1,1,0),(1,1,0,1),(1,0,1,1),(1,0,1,0),(0,1,0,1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(0,0,0,0)} (2)D:表示所有允许运载向量D={(1,0,0,0),(1,1,0,0),(1,0,1,0),(1,0,0,1)}(3)S k:表示第K步允许状态向量(4)D k:表示第K步允许运载向量(5)k:表示第几步,k=1,2,3…n四、模型及解模型:在计算规则“1+1=0,1+0=1,0+1=1,0+0=0”下,且满足S k + D k = S k+1,问题:(1)求D k属于D,使得S k+1属于S;(2)求最优的n。

其中:初始条件S=(1,1,1,1),最终状态S n+1=(0,0,0,0)解法(1):算法4.1 (0,1,0,1)与上述第二步重复,必定不是最优解,故不用进行下去。

4.2.1 ( 1,1,0,1 )与上述第3步重复,必定不是最优解,不用进行下去4.2.2.1 (0,0,0,1)与上述4.2重复,必定不是最优解,不用进行下去4.2.2.2.1 (1,0,1,1)与上述4.2.2重复,必定不是最优解,不用进行下去已得最终状态向量(0,0,0,0),过程无重复,此即为最优解。

4.3.1 ( 1,1,0,1 )与上述第3步重复,必定不是最优解,不用进行下去4.3.2.1 (0,1,0,0)与上述4.3重复,必定不是最优解,不用进行下去4.3.2.2 ( 0,0,1,0 )与按上述4.2.2.2步骤进行即可得相同的最优解 模型的解 最终结果:解一: D1(1,1,1,1)→D2(0,1,0,1)→D3( 1,1,0,1 )→D4(0,1,0,0)→D5( 1,1,1,0 )→D6( 0,0,1,0 )→D7(1,0,1,0)→D8(0,0,0,0)(1,1,0,0)(1,0,1,0) (1,0,0,1) (1,0,0,0)4.3.2 (1,1,1,0) +=(0,0,1,0) √ =(0,1,0,0) √ =(0,1,1,1) × =(0,1,1,0) ×解二: D1(1,1,1,1)→D2(0,1,0,1)→D3( 1,1,0,1 )→D4(0,0,0,1)→D5(1,0,1,1)→D6( 0,0,1,0 )→D7(1,0,1,0)→D8(0,0,0,0) n=7 解法(2):图解法绘图要求:(1)连线两端必须是允许状态向量;(2)相邻两点(通过一次运载得到的点)相连; (3)从(1,1,1,1)至(0,0,0,0)结束。

连线如下:最终结果:(1,1,1,1)(1,0,1,0)(1,1,0,1)(1,0,1,1)(1,1,1,0)(0,0,0,0)(0,0,0,1)(0,0,1,0)(0,1,0,0)(0,1,0,1)模型的解解一: D1(1,1,1,1)→D2(0,1,0,1)→D3( 1,1,0,1 )→D4(0,1,0,0)→D5( 1,1,1,0 )→D6( 0,0,1,0 )→D7(1,0,1,0)→D8(0,0,0,0)解二: D1(1,1,1,1)→D2(0,1,0,1)→D3( 1,1,0,1 )→D4(0,0,0,1)→D5(1,0,1,1)→D6( 0,0,1,0 )→D7(1,0,1,0)→D8(0,0,0,0)n=7与解法(1)解相同五、计算机编程法(C语言)要解决这个问题就要使过河时载两个过河,返回时尽量只有一个回来。

用一个字符串数组来存人,狼,羊,草;下标依次为0,1,2,3;但他们都有河这边和那边两种状态;为方便则定义一个结构,只含一个int型变量n;当在河这边时n设为0;在河那边时n设为1。

由于每次过河与返回都要考虑狼能否吃羊或羊能否吃草;则需要一个函数来判断每次选择是否满足条件。

源代码:#include"stdio.h"typedef struct node{int n;}node;int p(node *a)int i,j=1;if(a->n==1){for(i=1;i<3;i++)if((a+i)->n==0&&(a+i+1)->n==0) {j=0;break;} }if(a->n==0){for(i=1;i<3;i++)if((a+i)->n&&(a+i+1)->n) {j=0;break;} }return j;}int main(){int i,k=0,m=0,l,j=0,q;char str[4][7]={"人","狼","羊","草"}; node a[4];for(i=0;i<4;i++) (a+i)->n=0;while(1){a[0].n=1;for(l=1;l<4;l++){if(l==j) {j=0;continue;}if((a+l)->n==0){(a+l)->n=1;if(p(a)) break;else (a+l)->n=0;}}printf("%s,%s 过河; ",str[m],str[l]);for(q=0;q<4;q++)if((a+q)->n) m=1;else {m=0;break;}if(m) break;a->n=0;if(p(a)==0) {k=1;for(j=1;j<4;j++){if(j==l) {l=0;continue;}if((a+j)->n==1){(a+j)->n=0;if(p(a)) break;else (a+j)->n=1;}}}if(k) {printf("%s,%s 返回\n",str[m],str[j]);k=0;}else printf("%s 返回\n",str[m]);}printf("\n");return 0;}图为计算机运行结果六、参考文献1、数学建模精讲精练,哈尔滨工程大学出版社,沈继红主编,20072、数学建模,哈尔滨工业大学出版社,白凤山等主编,20033,数学模型,高等教育出版社,姜启源主编,19934、C语言程序设计教程,电子工业出版社,凌云主编,20085、数学建模,浙江大学出版社,杨启帆主编,19996、数学建模导论,北京邮电大学出版社,陈理荣主编,2000。

相关文档
最新文档