这是一个很经典的问题,关于商人过河的问题,有兴趣的可以试一试

backplace 2003-09-13 01:08:34
有n名商人各带m名仆人要过河,但船最多只能载二人,商人已获知仆人的阴谋:在河的任一岸,只要仆人数超过商人数,仆人会将商人杀死并且窃取货物,安排如何乘船,商人才能安全过河,
我的思路:

用向量表示该过程:
岸上:
——>过河
|
(商人数,仆人数)——>(商人数,仆人数)
船上的:
(商人数',仆人数')
n:是过河次数。
(商人数,仆人数)+ (商人数',仆人数')=(商人数,仆人数)
------------------------------------- ----------------
| |
^ ^
过河 过河后在岸上
因此用函数替归的方法。
这是我写的程序:

#include<stdio.h>
#include<math.h>
void moveit(long n,long mer,long per,long k)
{
long i,j, k0,i1,j1;
static long array[1000][2];
if (n % 2 != 0)
if (mer==0 && per==0)
for (i1=0;i1 < k+1;i1++)
printf("(%ld,%ld)\n",array[k][0],array[k][1]);
if (mer>0 && per>0)
if (mer>=per)
{
for (i=0;i<3;i++)
for (j=0;j<3;j++)
{
array[k][0]=mer+pow(-1,n)*i;
array[k][1]=per+pow(-1,n)*j;
moveit(n++,mer,per,k++);
}
}
}
main()
{
long mer,per,n,k;
n=1;
k=0;
printf("please input the number of merchants\n");
scanf("%d",&mer);
printf("please input the number of pervonts\n");
scanf("%d",&per);
moveit( n,mer,per,k);
}
本想输出的结果依次为(array[][0],array[][1])的形式
但输出后无任何信息
...全文
379 5 打赏 收藏 举报
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
backplace 2004-02-29
#include "stdio.h"
#include "string.h"
#include "conio.h"
FILE *fp/*,*fpp*/;
/*long kg;*/
struct a{
long m,s;
struct a *next;
};/*数组类型a:记录各种情况下船上的商人和仆人数*/
struct a *jj,head;
long n,total=0,js=0;
struct aim {
long m1,s1,m2,s2;
long n;
struct aim *back,*next;};/*用于建立双向的指针链表,记入符合的情况*/
long k1,k2;
void freeit(struct aim *p){
struct aim *p1=p;

p1=p->back;
free(p);
if(p1!=NULL)
p1->next=NULL;
return;

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




long 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;
return 0;}/*判断函数*/


long sign(long 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;

}/*复制内容函数*/
void print(struct aim *p3){
struct aim *p=p3;
js++;
while(p->back){p=p->back;}
printf("\nit's%ld:\n",js);
fprintf(fp,"\nit's%ld:\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;
;}
}/*打印函数*/

void trans(struct aim *p){
struct aim *p3,*p0;
struct a *fla;
long 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);
/*kg++;
if(kg%4==0)fprintf(fpp,"\n");
fprintf(fpp,"(%ld,%ld:%ld,%ld,%ld)\t",p3->m1,p3->s1,p3->m2,p3->s2,p3->n);
*/
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;long /*ww=0,*/j,a;
long e,f;
struct a *flag;
FILE*fpt/*,*fptt*/;
/*kg=0;*/
if((fpt=fopen("c:result.dat","w+"))==0){
printf("can't creat it\n");
exit(0);}
/*if((fptt=fopen("c:process1.dat","w+"))==0){
printf("can't creat it\n");
exit(0);}*/
fp=fpt;
/*fpp=fptt;*/
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("%ld",&n);
fprintf(fp,"\n%ld\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;
/*ww++;
if(ww%4==0)fprintf(fpp,"\n");
fprintf(fpp,"(%ld,%ld)\t",jj->m,jj->s);
printf("(%ld,%ld)\t",jj->m,jj->s); */

}

/*fprintf(fpp,"\n\n::");*/
/*********************************/
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);
/*fclose(fptt);*/

getch();
}
  • 打赏
  • 举报
回复
backplace 2003-09-19
这道题目是数学模型上的题目,但没有具体编程过程,如果说有什么不同的话我想,我只是把其中的商人数和仆人数改为m,n不过我觉的商人数和仆人数具体是多少并不重要,因为我是初学者,而且我只学了c,加上我觉的用c就足可以解决了,如果我有更好的方案我会立即现上,其实也不算难,只是我学的还不够,对于tryber写的,我很感激,但是其中有一个问题,那就是你用的方法,对商人和仆人数少时还好,一旦多余10个人时,就很难这样做了。不过我觉你还是非常不错。
  • 打赏
  • 举报
