BFS简介
BFS和DFS(深度优先搜索)差不多,其特点可以概括为一下3点:
- 逐层搜索:一层一层地搜索,这样可以找到最短路径。
- 使用队列:主要作用是为了实现“逐层搜索”
- 不是递归:DFS一般用使用递归的手段,但BFS使用的是基于队列的循环
需要的数据结构
实现BFS可能用到字典dict,集合set,队列queue
1.字典dict的功能是为了记录,到达当下搜索的状态,一共走了多少步?举个例子:相当于记录,核污水到达太平洋东区花了多少天。
2.队列queue是为了实现“逐层搜索”,这样可以始终从最浅的那一层开始搜索,有利于及时地找到短的那条路(在走迷宫的场景中)。在python中建议使用deque,而不是像c++一样用queue,具体原因不多说。
3.集合set为了记录已经搜索到的状态,其实,上面实现的字典dict也相当于记录了搜索到的所有状态,因此set是多余的(还是有人这么写)。注意,不能用列表记录:检查一个元素是否在列表中的时间复杂度为Θ(n),相反,set和dict的时间复杂度几乎为Θ(1),具体原因不多说。
做题实战
关键步骤:
- 准备好数据结构
- 开始循环,从当前的点出发,去找新的点x -> y
- 检查当前状态是否搜到结果,搜到了直接返回答案
这道题被官方标注为困难,其实还好啦
from collections import deque
q=deque()#队列
s1=input()
s2=input()
d=dict()#字典,记录搜索到的状态和相应的步数
#准备数据
start=s1.find("*")
end=s2.find("*")
n=len(s1)
#以空杯为对象
def bfs(queue,s1,start):
d[s1]=0
queue.appendleft((start,s1))
while queue:
x,s=queue.popleft()#x为当前的位置
for y in [x-2,x+2,x-3,x+3,x-1,x+1]:#y代表的是下一步的位置
if 0<=y<=n-1:#检查这个位置合不合法
new_s=list(s)#这里需要复制列表,而不是引用
new_s[x],new_s[y]=new_s[y],new_s[x]
new_s=''.join(new_s)
if new_s not in d:
queue.append((y,new_s))
d[new_s]=d[s]+1#更新
if new_s ==s2:#检查当前状态是否为答案
return d[new_s]
ans=bfs(q,s1,start)
print(ans)