双向广搜:
应用场景:
有确定的起点s和终点t;把从起点到终点的单向搜索,变换为分别从起点出发和从终点出发的“相遇”问题。
操作:从起点s(正向搜索)和终点t(逆向搜索)同时开始搜索,当两个搜索产生相同的一个子状态v时就结束,v是相遇点。得到的s-v-t是一条最佳路径。
队列:一般用两个队列分别处理正向BFS和逆向BFS。
跳蚱蜢题目详见http://t.csdn.cn/RHvrj
由于起点和终点的串不同,正向BFS和逆向BFS扩展的下一层数量也不同,也就是进入2个队列的串的数量不同,先处理较小的队列,可以加快搜索速度
from queue import *
meet=False
def extend(q,m1,m2):
global meet
s=q.get() #从队头删除,并返回,012345678
for i in range(len(s)):
if s[i]=='0': #确定空盘子0的位置
break
for j in range(4):
news=list(s)
if j==0:
news[(i-2+9)%9],news[i]=news[i],news[(i-2+9)%9] #四种情况,交换
if j==1:
news[(i-1+9)%9],news[i]=news[i],news[(i-1+9)%9]
if j==2:
news[(i+1+9)%9],news[i]=news[i],news[(i+1+9)%9]
if j==3:
news[(i+2+9)%9],news[i]=news[i],news[(i+2+9)%9]
a="".join(news) #重新转化为字符串
if a in m2:
print(m1[s]+1+m2[a])
meet=True
return
if a not in m1:
q.put(a) #从队尾插入
m1[a]=m1[s]+1 #向字典中添加
meet=False
q1=Queue(); q2=Queue() #q1正向搜索,q2逆向搜索
q1.put("012345678"); q2.put("087654321")
mp1={'012345678':0}; mp2={'087654321':0} #定义字典,用于判重
while not q1.empty() and not q2.empty(): #队列是否为空
if q1.qsize()<=q2.qsize(): #先处理较小的队列
extend(q1,mp1,mp2)
else:
extend(q2,mp2,mp1)
if meet==True: #相遇过直接退出
break