回复
ZhangYv 2003-09-13
你到算法版去搜“商人”或者“野人”有不少源程序的,这个问题很早就讨论过了。这个问题属于人工智能搜索算法的产生式系统,
综合数据库(问题的表述,数据结构):一个三元组(商人个数,野人个数,船的状态)
规则集(过程):把所有可能的走法都归到规则集中,对这个问题共有10条规则可以在此集合中
控制:一个控制系统选定“规则集”中的某条集合作用于综合数据库上。

该问题的解法包括以上三个部分。
  • 打赏
  • 举报
回复
tryber 2003-09-13
去年写的,好像是对的,希望对你有用:

///定义一个过河动作列表,动作记录每次过河是人数和野人数
///如{2,0}表两个人和0个野人过河
///根据经验,从左边到右边的人运作只有这几个动作有意义
//toright[3]={{0,2},{1,1},{2,0}}
//而从右边回左边的动作只有这几个是有意义的
//toleft[3]={{0,2},{1,1},{0,1}}
//而且过河动作至少要11次,每个动作类似:{1,2,0,1,1,0,1,2,2,1,1}
//为了遍历过河动作,构造了一个3进制数,对它递增,再读这个列表过河即可.
////////////////

#include <stdio.h>
#include <math.h> //用到了幂函数pow

/////在TC++3.0中这么定义
#define BOOL int
#define TRUE 1
#define FALSE 0
///在VC中也可这么定义
///#define BOOL boolean


typedef struct tagBoatman
{
int man;
int savage;
}Boatman,*pBoatman;

class Boat
{
private:
Boatman toleft[3];
Boatman toright[3];
int boatlist[11];
public:
long lvalue;
Boat(int *pboatlist);
BOOL Pass();
long operator++();
//long operator--();
};
Boat::Boat(int *pboatlist)
{
lvalue=0;
for(int i=0;i<11;i++)
{
boatlist[i]=*(pboatlist++);
lvalue+=boatlist[i]*pow(3,i);
}
toleft[0].man=0;
toleft[0].savage=1;
toleft[1].man=1;
toleft[1].savage=1;
toleft[2].man=0;
toleft[2].savage=2;

toright[0].man=0;
toright[0].savage=2;
toright[1].man=1;
toright[1].savage=1;
toright[2].man=2;
toright[2].savage=0;
}
long Boat::operator++()
{
lvalue++;
long tmpvalue;
long tmppow;
for(int i=11;i>0;i--)
{
tmppow=(long)pow(3,i);
tmpvalue=lvalue%tmppow;
tmppow=(long)pow(3,i-1);
boatlist[i-1]=tmpvalue/tmppow;
}
return lvalue;
}
BOOL Boat::Pass()
{
int man=3;
int savage=3;
for(int i=0;i<11;i++)
{
if(!(i%2))
{
man-=toright[boatlist[i]].man;
savage-=toright[boatlist[i]].savage;
if((man<0)||(savage<0))
return FALSE;
if((man!=0)&&(man<savage))
return FALSE;
if(((3-man)!=0)&&((3-man)<(3-savage)))
return FALSE;
if((man==0)&&(savage==0))
{
for(int j=0;j<11;j++)
{ if(!(j%2))
printf("%d,%d,%d\n",toright[boatlist[j]].man,toright[boatlist[j]].savage,1);
else
printf("%d,%d,%d\n",toleft[boatlist[j]].man,toleft[boatlist[j]].savage,0);
}
return TRUE;
}
}
else
{
man+=toleft[boatlist[i]].man;
savage+=toleft[boatlist[i]].savage;
if((man<0)||(savage<0))
return FALSE;
if((man!=0)&&(man<savage))
return FALSE;
if(((3-man)!=0)&&((3-man)<(3-savage)))
return FALSE;
}
}
return FALSE;
}

int main()
{
int bl[11]={0,0,0,0,0,0,0,0,0,0,0};
Boat boat(bl);
BOOL res=FALSE;
while(!res)
{
boat++;
res=boat.Pass();
}
printf("Press any key to exit");
getchar();
return 1;
}
  • 打赏
  • 举报
回复
tianjieshui 2003-09-13
题目都写错了 一个商人带两个仆人 还没上船商人就死了
  • 打赏
  • 举报
回复
相关推荐
发帖
C语言
加入

6.6w+

社区成员

C语言相关问题讨论
社区管理员
  • C语言
  • 小灸舞
申请成为版主
帖子事件
创建了帖子
2003-09-13 01:08
社区公告
暂无公告