'''三商人三仆人过河问题,有一条船,最多只允许乘2人,要求商人数不少于仆人数,
设计过河方案'''
'''基于状态空间搜索,深度优先搜索'''
test=[[True,True,True,True],##### 状态允许,作为检验下一步的依据
[True,True,False,False],
[True,True,True,False],
[True,True,True,True]]
###有效的操作
dirs=[[1,1],[0,2],[0,1],[1,0],[2,0]]
start=[3,3,1]###开始状态
end=[0,0,0]###结束状态
list2=[start]
###mark函数用于标记已经存在的状态,如果这个状态可行,加入list2中。
def mark(nextp):
list2.append(nextp)
return True
#######判断解的可行性,如果可行,加入栈中
def passable(nextp):
k=[]
a=[3-nextp[0],3-nextp[1]]
for i in a:
if i<0 or i>3:
return False
if test[a[0]][a[1]] and test[nextp[0]][nextp[1]]:
if nextp not in list2:
return True
else:
return False
#####主函数
def solver(start,end):
if start==end:
print(start)
return
stack=[] #建立栈
stack.append((start,0)) #放入初始状态
while stack:
n=len(stack)
#nxt 记录记录方向
pos,nxt=stack.pop()
#### 5表示操作数
for i in range(nxt,5):
'''计算下一步,n是栈的长度,n为奇数,表示过河,n为偶数,表示将船返回'''
nextp=[pos[0]+pow(-1,n)*dirs[i][0],pos[1]+pow(-1,n)*dirs[i][1],(n+1)%2]
####搜索结束的条件
if nextp==end:
stack.append((nextp,0))
print('问题解决')
return stack
####判断解是否可行
if passable(nextp):
###如果可行,将原状态先放入栈中,并将 方向+1
stack.append((pos,i+1))
###标记解,防止无限循环
mark(nextp)
###将下一状态放入栈中
stack.append((nextp,0))
###结束循环
break
st=solver(start,end)
for i in st:
print('左岸商人数: %d'%i[0][0],'左岸仆人数: %d'%i[0][1])
左岸商人数: 3 左岸仆人数: 3
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 0
左岸商人数: 3 左岸仆人数: 1
左岸商人数: 1 左岸仆人数: 1
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 3
左岸商人数: 0 左岸仆人数: 1
左岸商人数: 0 左岸仆人数: 0
全部过河,共11步
设计过河方案'''
'''基于状态空间搜索,深度优先搜索'''
test=[[True,True,True,True],##### 状态允许,作为检验下一步的依据
[True,True,False,False],
[True,True,True,False],
[True,True,True,True]]
###有效的操作
dirs=[[1,1],[0,2],[0,1],[1,0],[2,0]]
start=[3,3,1]###开始状态
end=[0,0,0]###结束状态
list2=[start]
###mark函数用于标记已经存在的状态,如果这个状态可行,加入list2中。
def mark(nextp):
list2.append(nextp)
return True
#######判断解的可行性,如果可行,加入栈中
def passable(nextp):
k=[]
a=[3-nextp[0],3-nextp[1]]
for i in a:
if i<0 or i>3:
return False
if test[a[0]][a[1]] and test[nextp[0]][nextp[1]]:
if nextp not in list2:
return True
else:
return False
#####主函数
def solver(start,end):
if start==end:
print(start)
return
stack=[] #建立栈
stack.append((start,0)) #放入初始状态
while stack:
n=len(stack)
#nxt 记录记录方向
pos,nxt=stack.pop()
#### 5表示操作数
for i in range(nxt,5):
'''计算下一步,n是栈的长度,n为奇数,表示过河,n为偶数,表示将船返回'''
nextp=[pos[0]+pow(-1,n)*dirs[i][0],pos[1]+pow(-1,n)*dirs[i][1],(n+1)%2]
####搜索结束的条件
if nextp==end:
stack.append((nextp,0))
print('问题解决')
return stack
####判断解是否可行
if passable(nextp):
###如果可行,将原状态先放入栈中,并将 方向+1
stack.append((pos,i+1))
###标记解,防止无限循环
mark(nextp)
###将下一状态放入栈中
stack.append((nextp,0))
###结束循环
break
st=solver(start,end)
for i in st:
print('左岸商人数: %d'%i[0][0],'左岸仆人数: %d'%i[0][1])
print('全部过河,共%d步'%len(st))
运行结果:
左岸商人数: 3 左岸仆人数: 3
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 2
左岸商人数: 3 左岸仆人数: 0
左岸商人数: 3 左岸仆人数: 1
左岸商人数: 1 左岸仆人数: 1
左岸商人数: 2 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 2
左岸商人数: 0 左岸仆人数: 3
左岸商人数: 0 左岸仆人数: 1
左岸商人数: 0 左岸仆人数: 0
全部过河,共11步