题目:
由空地和墙组成的迷宫中有一个球。球可以向上下左右四个方向滚动,但在遇到墙壁前不会停止滚动。当球停下时,可以选择下一个方向。
给定球的起始位置,目的地和迷宫,找出让球停在目的地的最短距离。距离的定义是球从起始位置(不包括)到目的地(包括)经过的空地个数。如果球无法停在目的地,返回 -1。
迷宫由一个0和1的二维数组表示。 1表示墙壁,0表示空地。你可以假定迷宫的边缘都是墙壁。起始位置和目的地的坐标通过行号和列号给出。
解答:
class Solution:
def shortestDistance(self, maze: List[List[int]], start: List[int], destination: List[int]) -> int:
m=len(maze)
n=len(maze[0])
#四个方向
directions=[[-1,0],[1,0],[0,-1],[0,1]]
#distance[i][j]: 记录从起始位置start到 (i, j) 的最小步数
distance=[[float('inf')]*n for _ in range(m)]
#初始化
distance[start[0]][start[1]]=0
q=[(start[0],start[1])]
while q:
curx,cury=q.pop(0)
#选择某个方向滚动直到停下
for dx,dy in directions:
x,y=curx+dx,cury+dy
count=0
#一直沿着该方向前进,直到碰到墙壁停止
while x>=0 and x<m and y>=0 and y<n and (maze[x][y]==0):
x+=dx
y+=dy
count+=1
#从墙壁回退一步
x-=dx
y-=dy
tmp=distance[curx][cury]+count
#若tmp小于终点当前的最小步数,则对其进行更新
if tmp<distance[x][y]:
distance[x][y]=tmp
q.append((x,y))
x,y=destination
return distance[x][y] if distance[x][y]!=float('inf') else -1