示例:
输入:
5 5
1 0 1 1 0
1 1 0 1 1
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5
输出:
8
(0, 0),(1, 0),(1, 1),(2, 1),(3, 1),(3, 2),(3, 3),(3, 4),(4, 4)
D,R,D,D,R,R,R,D
代码:
from queue import Queue
n,m=map(int ,input().split()) #长度和宽度
g=[list(map(int,input().split()))for i in range(n)] #g是迷宫地图 1是可以走,0是障碍物
dir=[[-1,0],[1,0],[0,-1],[0,1]] #dir是方向数组
dir_letter=['U','D','L','R'] #dir_letter是对应的方向,up,down,left,right
path=[] #path,存所有走过的路径,(x,y)
dirpath={} #dir_path存每一步的dir_letter,上一步到这一步怎么走的,U,D,L或者,R
father={} #father,是字典,存这一步的上一步是哪一个
vis=[[0 for i in range(m)]for i in range(n)] #vis的作用有两个,一个是筛选,没有走过的点都是0,一个是记录,记录到这一步的步数
x1,y1,x2,y2=map(int,input().split()) #x1,y1,x2,y2是入口和出口
q=Queue() #建立队列
def ins(x,y): #ins函数,看是否在迷宫以内防止出界
if 0<=x<=n-1 and 0<=y<=m-1:
return 1
else:
return 0
def bfs(x,y): #bfs主函数,x,y是入口
global path,father,dirpath,vis #定义全局变量,这是python和c++的区别之一,pyhon不定义会报错
q.put([x,y]) #先把入口入队列
vis[x][y]=1 #入口已经走过,所以vis为1,但是现在还没有走路,步数为0,所以最后返回值应该减一
father[(x,y)]=0 #入口上一个没有结点,为0 (None 和is not None对应),这里改成None,下面要改为 while cur is not None
while q: #当队列不为空
(nx,ny)=q.get() #get(),出队,返回出队值,有没有()都可以
if nx==x2-1 and ny==y2-1: #如果到了终点
cur=nx,ny
while cur: #开始从终点找到起点路径(起点cur==0)
path.append(cur)
cur=father[cur]
path=path[::-1] #倒转,得到真正路径
break
for i in range(4): #四个方向遍历
dx=nx+dir[i][0]
dy=ny+dir[i][1]
if ins(dx,dy)and vis[dx][dy]==0 and g[dx][dy]==1: #条件判断,在迷宫内,没有走过,不是墙壁可以走
q.put([dx,dy]) #入队
vis[dx][dy]=vis[nx][ny]+1 #步数+1
dirpath[(dx,dy)]=dir_letter[i] #保存这一步是怎么走过来的
father[(dx,dy)]=nx,ny #保存上一步是在哪里
return vis[x2-1][y2-1]-1 #返回走了多少步
print(bfs(x1-1,y1-1)) #输出走了多少步
for i in range(len(path)-1): #输出路径
print(path[i],end=",")
print(path[len(path)-1])
for i in path[1:len(path)-1]: #输出动作
print(dirpath[i],end=",")
print(dirpath[path[len(path)-1]])
测试用例
5 5
1 0 1 1 0
1 1 0 1 1
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5
以下一段话取自他人博客bfs
其实对于BFS来说,while里面的for循环更像是一种分身机制; 假如你现在有一只老鼠(代码里的cur)帮你走迷宫。当它遇到一个二叉分叉口(代码里的四个方向)的时候,他不会去选择其中一个去走,而是变出两个分身(代码里的next_pos)替它去走(之后自己保持原地不动,在队列里面它就是出队了,相当于在之后的搜索里面起不到任何作用)。这样的话,每碰到一个分叉口就变出更多的分身。这里的分叉口其实就是对于我们迷宫中的每一个位置,而分叉口的个数则是当前能走的方向数(没有走过且不是墙且在地图内)。对于每一时刻的老鼠(其实每一时刻的所有老鼠,都是上一时刻所有老鼠的分身), 我们让它们每次只走一步。这样子就能保证在任意时刻每个老鼠所走的步数是相同的,那么只要在某个时刻有一只老鼠到达终点, 那它的路径一定就是最短的。这就是为什么BFS总能找到最短路径。那如何保存这个最短路径呢?我们知道,每一个老鼠都是由之前的某个老鼠分身而来的,那么我们只需要记录每个老鼠是由谁分身而来的就可以了。这样子,我们抓到最后一只找到出口的老鼠,不断地从它身上寻找它的源体,最终就能找到一开始放在入口的那只老鼠。然后我们再把这个过程倒过来,那么就得到了从入口到出口的一个最短路径了,这就是BFS的全过
受益匪浅