queue =[enter]paths ={enter:[enter]}while queue: v = queue.pop(0)if v==exit:return path[v]for u inneighbors(p):if u in path:continueifwall(u, v):continue queue.append(u) paths[u]= paths[v]+[u]return[]
这里我们简单起见只返回了任一可行解。留意这里因为要记录最后可行解的路径,我们用paths: point -> path来保存在任一点到达这一点的路径,并代替了使用vis数组来判断是否已经访问了某一点。
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
nums = "0123456789"
def neighbor(s):
for i in range(4):
yield s[:i]+nums[(nums.index(s[i])+1)%10]+s[i+1:]
yield s[:i]+nums[(nums.index(s[i])-1)%10]+s[i+1:]
start = "0000"
if start in deadends: return -1
queue = [(start, 0)]
vis = set([start] + deadends)
while queue:
s, step = queue.pop(0)
if s==target: return step
for ns in [x for x in neighbor(s) if x not in vis]:
queue.append((ns, step+1))
vis.add(ns)
return -1
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
nums = "0123456789"
def neighbor(s):
for i in range(4):
yield s[:i]+nums[(nums.index(s[i])+1)%10]+s[i+1:]
yield s[:i]+nums[(nums.index(s[i])-1)%10]+s[i+1:]
start = "0000"
if start==target: return 0
if start in deadends: return -1
vis = set([start, target]+deadends)
vis1, vis2 = set([start]), set([target])
step = 0
while vis1 and vis2:
if len(vis1)>len(vis2): vis1, vis2 = vis2, vis1
vislevel = set()
for s in vis1:
for ns in neighbor(s):
if ns in vis2: return step+1
if ns not in vis|vislevel:
vislevel.add(ns)
vis.add(ns)
step += 1
vis1 = vislevel
return -1
def shortestDistance(grid):
m, n = len(grid), len(grid[0])
dx, dy = (1, -1, 0, 0), (0, 0, 1, -1)
def inboard(x, y, vis):
return 0<=x<m and 0<=y<n and grid[x][y]==0 and not vis[x][y]
def expand(i, j):
queue.append((i, j, 0))
vis = [[False]*n for _ in range(m)]
while queue:
x, y, d = queue.pop(0)
for di in range(4):
nx, ny = x+dx[di], y+dy[di]
if not inboard(nx, ny, vis): continue
cnts[nx][ny] += 1
dist[nx][ny] += d+1
vis[nx][ny] = True
queue.append((nx, ny, d+1))
cnts = [[0]*n for _ in range(m)]
dist = [[0]*n for _ in range(m)]
queue = []
cnt = 0
for i in range(m):
for j in range(n):
if grid[i][j]==1:
cnt += 1
expand(i, j)
res = float('inf')
for i in range(m):
for j in range(n):
if cnts[i][j]==cnt:
res = min(res, dist[i][j])
return res if res < float('inf') else -1
def solveTiltMazeBFS(maze, start, goal):
m, n = len(maze), len(maze[0])
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
def validCell(x, y, i):
return 0<=x<m and 0<=y<n and (x, y, i) not in path and maze[x][y] != 'x'
sx, sy = start
queue = [(sx, sy, 4)]
path = {(sx, sy, 4): [(sx, sy, 4)]}
while queue:
x, y, d = queue.pop(0)
if (x, y) == goal:
return path[(x, y, d)]
curPath = path[(x, y, d)]
if d==4: # stationary ball
for i in range(4):
dx, dy = directions[i]
nx, ny = x+dx, y+dy
if validCell(nx, ny, i):
queue.append((nx, ny, i))
path[(nx, ny, i)] = curPath + [(nx, ny, i)]
else: # if ball is rolling
dx, dy = directions[d]
nx, ny = x+dx, y+dy
if validCell(nx, ny, d):
queue.append((nx, ny, d))
path[(nx, ny, d)] = curPath + [(nx, ny, d)]
if not validCell(nx, ny, 4):
queue.append((x, y, 4))
path[(x, y, 4)] = curPath + [(x, y, 4)]
return []
# tiltMaze = [
# 'Sx--',
# '----',
# 'xx--',
# '--G-',
# '----',
# ]
# path = solveTiltMazeBFS(tiltMaze, (0,0), (3,2))
def solveTiltMazeDFS(maze, start, goal):
m, n = len(maze), len(maze[0])
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
def validCell(x, y, i):
return 0<=x<m and 0<=y<n and (x, y, i) not in vis and maze[x][y] != 'x'
def explore(nx, ny, d):
vis.append((nx, ny, d))
if dfs(nx, ny, d): return True
vis.pop()
return False
def dfs(x, y, d):
if (x, y) == goal:
res[:] = [(x, y, d) for x, y, d in vis]
return True
if d==4: # stationary ball
for i in range(4):
dx, dy = directions[i]
nx, ny = x+dx, y+dy
if validCell(nx, ny, i) and explore(nx, ny, i): return True
else: # if ball is rolling
dx, dy = directions[d]
nx, ny = x+dx, y+dy
if validCell(nx, ny, d) and explore(nx, ny, d): return True
elif not validCell(nx, ny, 4) and explore(x, y, 4): return True
return False
sx, sy = start
res = []
vis = [(sx, sy, 4)]
if dfs(sx, sy, 4):
return res
return []
# tiltMaze = [
# 'Sx--',
# '----',
# 'xx--',
# '--G-',
# '----',
# ]
# path = solveTiltMazeDFS(tiltMaze, (0,0), (3,2))