数学建模:研究商人过河问题

  • 格式:doc
  • 大小:90.00 KB
  • 文档页数:25

创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 数学建模实验一陈说之吉白夕凡创作

创作时间:二零二一年六月三十日

实验题目:研究商人过河问题

一、实验目的:编写一个法式(可以是C,C++或Mathlab)实现商人平安过河问题.

二、实验环境:Turbo c 2.0、、Matlab 6.0以上

三、实验要求:要求该法式不单能找出一组平安过河的可行方案,

还可以获得所有的平安过河可行方案.而且该法式具有一定的可扩展性, 即不单可以实现3个商人, 3个随从的过河问题.还应能实现

n个商人, n个随从的过河问题以及n个分歧对象且每个对象有m个元素问题(说明:对3个商人, 3个随从问题分别对应于n=2,m=3)的过河问题.从而给出课后习题5(n=4,m=1)的全部平安过河方案.

四、实验步伐:

第一步:问题分析.这是一个多步决策过程, 涉及到每一次船上的人员以及要考虑彼岸和彼岸上剩余的商人数和随从数, 在平安的条件下(两岸的随从数不比商人多), 经有限步使全体人员过河.

第二步:分析模型的构成.记第k次渡河前彼岸的商人数为kx,

随从数为ky, 2,1k, nyxkk2,1,, (具有可扩展性), 将)(kkyx,界说为状态, 状态集合成为允许状态集合(S).S={2,1;3,2,1,0,3;3,2,1,0,0|,yxyxyxyx)(}记第k次渡船创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 的商人数为ku, 随从数为kv, 决策为),(kkvu, 平安渡河条件下, 决策的集合为允许决策集合.允许决策集合记作D, 所以D={2,1,0,,21|,vuvuvu)(|1

第三步:模型求解.

#include "stdio.h"

#include "string.h"

#include

#include

#include

using namespace std;

#include "conio.h"

FILE *fp;/*设立文件指针, 以便将它用于其他函数中*/

struct a{

long m,s;

struct a *next;

};/*数组类型a:记录各种情况下船上的商人和仆人数, m:代表商人数 s:代表仆人数*/ 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 struct a *jj,head;/*head为头指针的链表单位(船上的人数的各种情况的链表)*/

int n,total=0,js=0;/*total暗示船上各种情况总数*/

struct aim {

long m1,s1,m2,s2;

int n;

struct aim *back,*next;};/*用于建立双向的指针链表, 记入符合的情况, m1, s1暗示要过岸的商人数和仆人数;m2, s2暗示过岸了的商人数和仆人数, n暗示来回的次数*/

int k1,k2;

void freeit(struct aim *p){

struct aim *p1=p;

p1=p->back;

free(p);

if(p1!=NULL)

p1->next=NULL;

return;

}/*释放该单位格, 并将其上的单位格的next指针还原*/

int determ(struct aim *p)

{ struct aim *p1=p;

if(p->s1>k2)return -1;/*仆人数不能超越总仆人数*/

if(p->m1>k1)return -1;/*商人数不能超越总商人数*/ 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 if(p->s2>k2)return -1;/*对岸, 同上*/

if(p->m2>k1)return -1;/*对岸, 同上*/

if(p->s1<0)return -1;/*仆人数不能为负*/

if(p->s2<0)return -1;/*商人数不能为负*/

if(p->m1<0)return -1;/*对岸, 同上*/

if(p->m2<0)return -1;/*对岸, 同上*/

if(p->m1!=0)

if(p->s1>p->m1)return -1;

if(p->m2!=0)

if(p->s2>p->m2)return -1;/*两岸商人数均不能小于仆人数*/

while(p1!=NULL){

p1=p1->back;

if(p1!=NULL)

if(p1->n%2==p->n%2)

if(p1->s1==p->s1)

if(p1->s2==p->s2)

if(p1->m1==p->m1)

if(p1->m2==p->m2)

return -1;}/*用于解决重复, 算法思想:即将每次算出的链表单位与以前的相比力, 若重复, 则暗示呈现循环*/

if(p->s1==0&&p->m1==0)

if(p->n%2==0)return 1; 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 else return -1;/*显然如果达到条件就说明ok了*/

return 0;}/*判断函数*/

int sign(int n){

if(n%2==0)return -1;

return 1;}/*符号函数*/

void copyit(struct aim *p3,struct aim *p){

p3->s1=p->s1;

p3->s2=p->s2;

p3->m1=p->m1;

p3->m2=p->m2;

p3->n=p->n+1;

p3->back=p;

p3->next=NULL;

p->next=p3;

}/*复制内容函数, 将p中的内容写入p3所指向的链表单位中*/

void print(struct aim *p3){

struct aim *p=p3;

js++;

while(p->back){p=p->back;}

printf("\n第%d种方法:\n",js);

fprintf(fp,"\n第%d种方法:\n",js);

int count=0; 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 while(p){ printf("%ld,%ld::%ld,%ld\t",p->m1,p->s1,p->m2,p->s2);

fprintf(fp,"%ld,%ld::%ld,%ld\t",p->m1,p->s1,p->m2,p->s2);

p=p->next;

count++;

}

cout<<"一共有"<

}/*打印函数, 将p3所指的内容打印出来*/

void trans(struct aim *p){

struct aim *p3;/*p3为申请的结构体指针*/

struct a *fla;

int i,j,f;

fla=&head;

p3=(struct aim *)malloc(sizeof(struct aim));

f=sign(p->n);

for(i=0;i

fla=fla->next;

copyit(p3,p);

p3->s1-=fla->m*f;

p3->m1-=fla->s*f;

p3->s2+=fla->m*f;

p3->m2+=fla->s*f;/*运算过程, 即过河过程*/ 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 j=determ(p3);/*判断, j记录判断结果*/

if(j==-1){

if(i

else{

freeit(p3);

break;}}

int count1=0;

if(j==1){if(i

count1++;

continue;}

else{print(p3);

freeit(p3);

break;}

//cout<

printf("%d",count1);

printf("\n");

}

if(j==0)trans(p3);

}

return;

}/*转移函数, 即将人转移过河*/

/*n=0*/ 创作时间:二零二一年六月三十日

创作时间:二零二一年六月三十日 void main()

{ struct aim *p,*p1;int j,a,e,f;

struct a *flag;/*flag是用与记录头指针*/

FILE*fpt;

if((fpt=fopen("c:result.dat","w+"))==0){

printf("can't creat it\n");

exit(0);}

fp=fpt;

system("cls");

printf("问题描述:三个商人各带一个随从搭船过河, 一只小船只能容纳X人, 由他们自己划船.三个商人窃听到随从们密谋, 在河的任意一岸上, 只要随从的人数比上人多, 就杀失落商人.可是如何搭船渡河的决策权在商人手里, 商人们如何安插渡河计划确保自身平安?\n");

printf("\n");

p=(struct aim *)malloc(sizeof(struct aim));

p->back=NULL;

p->next=NULL;

p->s2=0;

p->m2=0;

p->n=1;/*设立初始头指针*/

printf("please input the total of people on the board\n");