# 计算船的合法状态空间defget_states(k):# 船准备跑第k趟global n, m, x
if k %2==0:# 从左到右,只考虑原左岸人数
s1, s2 = n -sum(s[0]for s in x), n -sum(s[1]for s in x)else:# 从右到左,只考虑原右岸人数(将船的历史状态累加可得!!!)
s1, s2 =sum(s[0]for s in x),sum(s[1]for s in x)for i inrange(s1 +1):for j inrange(s2 +1):if0< i + j <= m and(i * j ==0or i >= j):# 生成船的合法状态yield[(-i,-j),(i, j)][k %2==0]# 冲突检测defconflict(k):# 船开始跑第k趟global n, m, x
# 若船上载的人与上一趟一样(会陷入死循环!!!!)if k >0and x[-1][0]==-x[-2][0]and x[-1][1]==-x[-2][1]:returnTrue# 任何时候,船上传教士人数少于野人,或者无人,或者超载(计算船的合法状态空间时已经考虑到了。)# 任何时候,左岸传教士人数少于野人if0< n -sum(s[0]for s in x)< n -sum(s[1]for s in x):returnTrue# 任何时候,右岸传教士人数少于野人if0<sum(s[0]for s in x)<sum(s[1]for s in x):returnTruereturnFalse# 无冲突defdfs(k):# 船准备跑第k趟global n, m, x, suc, ans
if suc:return x # 终止所有递归if n -sum(s[0]for s in x)==0and n -sum(s[1]for s in x)==0:# 左岸人数全为0print(x)for i inrange(len(x)):if(i%2==0):print("第%d趟:从左岸到右岸%d个传教士、%s个野人"%(i+1, x[i][0], x[i][1]))else:print("第%d趟:从右岸到左岸%d个传教士、%d个野人"%(i+1,-x[i][0],-x[i][1]))
suc =Trueelse:for state in get_states(k):# 遍历船的合法状态空间
x.append(state)ifnot conflict(k):
dfs(k +1)# 深度优先
x.pop()# 回溯
n =3# n个传教士、n个野人
m =2# 船能载m人
x =[]# 一个解,就是船的一系列状态
X =[]# 一组解
suc =False# 全局终止标志
ans =[]# 测试
dfs(0)
猴子摘香蕉# -*- coding: utf-8 -*-'''猴子摘香蕉问题''''''monkey Location of monkeybox Location of boxonbox 0:monkey not on 1:monkey on the boxpick_banana 1: banana pickedbanana Location of banana'''class State: def __init__(self, monkey=-1, on