商人过河问题程序.docx
《商人过河问题程序.docx》由会员分享,可在线阅读,更多相关《商人过河问题程序.docx(17页珍藏版)》请在冰豆网上搜索。
商人过河问题程序
3人的可以过河,4人的没有办法。
用递归的源程序如下:
运行结果是没有解,超过3人的没有解。
开始时商人,强盗所在的河的这边设为0状态,另一边设为1状态(也就是船开始时的一边设为0,当船驶到对岸是设为1状态,在这两个状态时,都必须符合条件)
#include
structnode/*建立一个类似栈的数据结构并且可以浏览每一个数据点*/
{
intx;
inty;
intstate;
structnode*next;
};
typedefstructnodestate;
typedefstate*link;
linkPPointer1=NULL;
linkPPointer2=NULL;
inta1,b1;
inta2,b2;
/*栈中每个数据都分为0,1状态*/
voidPush(inta,intb,intn)
{
linknewnode;
newnode=(link)malloc(sizeof(state));
newnode->x=a;
newnode->y=b;
newnode->state=n;
newnode->next=NULL;
if(PPointer1==NULL)
{
PPointer1=newnode;
PPointer2=newnode;
}
else
{
PPointer2->next=newnode;
PPointer2=newnode;
}
}
voidPop()/*弹栈*/
{
linkpointer;
if(PPointer1==PPointer2)
{
free(PPointer1);
PPointer1=NULL;
PPointer2=NULL;
}
pointer=PPointer1;
while(pointer->next!
=PPointer2)
pointer=pointer->next;
free(PPointer2);
PPointer2=pointer;
PPointer2->next=NULL;
}
inthistory(inta,intb,intn)/*比较输入的数据和栈中是否有重复的*/
{
linkpointer;
if(PPointer1==NULL)
return1;
else
{
pointer=PPointer1;
while(pointer!
=NULL)
{
if(pointer->x==a&&pointer->y==b&&pointer->state==n)
return0;
pointer=pointer->next;
}
return1;
}
}
intjudge(inta,intb,intc,intd,intn)/*判断这个状态是否可行,其中使用了history函数*/
{
if(history(a,b,n)==0)return0;
if(a>=0&&b>=0&&a<=3&&b<=3&&c>=0&&d>=0&&c<=3&&d<=3&&a+c==3&&b+d==3)
{
switch(n)
{
case1:
{
if(a==3)
{
Push(a,b,n);
return1;
}
elseif(a==0)
{
Push(a,b,n);
return1;
}
elseif(a==b)
{
Push(a,b,n);
return1;
}
elsereturn0;
}
case0:
{
if(a==3)
{
Push(a,b,n);
return1;
}
elseif(a==0)
{
Push(a,b,n);
return1;
}
elseif(a>=b)
{
Push(a,b,n);
return1;
}
elsereturn0;
}
}
}
elsereturn0;
}
intDuhe(inta,intb,intn)/*递归法解决商人渡河问题,如果这一个状态符合*/
{/*则判断下一个状态,直至问题解决*/
if(a==0&&b==0)return1;
if(n==0)/*判断0状态时,商匪状态是否符合要求*/
{
if(judge(a-1,b-1,4-a,4-b,1))
{
if(Duhe(a-1,b-1,1)==1)
return1;
}
if(judge(a,b-2,3-a,5-b,1))
{
if(Duhe(a,b-2,1)==1)
return1;
}
if(judge(a-2,b,5-a,3-b,1))
{
if(Duhe(a-2,b,1)==1)
return1;
}
if(judge(a-1,b,4-a,3-b,1))
{
if(Duhe(a-1,b,1)==1)
return1;
}
if(judge(a,b-1,3-a,4-b,1))
{
if(Duhe(a,b-1,1)==1)
return1;
}
else
{
Pop(0);
return0;
}
}
if(n==1)/*判断0状态时,商匪状态是否符合要求*/
{
if(judge(a+1,b+1,2-a,2-b,0))
{
if(Duhe(a+1,b+1,0)==1)
return1;
}
if(judge(a,b+2,3-a,1-b,0))
{
if(Duhe(a,b+2,0)==1)
return1;
}
if(judge(a+2,b,1-a,3-b,0))
{
if(Duhe(a+2,b,0)==1)
return1;
}
if(judge(a+1,b,2-a,3-b,0))
{
if(Duhe(a+1,b,0)==1)
return1;
}
if(judge(a,b+1,3-a,2-b,0))
{
if(Duhe(a,b+1,0)==1)
return1;
}
else
{
Pop
(1);
return0;
}
}
return0;
}
main()
{
linkpointer;
Push(3,3,0);
Duhe(3,3,0);
pointer=PPointer1;
while(pointer!
=NULL)
{
printf("%d,%d---%d\n",pointer->x,pointer->y,pointer->state);
pointer=pointer->next;
}
getch();
}
a=[
0,0;
0,1;
0,2;
0,3;
3,0;
3,1;
3,2;
3,3;
1,1;
2,2;
];%10enabledstates
s=[0,0;
0,1;
0,2;
0,3;
1,0;
1,1;
1,2;
1,3;
2,0;
2,1;
2,2;
2,3;
3,0;
3,1;
3,2;
3,3;
];
d=[
0,2;
2,0;
1,1;
0,1;
1,0;
];%5enableddecisions
i=1;
j=1;
k=1;
s(1,
=[3,3];
disp('Thisshore-OnBoat-Thatshore')
fori=1:
12
*R5P0S8N$a'E-O
&B4i4Z#s#zD7O7j;f
forj=1:
5
t=0;
r=mod(i,2);
m=r;
u=0;
fork=1:
10
ifs(i,
+(-1)^i*d(j,
==a(k,
t=1;
end
end
end
ift==1
ifu==0
s(i+1,
=s(i,
+(-1)^i*d(j,
;
c(i+1,
=d(j,
;
return;
elseifu==1
continue;
end
elsecontinue;
end
end;
ift==0
disp('NoResult');
return;
end;
b(i+1,
=[3,3]-s(i+1,
;
play=sprintf('{%d,%d}-{%d,%d}-{%d,%d}',s(i,1),s(i,2),c(i+1,1),c(i+1,2),b(i+1,1),b(i+1,2));
disp(play)
ifs(i+1,
==[0,0]
return;
end;
functionjueche=guohe
%%%%%%%%%%%%%%%%%%%%%%
程序开始需要知道商人和仆人数;
n=input(‘输入商人数目:
’,’12’);
nn=input(‘输入仆人数目:
’,’12’);
nnn=input(‘输入船的最大容量:
’,’20’);
ifnn>n
n=input(‘输入商人数目:
’,’23’);
nn=input(‘输入仆人数目:
’,’23’);
nnn=input(‘输入船的最大容量:
’,’34’);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%决策生成
jc=1;%决策向量放在矩阵d中,jc为插入新元素的行标初始为1;
fori=0:
nnn
forj=0:
nnn
if(i+j<=nnn)&(i+j>0)%满足条D={(u,v)|1<=u+v<=nnn,u,v=0,1,2}
d(jc,1:
3)=[i,j,1];%生成一个决策向量立刻扩充为三维;
d(jc+1,1:
3)=[-i,-j,-1];%同时生成他的负向量;
jc=jc+2;%由于生成两个决策向量,则jc要向下移动两个;end
end
j=0;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%状态数组生成
kx=1;%状态向量放在A矩阵中,生成方法同矩阵生成;
fori=n:
-1:
0
forj=nn:
-1:
0
if((i>=j)&((n-i)>=(nn-j)))|((i==0)|(i==n))
%(i>=j)&((n-i)>=(nn-j)))|((i==0)|(i==n))为可以存在的状态的约束条件
A(kx,1:
3)=[i,j,1];%生成状态数组集合D`
A(kx+1,1:
3)=[i,j,0];
kx=kx+2;
end
end
j=nn;
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%将状态向量生成抽象矩阵
k=(1/2)*size(A,1);
CX=zeros(2*k,2*k);
a=size(d,1);
fori=1:
2*k
forj=1:
a
c=A(i,:
)+d(j,:
);
x=find((A(:
1)==c
(1))&(A(:
2)==c
(2))&(A(:
3)==c(3)));
v(i,x)=1;%x为空不会改变v值
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%dijstra算法
x=1;y=size(A,1);
m=size(v,1);
T=zeros(m,1);
T=T.^-1;
lmd=T;
P=T;
S=zeros(m,1);
S(x)=1;
P(x)=0;lmd(x)=0;
k=x;
while
(1)
a=find(S==0);
aa=find(S==1);
ifsize(aa,1)==m
break;
end
forj=1:
size(a,1)
pp=a(j,1);
ifv(k,pp)~=0
ifT(pp)>(P(k)+v(k,pp))
T(pp)=(P(k)+v(k,pp));
lmd(pp)=k;
end
end
end
mi=min(T(a));
ifmi==inf
break;
else
d=find(T==mi);
d=d
(1);
P(d)=mi;
T(d)=inf;
k=d;
S(d)=1;
end
end
iflmd(y)==inf
jueche='cannotreach';
return;
end
jueche
(1)=y;
g=2;h=y;
while
(1)
ifh==x
break;
end
jueche(g)=lmd(h);
g=g+1;
h=lmd(h);
end
jueche=A(jueche,:
);
jueche(:
3)=[];
clearall%080817
clc %n为商人数,m为仆人数,h为每次过河的最多人数
n=3;m=3;h=2;%初始状态及数据
m0=0;n0=0;
tic
LS=0; %允许的状态集合S与个数LS
LD=0; %允许的决策集合D与个数LD
fori=0:
n
forj=0:
m
ifi>=j&n-i>=m-j|i==n|i==0
LS=LS+1;S(LS,:
)=[ij];
end
ifi+j>0&i+j<=h&(i>=j|i==0)
LD=LD+1;D(LD,:
)=[ij];
end
end
end
%用搜寻法找出符合条件的渡河方案
%……………………………………………………………………………………………$$
N=15;
Q1=inf*ones(2*N,2*N);
Q2=inf*ones(2*N,2*N);
t=1;
le=1;
q=[mn];
f0=0;%判断循环终止标记
whilef0~=1&t k=1;
sa=[];
sb=[];
fori0=1:
le %第n次允许的策略集逐次搜索
s0=q(i0,:
);
iff0==1
break
end
fori=1:
LD %由s0搜索D后得到允许的状态
s1=s0+(-1)^t*D(i,:
);
ifs1==[m0,n0]
sa=[m0,n0];
sb=D(i,:
);
f0=1;
break
end
forj=2:
LS-1 %搜索对比S后允许状态
ifs1==S(j,:
)
ifk==1
sa(k,:
)=s1;
sb(k,:
)=D(i,:
);
k=k+1;
break
end
ifk>1 %对重复状态删除处理
f1=0;
forii=1:
k-1
ifs1==sa(ii,:
)
f1=1;
break
end
end
end %……
iff1==0
sa(k,:
)=s1;
sb(k,:
)=D(i,:
);
k=k+1;
break
end
end
end %…………………
end %………………………………
end %……………………………………………
q=sa;
le=size(q,1);
Q1(1:
le,t*2-1:
t*2)=q;
Q2(1:
le,t*2-1:
t*2)=sb;
t=t+1;
end %………………………………………………………$$
%在可行方案集合中逆向搜寻唯一方案
%……………………………………………………………………………………………¥¥
tr=t-1;saa1=sa;
SA=zeros(tr,2);SB=zeros(tr,2);
fork=tr:
-1:
2
k1=k-1;f0=0;
sbb=Q2(:
k*2-1:
k*2);
saa=Q1(:
k1*2-1:
k1*2);
fori=1:
2*N
saa2=saa1-(-1)^k*sbb(i,:
);
forj=1:
2*N
ifsaa2==saa(j,:
)
saa1=saa2;
sbb1=sbb(i,:
);
f0=1;
break
end
end
iff0==1
break
end
end
SA(k1,:
)=saa1;
SB(k,:
)=sbb1;
end
SA(tr,:
)=[m0n0];
SB(1,:
)=[m,n]-SA(1,:
);
%………………………………………………………………………………………………¥¥
disp'初始状态:
'
X0=[m,n]
disp'状态为:
'
SA
disp'决策为:
'
SB
toc