修正我上次关于《商人过河的问题》

原创 2004年03月08日 11:31:00

/*实在不好意思,在trans()函数中我没有把开始调试时的用的4改成total-1,现已改正,并已注明改正处,谢谢,并致以歉意*/

#include "stdio.h"
#include "string.h"
#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("/nit's%d:/n",js);
fprintf(fp,"/nit's%d:/n",js);
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;
;}
}/*打印函数,将p3所指的内容打印出来*/

void trans(struct aim *p){
struct aim *p3;/*p3为申请的结构体指针*/
struct a *fla;
int i,j,f,e;
fla=&head;
p3=(struct aim *)malloc(sizeof(struct aim));
f=sign(p->n);
for(i=0;i<total;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<total-1){continue;}
else{
freeit(p3);
break;}}

if(j==1){if(i<total-1){print(p3);
continue;}
else{print(p3);
freeit(p3);
break;}}

if(j==0)trans(p3);
}
return;
}/*转移函数,即将人转移过河*/
/*n=0*/

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;
clrscr();
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");
fprintf(fp,"/nplease input the total of people on the board/n");
scanf("%d",&n);
fprintf(fp,"/n%d/n",n);
flag=&head;
for(e=0;e<=n;e++)
 for(f=0;f<=n;f++)
 if(e+f>0&&e+f<=n)
 { total++;
 jj=(struct a*)malloc(sizeof(struct a));
 jj->m=e;
 jj->s=f;
 flag->next=jj;
 jj->next=NULL;
 flag=jj;

 }


/*********************************/
printf("please input the total of merchant and salvent as follow: mechant,salvent;/n");
fprintf(fp,"/nplease input the total of merchant and salvent as follow: mechant,salvent;/n");
scanf("%ld,%ld",&p->m1,&p->s1);
fprintf(fp,"/n%ld,%ld/n",p->m1,p->s1);
/**********************************/
k1=p->m1;
k2=p->s1;
trans(p);
fclose(fpt);

getch();
}
/*一年前,我初学c语言,在数模书上无意中看到这道题原题是:有n个商人k个仆人过河,船上最多有m个人,两岸上有任意一岸仆人数多于商人数商人都会死,问应如何安排才能使商人顺利过河,若不能则不打印出全过程:建议开始值n=3,k=3,m=2

这个问题是在我自学过指针后才有思路的,并且在此之前我也在提问题的地方求教过,如今写来仅表纪念,还请大家不要笑我,谢谢*/

注明:我并非计算机专业,开始我本只想写着好玩,而且我只是想将自己

没想到。。。。不过我倒是没什么,只觉的自己的风格有待提高,其实想法很简单,就是用穷举搜索的方法,先将船上的人数建成一个二维的列表,两岸的人数建立成一个双向的链表,用于存储符合条件的情况,用检查重复的方法来解决循环出现。其实它可用来解决这样一类过河的问题,

解决问题的思想是基于多维向量的运算,不加注释,并非我一相情愿,只是我用的是turboc2.0,在其环境下无法使用中文,又怕我蹩脚的英文吓到大家,反而增加误会,还有我自己确实对c了解不是很多,我今年大二

,大二上学期才学了c,用的是一本《c/c++。。》作者是唐诠,是江苏省的教材

 

商人过河 Matlab程序实现

这是我在本科的时候,即08年8月数学建模竞赛前 编写并优化后的 “商人过河” 程序,但最近无意间发现多个转载或者改写本程序的帖子和文档,却没有标明 参考出处,我表示很无语! 其实,作为一个开源社区的...
  • gujinjin2008
  • gujinjin2008
  • 2014年04月20日 22:52
  • 3610

【数学模型】商人们怎样过河?

这篇博文中,同样是一个很简单的数学问题,但是解决起来比上一个的问题要复杂一些。在这次模型求解中,我会使用两种方法,一种是纯粹的数学方法,另一种是通过计算机程序来计算,通过计算机求解我们可以求解一些规模...
  • luoyhang003
  • luoyhang003
  • 2016年01月06日 13:36
  • 6831

(回溯算法)商人怎样安全过河

(回溯算法)商人怎样安全过河(本文属原创,转载请注名作者!author:wcnpepyu)过河问题: 有三个商人和三个仆人过河,只有一条能装下两个人的船,在河的任何一岸上,如果仆人的人数大于商人的人数...
  • wengjiaxiang
  • wengjiaxiang
  • 2007年03月07日 22:29
  • 1608

[数学模型]商人怎样安全过河

商人怎样安全过河
  • YinJianxiang
  • YinJianxiang
  • 2017年09月17日 11:50
  • 302

【算法思想】过河问题(续)

前一篇文章用人、狗、鸡、米过河问题介绍了解决过河问题的普适解决方法以及其改进算法。本文先用该算法解决我们常见的六只老虎过河问题,然后用特殊方法解决另外一种过河问题。 六只老虎过河问题:     问...
  • tengweitw
  • tengweitw
  • 2014年05月14日 19:00
  • 1780

过河问题(牛虎过河、商人仆人过河、农夫妖怪过河、传教士野人过河)(第2届第2题)

经典的过河问题,利用栈实现回溯,利用递归遍历各种状态,类似于迷宫寻路或者八皇后问题的解决方案。...
  • kangjianwei101
  • kangjianwei101
  • 2015年12月20日 20:11
  • 1390

【算法编程】过河问题

今天偶尔想到了过河问题。记得读小学六年级的时候第一次接触到这个问题--六个老虎过河问题(百度上有详细介绍,本文解决的是一个简单的问题,下一篇文章中将讨论该问题),当时都是从逻辑思维的方法得到正确的解决...
  • tengweitw
  • tengweitw
  • 2014年05月08日 12:31
  • 2599

商人胡萝卜问题

一个商人骑一头驴要穿越1000公里长的沙漠,去卖3000根胡萝卜。 已知驴一次性可驮1000根胡萝卜,但每走1公里又要吃掉1根胡萝卜。 问:商人最多可卖出多少胡萝卜?要使到达终点的萝卜最多,就不能浪费...
  • utimes
  • utimes
  • 2012年12月31日 12:11
  • 2461

商人过河问题

今天星期天,刚上完数学建模,感觉好累,老师说了一个商人过河问题。不懂~~上网COPY了一篇别人写的,看不懂,还不如自己编呢。今天到此为止,我要编程序了。...
  • hoverchang
  • hoverchang
  • 2005年03月20日 16:26
  • 549

马云纽约演讲全文:再不改革教育_年轻人都要失业

想不想知道是什么 马云: 克林顿总统先生、迈克尔、各位阁下、朋友们,早上好。 先前他们联系我说,纽约有一场论坛,让我们分享对未来的想法和思考。我感...
  • yunqishequ1
  • yunqishequ1
  • 2017年09月30日 13:43
  • 189
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:修正我上次关于《商人过河的问题》
举报原因:
原因补充:

(最多只允许输入30个字)