@@ -116,6 +116,12 @@ tags:
116116
117117### 方法一:DFS 建图 + 堆优化版 Dijkstra 算法
118118
119+ 我们注意到,网格的大小为 $m \times n$,其中 $m, n \leq 100$。因此,我们可以初始化起点坐标 $(sx, sy) = (100, 100)$,并假设网格的大小为 $200 \times 200$。然后,我们可以使用深度优先搜索(DFS)来探索整个网格,并构建一个表示网格的二维数组 $g$,其中 $g[ i] [ j ] $ 表示从起点 $(sx, sy)$ 到坐标 $(i, j)$ 的移动消耗。如果某个单元格不可达,则将其值设为 $-1$。我们将终点坐标存储在 $\textit{target}$ 中,如果无法到达终点,则 $\textit{target} = (-1, -1)$。
120+
121+ 接下来,我们可以使用堆优化版的 Dijkstra 算法来计算从起点 $(sx, sy)$ 到终点 $\textit{target}$ 的最小消耗路径。我们使用一个优先队列来存储当前的路径消耗和坐标,并使用一个二维数组 $\textit{dist}$ 来记录从起点到每个单元格的最小消耗。当我们从优先队列中取出一个节点时,如果该节点是终点,则返回当前的路径消耗作为答案。如果该节点的路径消耗大于 $\textit{dist}$ 中记录的值,则跳过该节点。否则,我们遍历该节点的四个邻居,如果邻居可达且通过该节点到达邻居的路径消耗更小,则更新邻居的路径消耗并将其加入优先队列。
122+
123+ 时间复杂度 $O(m \times n \log(m \times n))$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。
124+
119125<!-- tabs:start -->
120126
121127#### Python3
@@ -132,55 +138,57 @@ tags:
132138# def move(self, direction: str) -> int:
133139#
134140#
135- # def isTarget(self) -> None :
141+ # def isTarget(self) -> bool :
136142#
137143#
138144
139145
140146class Solution (object ):
141- def findShortestPath (self , master : ' GridMaster' ) -> int :
142- def dfs (i , j ) :
147+ def findShortestPath (self , master : " GridMaster" ) -> int :
148+ def dfs (x : int , y : int ) -> None :
143149 nonlocal target
144150 if master.isTarget():
145- target = (i, j)
146- for dir , (a, b, ndir) in dirs.items():
147- x, y = i + a, j + b
148- if 0 <= x < N and 0 <= y < N and master.canMove(dir ) and g[x][y] == - 1 :
149- g[x][y] = master.move(dir )
150- dfs(x, y)
151- master.move(ndir)
152-
151+ target = (x, y)
152+ for k in range (4 ):
153+ dx, dy = dirs[k], dirs[k + 1 ]
154+ nx, ny = x + dx, y + dy
155+ if (
156+ 0 <= nx < m
157+ and 0 <= ny < n
158+ and g[nx][ny] == - 1
159+ and master.canMove(s[k])
160+ ):
161+ g[nx][ny] = master.move(s[k])
162+ dfs(nx, ny)
163+ master.move(s[(k + 2 ) % 4 ])
164+
165+ dirs = (- 1 , 0 , 1 , 0 , - 1 )
166+ s = " URDL"
167+ m = n = 200
168+ g = [[- 1 ] * n for _ in range (m)]
153169 target = (- 1 , - 1 )
154- N = 200
155- INF = 0x 3F3F3F3F
156- g = [[- 1 ] * N for _ in range (N)]
157- dirs = {
158- ' U' : (- 1 , 0 , ' D' ),
159- ' D' : (1 , 0 , ' U' ),
160- ' L' : (0 , - 1 , ' R' ),
161- ' R' : (0 , 1 , ' L' ),
162- }
163- dfs(100 , 100 )
170+ sx = sy = 100
171+ dfs(sx, sy)
164172 if target == (- 1 , - 1 ):
165173 return - 1
166- q = [(0 , 100 , 100 )]
167- dist = [[INF ] * N for _ in range (N )]
168- dist[100 ][ 100 ] = 0
169- while q :
170- w, i, j = heappop(q )
171- if (i, j ) == target:
174+ pq = [(0 , sx, sy )]
175+ dist = [[inf ] * n for _ in range (m )]
176+ dist[sx][sy ] = 0
177+ while pq :
178+ w, x, y = heappop(pq )
179+ if (x, y ) == target:
172180 return w
173- for a, b, _ in dirs.values( ):
174- x, y = i + a, j + b
181+ for dx, dy in pairwise(dirs ):
182+ nx, ny = x + dx, y + dy
175183 if (
176- 0 <= x < N
177- and 0 <= y < N
178- and g[x][y ] != - 1
179- and dist[x][y] > w + g[x][y ]
184+ 0 <= nx < m
185+ and 0 <= ny < n
186+ and g[nx][ny ] != - 1
187+ and w + g[nx][ny] < dist[nx][ny ]
180188 ):
181- dist[x][y ] = w + g[x][y ]
182- heappush(q , (dist[x][y ], x, y ))
183- return 0
189+ dist[nx][ny ] = w + g[nx][ny ]
190+ heappush(pq , (dist[nx][ny ], nx, ny ))
191+ return - 1
184192```
185193
186194#### Java
@@ -197,63 +205,247 @@ class Solution(object):
197205 */
198206
199207class Solution {
200- private static final char [] dir = {' U' , ' R' , ' D' , ' L' };
201- private static final char [] ndir = {' D' , ' L' , ' U' , ' R' };
202- private static final int [] dirs = {- 1 , 0 , 1 , 0 , - 1 };
203- private static final int N = 200 ;
204- private static final int INF = 0x3f3f3f3f ;
205- private static int [][] g = new int [N ][N ];
206- private static int [][] dist = new int [N ][N ];
207- private int [] target;
208+ private final int m = 200 ;
209+ private final int n = 200 ;
210+ private final int inf = Integer . MAX_VALUE / 2 ;
211+ private final int [] dirs = {- 1 , 0 , 1 , 0 , - 1 };
212+ private final char [] s = {' U' , ' R' , ' D' , ' L' };
213+ private int [][] g;
214+ private int sx = 100 , sy = 100 ;
215+ private int tx = - 1 , ty = - 1 ;
216+ private GridMaster master;
208217
209218 public int findShortestPath (GridMaster master ) {
210- target = new int [] { - 1 , - 1 } ;
211- for ( int i = 0 ; i < N ; ++ i) {
212- Arrays . fill(g[i], - 1 );
213- Arrays . fill(dist[i], INF );
219+ this . master = master ;
220+ g = new int [m][n];
221+ for ( var gg : g) {
222+ Arrays . fill(gg, - 1 );
214223 }
215- dfs(100 , 100 , master );
216- if (target[ 0 ] == - 1 && target[ 1 ] == - 1 ) {
224+ dfs(sx, sy );
225+ if (tx == - 1 && ty == - 1 ) {
217226 return - 1 ;
218227 }
219- PriorityQueue<int[]> q = new PriorityQueue<> (Comparator . comparingInt(a - > a[0 ]));
220- q. offer(new int [] {0 , 100 , 100 });
221- dist[100 ][100 ] = 0 ;
222- while (! q. isEmpty()) {
223- int [] p = q. poll();
224- int w = p[0 ], i = p[1 ], j = p[2 ];
225- if (i == target[0 ] && j == target[1 ]) {
228+ PriorityQueue<int[]> pq = new PriorityQueue<> ((a, b) - > a[0 ] - b[0 ]);
229+ pq. offer(new int [] {0 , sx, sy});
230+ int [][] dist = new int [m][n];
231+ for (var gg : dist) {
232+ Arrays . fill(gg, inf);
233+ }
234+ dist[sx][sy] = 0 ;
235+ while (! pq. isEmpty()) {
236+ var p = pq. poll();
237+ int w = p[0 ], x = p[1 ], y = p[2 ];
238+ if (x == tx && y == ty) {
226239 return w;
227240 }
241+ if (w > dist[x][y]) {
242+ continue ;
243+ }
228244 for (int k = 0 ; k < 4 ; ++ k) {
229- int x = i + dirs[k], y = j + dirs[k + 1 ];
230- if (x >= 0 && x < N && y >= 0 && y < N && g[x][y ] != - 1
231- && dist[x][y] > w + g[x][y ]) {
232- dist[x][y ] = w + g[x][y ];
233- q . offer(new int [] {dist[x][y ], x, y });
245+ int nx = x + dirs[k], ny = y + dirs[k + 1 ];
246+ if (nx >= 0 && nx < m && ny >= 0 && ny < n && g[nx][ny ] != - 1
247+ && w + g[nx][ny] < dist[nx][ny ]) {
248+ dist[nx][ny ] = w + g[nx][ny ];
249+ pq . offer(new int [] {dist[nx][ny ], nx, ny });
234250 }
235251 }
236252 }
237- return 0 ;
253+ return - 1 ;
238254 }
239255
240- private void dfs (int i , int j , GridMaster master ) {
256+ private void dfs (int x , int y ) {
241257 if (master. isTarget()) {
242- target = new int [] {i, j};
258+ tx = x;
259+ ty = y;
243260 }
244261 for (int k = 0 ; k < 4 ; ++ k) {
245- char d = dir [k], nd = ndir[k ];
246- int x = i + dirs[k], y = j + dirs[k + 1 ] ;
247- if (x >= 0 && x < N && y >= 0 && y < N && master . canMove(d) && g[x][y ] == - 1 ) {
248- g[x][y ] = master. move(d );
249- dfs(x, y, master );
250- master. move(nd );
262+ int dx = dirs [k], dy = dirs[k + 1 ];
263+ int nx = x + dx, ny = y + dy ;
264+ if (nx >= 0 && nx < m && ny >= 0 && ny < n && g[nx][ny ] == - 1 && master . canMove(s[k]) ) {
265+ g[nx][ny ] = master. move(s[k] );
266+ dfs(nx, ny );
267+ master. move(s[(k + 2 ) % 4 ] );
251268 }
252269 }
253270 }
254271}
255272```
256273
274+ #### C++
275+
276+ ``` cpp
277+ /* *
278+ * // This is the GridMaster's API interface.
279+ * // You should not implement it, or speculate about its implementation
280+ * class GridMaster {
281+ * public:
282+ * bool canMove(char direction);
283+ * int move(char direction);
284+ * boolean isTarget();
285+ * };
286+ */
287+
288+ class Solution {
289+ public:
290+ int findShortestPath(GridMaster& master) {
291+ const int m = 200, n = 200;
292+ const int sx = 100, sy = 100;
293+ const int INF = INT_MAX / 2;
294+ int dirs[ 5] = {-1, 0, 1, 0, -1};
295+ char s[ 4] = {'U', 'R', 'D', 'L'};
296+
297+ vector<vector<int>> g(m, vector<int>(n, -1));
298+ pair<int, int> target = {-1, -1};
299+
300+ auto dfs = [&](this auto& dfs, int x, int y) -> void {
301+ if (master.isTarget()) {
302+ target = {x, y};
303+ }
304+ for (int k = 0 ; k < 4 ; ++k) {
305+ int dx = dirs[k], dy = dirs[k + 1];
306+ int nx = x + dx, ny = y + dy;
307+ if (0 <= nx && nx < m && 0 <= ny && ny < n && g[nx][ny] == -1 && master.canMove(s[k])) {
308+ g[nx][ny] = master.move(s[k]);
309+ dfs (nx, ny);
310+ master.move(s[ (k + 2) % 4] );
311+ }
312+ }
313+ };
314+
315+ g[sx][sy] = 0;
316+ dfs (sx, sy);
317+
318+ if (target.first == -1 && target.second == -1) {
319+ return -1;
320+ }
321+
322+ vector<vector<int>> dist(m, vector<int>(n, INF));
323+ dist[sx][sy] = 0;
324+
325+ using Node = tuple<int, int, int>;
326+ priority_queue<Node, vector<Node>, greater<Node>> pq;
327+ pq.emplace(0, sx, sy);
328+
329+ while (!pq.empty()) {
330+ auto [w, x, y] = pq.top();
331+ pq.pop();
332+ if (x == target.first && y == target.second) {
333+ return w;
334+ }
335+ if (w > dist[x][y]) {
336+ continue;
337+ }
338+
339+ for (int k = 0; k < 4; ++k) {
340+ int nx = x + dirs[k], ny = y + dirs[k + 1];
341+ if (0 <= nx && nx < m && 0 <= ny && ny < n && g[nx][ny] != -1) {
342+ int nd = w + g[nx][ny];
343+ if (nd < dist[nx][ny]) {
344+ dist[nx][ny] = nd;
345+ pq.emplace(nd, nx, ny);
346+ }
347+ }
348+ }
349+ }
350+
351+ return -1;
352+ }
353+ };
354+ ```
355+
356+ #### JavaScript
357+
358+ ``` js
359+ /**
360+ * // This is the GridMaster's API interface.
361+ * // You should not implement it, or speculate about its implementation
362+ * function GridMaster() {
363+ *
364+ * @param {character} direction
365+ * @return {boolean}
366+ * this.canMove = function(direction) {
367+ * ...
368+ * };
369+ * @param {character} direction
370+ * @return {integer}
371+ * this.move = function(direction) {
372+ * ...
373+ * };
374+ * @return {boolean}
375+ * this.isTarget = function() {
376+ * ...
377+ * };
378+ * };
379+ */
380+
381+ /**
382+ * @param {GridMaster} master
383+ * @return {integer}
384+ */
385+ var findShortestPath = function (master ) {
386+ const [m , n ] = [200 , 200 ];
387+ const [sx , sy ] = [100 , 100 ];
388+ const inf = Number .MAX_SAFE_INTEGER ;
389+ const dirs = [- 1 , 0 , 1 , 0 , - 1 ];
390+ const s = [' U' , ' R' , ' D' , ' L' ];
391+ const g = Array .from ({ length: m }, () => Array (n).fill (- 1 ));
392+ let target = [- 1 , - 1 ];
393+ const dfs = (x , y ) => {
394+ if (master .isTarget ()) {
395+ target = [x, y];
396+ }
397+ for (let k = 0 ; k < 4 ; ++ k) {
398+ const dx = dirs[k],
399+ dy = dirs[k + 1 ];
400+ const nx = x + dx,
401+ ny = y + dy;
402+ if (
403+ 0 <= nx &&
404+ nx < m &&
405+ 0 <= ny &&
406+ ny < n &&
407+ g[nx][ny] === - 1 &&
408+ master .canMove (s[k])
409+ ) {
410+ g[nx][ny] = master .move (s[k]);
411+ dfs (nx, ny);
412+ master .move (s[(k + 2 ) % 4 ]);
413+ }
414+ }
415+ };
416+ g[sx][sy] = 0 ;
417+ dfs (sx, sy);
418+ if (target[0 ] === - 1 && target[1 ] === - 1 ) {
419+ return - 1 ;
420+ }
421+ const dist = Array .from ({ length: m }, () => Array (n).fill (inf));
422+ dist[sx][sy] = 0 ;
423+ const pq = new MinPriorityQueue (node => node[0 ]);
424+ pq .enqueue ([0 , sx, sy]);
425+ while (! pq .isEmpty ()) {
426+ const [w , x , y ] = pq .dequeue ();
427+ if (x === target[0 ] && y === target[1 ]) {
428+ return w;
429+ }
430+ if (w > dist[x][y]) {
431+ continue ;
432+ }
433+ for (let k = 0 ; k < 4 ; ++ k) {
434+ const nx = x + dirs[k],
435+ ny = y + dirs[k + 1 ];
436+ if (0 <= nx && nx < m && 0 <= ny && ny < n && g[nx][ny] !== - 1 ) {
437+ const nd = w + g[nx][ny];
438+ if (nd < dist[nx][ny]) {
439+ dist[nx][ny] = nd;
440+ pq .enqueue ([nd, nx, ny]);
441+ }
442+ }
443+ }
444+ }
445+ return - 1 ;
446+ };
447+ ```
448+
257449<!-- tabs:end -->
258450
259451<!-- solution:end -->
0 commit comments