问题描述:
【传教士和食人者问题】
在河的左岸有3个传教士、1条船和3个食人者,传教士们想用这条船将所有的成员运到河的右岸,但是受到以下条件的限制:
(1)船每次最多只能装2个乘客(传教士和食人者都会划船);
(2)在任何岸边,如果食人者数目超过传教士则传教士将被食人者吃掉。
(3)假定食人者会服从任何一种过河安排。
C++版本:
#include
#include
using namespace std;
int m,c,k;//m个传教士,n个食人者,船上可以有k个人
int xx[]={0,0,1,1,2};//每次可以上船的人员数量
int yy[]={1,2,0,1,0};
struct zt{
int lm;
int lc;
int rm;
int rc;
int ship;
int top;
};
queue<zt>open;
struct zt temp[1000];
int index=0;
int Isdangerous(zt temp)
{
if((temp.lm>=temp.lc&&temp.rm>=temp.rc&&temp.lm>=0&&temp.lc>=0&&temp.rm>=0&&temp.rc>=0)||
(temp.lm>=0&&temp.lc>=0&&temp.rm>=0&&temp.rc>=0&&temp.lm==0&&temp.rm>=temp.rc)||
(temp.lm>=0&&temp.lc>=0&&temp.rm>=0&&temp.rc>=0&&temp.lm>=temp.lc&&temp.rm==0))
{
return 1;
}
return 0;
}
int pd(zt p,int top)
{
for(int i=0;i<top;i++)
{
if(temp[i].lm==p.lm&&temp[i].lc==p.lc&&temp[i].rm==p.rm&&temp[i].rc==p.rc&&temp[i].ship==p.ship)
{
return 0;
}
}
return 1;
}
void bfS()
{
while(!open.empty())
{
zt temp1=open.front();
int x1=temp1.lm;
int y1=temp1.lc;
int x2=temp1.rm;
int y2=temp1.rc;
for(int i=0;i<5;i++)
{
if(temp1.ship==1){
zt temp2;
temp2.lm=x1-xx[i];
temp2.lc=y1-yy[i];
temp2.rm=x2+xx[i];
temp2.rc=y2+yy[i];
temp2.ship=-temp1.ship;
temp2.top=temp1.top+1;
if(temp2.lm==0&&temp2.lc==0&&temp2.rm==3&&temp2.rc==3)
{
goto loop;
}
if(Isdangerous(temp2)==1&&pd(temp2,index)==1)
{
temp[index++]=temp2;
open.push(temp2);
}
}
if(temp1.ship==-1){
zt temp2;
temp2.lm=x1+xx[i];
temp2.lc=y1+yy[i];
temp2.rm=x2-xx[i];
temp2.rc=y2-yy[i];
temp2.ship=-temp1.ship;
temp2.top=temp1.top+1;
if(Isdangerous(temp2)==1&&pd(temp2,index)==1)
{
temp[index++]=temp2;
open.push(temp2);
}
}
}
open.pop();
}
loop:;
}
int main()
{
zt p;
p.lm=3;
p.lc=3;
p.rm=0;
p.rc=0;
p.ship=1;
p.top=0;
open.push(p);
temp[index++]=p;
bfS();
cout<<"初始状态:"<<3<<' '<<3<<' '<<0<<' '<<0<<endl;
for(int i=3;i<index-1;i++)
{
if(temp[i].ship==1)
{
cout<<"B----->A:";
cout<<temp[i].lm<<' '<<temp[i].lc<<' '<<temp[i].rm<<' '<<temp[i].rc<<endl;
}
if(temp[i].ship==-1)
{
cout<<"A----->B:";
cout<<temp[i].lm<<' '<<temp[i].lc<<' '<<temp[i].rm<<' '<<temp[i].rc<<endl;
}
}
cout<<"目标状态:"<<0<<' '<<0<<' '<<3<<' '<<3<<endl;
return 0;
}
python版本:
from queue import Queue
class zt:
def __init__(self,x1,y1,x2,y2,ship,top):
self.lm=x1
self.lc=y1
self.rm=x2
self.rc=y2
self.ship=ship
self.top=top
temp = Queue(maxsize=0)
xx=[0,0,1,1,2]
yy=[1,2,0,1,0]
list=[]#对象list
index=0#对象指针
def Isdangerous(temp):
if (( temp.lm >= temp.lc and temp.rm >= temp.rc and temp.lm >= 0 and temp.lc >= 0 and temp.rm >= 0 and temp.rc >= 0)
or (temp.lm >= 0 and temp.lc >= 0and temp.rm >= 0 and temp.rc >= 0 and temp.lm == 0 and temp.rm >= temp.rc)
or (temp.lm >= 0 and temp.lc >= 0 and temp.rm >= 0 and temp.rc >= 0 and temp.lm >= temp.lc and temp.rm == 0)):
return 1
else:
return 0
def pd(p,index):
for i in range(0,index):
if(list[i].lm==p.lm and list[i].lc==p.lc and list[i].rm==p.rm and list[i].rc==p.rc and list[i].ship==p.ship):
return 0
return 1
def fin(temp):
if temp.lm==0 and temp.lc==0 and temp.rm==3 and temp.rc==3:
return 1
return 0
def bfs():
global index
while temp.empty()==0:
temp1=temp.get()
x1=temp1.lm
y1=temp1.lc
x2=temp1.rm
y2=temp1.rc
for i in range(0,5):
x=xx[i]
y=yy[i]
if temp1.ship==1:
temp2=zt(x1-x,y1-y,x2+x,y2+y,-1,temp1.top+1)
if fin(temp2)==1:
return
if Isdangerous(temp2)==1and pd(temp2,index)==1:
temp.put(temp2)
list.append(temp2)
index+=1
else :
temp2 = zt(x1 + x, y1 + y, x2 - x, y2 - y, 1, temp1.top + 1)
if Isdangerous(temp2) == 1 and pd(temp2, index) == 1:
temp.put(temp2)
list.append(temp2)
index += 1
start=zt(3,3,0,0,1,0)
temp.put(start)
list.append(start)
index+=1
bfs()
print('初始状态',3,3,0,0)
for item in range(3,index-1):
if list[item].ship==-1:
if item==3:
print(" A----->B:", end='')
else:
print("A----->B:",end='')
print(list[item].lm,list[item].lc,list[item].rm,list[item].rc,'\n',end=' ')
if list[item].ship==1:
print("B----->A:",end='')
print(list[item].lm,list[item].lc,list[item].rm,list[item].rc,'\n',end=' ')
print("目标状态:",0,0,3,3)