-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path1091_shortest_path_in_binary_matrix.py
130 lines (105 loc) · 4.03 KB
/
1091_shortest_path_in_binary_matrix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
from typing import List
import heapq
class Solution:
def shortestPathBinaryMatrix0(self, grid: List[List[int]]) -> int:
m, n = len(grid) - 1, len(grid[0]) - 1
if grid[0][0] == 1 or grid[m][n] == 1:
return -1
queue = [(0, 0)]
grid[0][0] = 1
ans = 0
offsets = ((0, 1), (0, -1), (1, 0), (-1, 0), (-1, 1), (-1, -1), (1, 1), (1, -1))
while queue:
l = len(queue)
ans += 1
for i in range(l):
x, y = queue[i]
if x == m and y == n:
return ans
for (dx, dy) in offsets:
next_x, next_y = x + dx, y + dy
if next_x < 0 or next_x > m or next_y < 0 or next_y > n or grid[next_x][next_y] != 0:
continue
queue.append((next_x, next_y))
grid[next_x][next_y] = 1
queue = queue[l:]
return -1
def shortestPathBinaryMatrix2(self, grid: List[List[int]]) -> int:
m, n = len(grid) - 1, len(grid[0]) - 1
if grid[0][0] == 1 or grid[m][n] == 1:
return -1
from queue import PriorityQueue
def get_distance(x: int, y: int):
return max(m - x, n - y)
start = (0, 0, 0, 1)
pq = PriorityQueue()
pq.put(start)
grid[0][0] = 1
while not pq.empty():
_, x, y, step = pq.get()
print(x, y, step)
if x == m and y == n:
return step
for (dx, dy) in ((1, 1), (0, 1), (1, 0), (0, -1), (-1, 0), (-1, 1), (-1, -1), (1, -1)):
next_x, next_y = x + dx, y + dy
if next_x < 0 or next_x > m or next_y < 0 or next_y > n or grid[next_x][next_y] != 0:
continue
pq.put((step + get_distance(next_x, next_y), next_x, next_y, step + 1))
print(f"[{x},{y}] -->[{next_x},{next_y}]", step + 1, pq.queue)
grid[next_x][next_y] = 1
return -1
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
m, n = len(grid) - 1, len(grid[0]) - 1
if grid[0][0] == 1 or grid[m][n] == 1:
return -1
def heuristic(x, y):
return max(abs(m - x), abs(n - y))
start = (0, (0, 0, 1))
pq = []
heapq.heappush(pq, start)
visited = set() # must use a set to mark, can not replace by setting grid value = 1
while pq:
_, (x, y, step) = heapq.heappop(pq)
if (x, y) in visited:
continue
visited.add((x, y))
if x == m and y == n:
return step
for (dx, dy) in [(-1, -1), (1, 0), (0, 1), (-1, 0), (0, -1), (1, 1), (1, -1), (-1, 1)]:
next_x, next_y = x + dx, y + dy
if next_x < 0 or next_x > m or next_y < 0 or next_y > n or grid[next_x][next_y] != 0:
continue
heapq.heappush(pq, (step + heuristic(next_x, next_y), (next_x, next_y, step + 1)))
return -1
def test():
s = Solution()
for (grid, target) in [
(
[[0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 1, 1, 0, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 1, 0, 0, 1, 1],
[0, 0, 1, 1, 1, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 1, 0]
], 11
),
(
[[0, 0, 0, 0, 1, 1],
[0, 1, 0, 0, 1, 0],
[1, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 1],
[0, 1, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 0]],
7
),
(
[[0, 0, 0], [1, 1, 0], [1, 1, 0]], 4
)
]:
ans = s.shortestPathBinaryMatrix(grid)
assert ans == target, f"expect {target}, got {ans}"
if __name__ == "__main__":
test()