58
58
59
59
<!-- 这里可写通用的实现逻辑 -->
60
60
61
- BFS 最小步数模型。
61
+ BFS 最小步数模型。可以使用朴素 BFS 直接搜索,也可以使用 A\* 算法优化搜索。
62
+
63
+ A\* 算法主要思想如下:
64
+
65
+ 1 . 将 BFS 队列转换为优先队列(小根堆);
66
+ 1 . 队列中的每个元素为 ` (dist[state] + f(state), state) ` ,` dist[state] ` 表示从起点到当前 state 的距离,` f(state) ` 表示从当前 state 到终点的估计距离,这两个距离之和作为堆排序的依据;
67
+ 1 . 当终点第一次出队时,说明找到了从起点到终点的最短路径,直接返回对应的 step;
68
+ 1 . ` f(state) ` 是估价函数,并且估价函数要满足 ` f(state) <= g(state) ` ,其中 ` g(state) ` 表示 state 到终点的真实距离;
69
+ 1 . A\* 算法只能保证终点第一次出队时,即找到了一条从起点到终点的最小路径,不能保证其他点出队时也是从起点到当前点的最短路径。
62
70
63
71
<!-- tabs:start -->
64
72
@@ -76,7 +84,7 @@ class Solution:
76
84
for j in range (3 ):
77
85
t[i * 3 + j] = str (board[i][j])
78
86
return ' ' .join(t)
79
-
87
+
80
88
def setb (s ):
81
89
for i in range (2 ):
82
90
for j in range (3 ):
@@ -121,6 +129,58 @@ class Solution:
121
129
return - 1
122
130
```
123
131
132
+ A* 算法:
133
+
134
+ ``` python
135
+ class Solution :
136
+ def slidingPuzzle (self , board : List[List[int ]]) -> int :
137
+ m, n = 2 , 3
138
+ seq = []
139
+ start, end = ' ' , ' 123450'
140
+ for i in range (m):
141
+ for j in range (n):
142
+ if board[i][j] != 0 :
143
+ seq.append(board[i][j])
144
+ start += str (board[i][j])
145
+
146
+ def check (seq ):
147
+ n = len (seq)
148
+ cnt = sum (seq[i] > seq[j] for i in range (n) for j in range (i, n))
149
+ return cnt % 2 == 0
150
+
151
+ def f (s ):
152
+ ans = 0
153
+ for i in range (m * n):
154
+ if s[i] != ' 0' :
155
+ num = ord (s[i]) - ord (' 1' )
156
+ ans += abs (i // n - num // n) + abs (i % n - num % n)
157
+ return ans
158
+
159
+
160
+ if not check(seq):
161
+ return - 1
162
+ q = [(f(start), start)]
163
+ dist = {start: 0 }
164
+ while q:
165
+ _, state = heapq.heappop(q)
166
+ if state == end:
167
+ return dist[state]
168
+ p1 = state.index(' 0' )
169
+ i, j = p1 // n, p1 % n
170
+ s = list (state)
171
+ for a, b in [[0 , - 1 ], [0 , 1 ], [1 , 0 ], [- 1 , 0 ]]:
172
+ x, y = i + a, j + b
173
+ if 0 <= x < m and 0 <= y < n:
174
+ p2 = x * n + y
175
+ s[p1], s[p2] = s[p2], s[p1]
176
+ next = ' ' .join(s)
177
+ s[p1], s[p2] = s[p2], s[p1]
178
+ if next not in dist or dist[next ] > dist[state] + 1 :
179
+ dist[next ] = dist[state] + 1
180
+ heapq.heappush(q, (dist[next ] + f(next ), next ))
181
+ return - 1
182
+ ```
183
+
124
184
### ** Java**
125
185
126
186
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -214,6 +274,91 @@ class Solution {
214
274
}
215
275
```
216
276
277
+ A* 算法:
278
+
279
+ ``` java
280
+ class Solution {
281
+ private int m = 2 ;
282
+ private int n = 3 ;
283
+
284
+ public int slidingPuzzle (int [][] board ) {
285
+ String start = " " ;
286
+ String end = " 123450" ;
287
+ String seq = " " ;
288
+ for (int i = 0 ; i < m; ++ i) {
289
+ for (int j = 0 ; j < n; ++ j) {
290
+ start += board[i][j];
291
+ if (board[i][j] != 0 ) {
292
+ seq += board[i][j];
293
+ }
294
+ }
295
+ }
296
+ if (! check(seq)) {
297
+ return - 1 ;
298
+ }
299
+ PriorityQueue<Pair<Integer , String > > q = new PriorityQueue<> (Comparator . comparingInt(Pair :: getKey));
300
+ Map<String , Integer > dist = new HashMap<> ();
301
+ dist. put(start, 0 );
302
+ q. offer(new Pair<> (f(start), start));
303
+ int [] dirs = {- 1 , 0 , 1 , 0 , - 1 };
304
+ while (! q. isEmpty()) {
305
+ String state = q. poll(). getValue();
306
+ int step = dist. get(state);
307
+ if (end. equals(state)) {
308
+ return step;
309
+ }
310
+ int p1 = state. indexOf(" 0" );
311
+ int i = p1 / n, j = p1 % n;
312
+ char [] s = state. toCharArray();
313
+ for (int k = 0 ; k < 4 ; ++ k) {
314
+ int x = i + dirs[k], y = j + dirs[k + 1 ];
315
+ if (x >= 0 && x < m && y >= 0 && y < n) {
316
+ int p2 = x * n + y;
317
+ swap(s, p1, p2);
318
+ String next = String . valueOf(s);
319
+ if (! dist. containsKey(next) || dist. get(next) > step + 1 ) {
320
+ dist. put(next, step + 1 );
321
+ q. offer(new Pair<> (step + 1 + f(next), next));
322
+ }
323
+ swap(s, p1, p2);
324
+ }
325
+ }
326
+ }
327
+ return - 1 ;
328
+ }
329
+
330
+ private void swap (char [] arr , int i , int j ) {
331
+ char t = arr[i];
332
+ arr[i] = arr[j];
333
+ arr[j] = t;
334
+ }
335
+
336
+ private int f (String s ) {
337
+ int ans = 0 ;
338
+ for (int i = 0 ; i < m * n; ++ i) {
339
+ if (s. charAt(i) != ' 0' ) {
340
+ int num = s. charAt(i) - ' 1' ;
341
+ ans += Math . abs(i / n - num / n) + Math . abs(i % n - num % n);
342
+ }
343
+ }
344
+ return ans;
345
+ }
346
+
347
+ private boolean check (String s ) {
348
+ int n = s. length();
349
+ int cnt = 0 ;
350
+ for (int i = 0 ; i < n; ++ i) {
351
+ for (int j = i + 1 ; j < n; ++ j) {
352
+ if (s. charAt(i) > s. charAt(j)) {
353
+ ++ cnt;
354
+ }
355
+ }
356
+ }
357
+ return cnt % 2 == 0 ;
358
+ }
359
+ }
360
+ ```
361
+
217
362
### ** C++**
218
363
219
364
``` cpp
@@ -297,6 +442,81 @@ public:
297
442
};
298
443
```
299
444
445
+ A* 算法:
446
+
447
+ ```cpp
448
+ class Solution {
449
+ public:
450
+ int m = 2;
451
+ int n = 3;
452
+
453
+ int slidingPuzzle(vector<vector<int>>& board) {
454
+ string start, seq;
455
+ string end = "123450";
456
+ for (int i = 0; i < m; ++i)
457
+ {
458
+ for (int j = 0; j < n; ++j)
459
+ {
460
+ start += char(board[i][j] + '0');
461
+ if (board[i][j] != 0) seq += char(board[i][j] + '0');
462
+ }
463
+ }
464
+ if (!check(seq)) return -1;
465
+ typedef pair<int , string> PIS;
466
+ priority_queue<PIS, vector<PIS>, greater<PIS>> q;
467
+ unordered_map<string, int> dist;
468
+ dist[start] = 0;
469
+ q.push({f(start), start});
470
+ vector<int> dirs = {-1, 0, 1, 0, -1};
471
+ while (!q.empty())
472
+ {
473
+ PIS t = q.top();
474
+ q.pop();
475
+ string state = t.second;
476
+ int step = dist[state];
477
+ if (state == end) return step;
478
+ int p1 = state.find('0');
479
+ int i = p1 / n, j = p1 % n;
480
+ for (int k = 0; k < 4; ++k)
481
+ {
482
+ int x = i + dirs[k], y = j + dirs[k + 1];
483
+ if (x < 0 || x >= m || y < 0 || y >= n) continue;
484
+ int p2 = x * n + y;
485
+ swap(state[p1], state[p2]);
486
+ if (!dist.count(state) || dist[state] > step + 1)
487
+ {
488
+ dist[state] = step + 1;
489
+ q.push({step + 1 + f(state), state});
490
+ }
491
+ swap(state[p1], state[p2]);
492
+ }
493
+ }
494
+ return -1;
495
+ }
496
+
497
+ bool check(string s) {
498
+ int n = s.size();
499
+ int cnt = 0;
500
+ for (int i = 0; i < n; ++i)
501
+ for (int j = i; j < n; ++j)
502
+ if (s[i] > s[j])
503
+ ++cnt;
504
+ return cnt % 2 == 0;
505
+ }
506
+
507
+ int f(string s) {
508
+ int ans = 0;
509
+ for (int i = 0; i < m * n; ++i)
510
+ {
511
+ if (s[i] == '0') continue;
512
+ int num = s[i] - '1';
513
+ ans += abs(num / n - i / n) + abs(num % n - i % n);
514
+ }
515
+ return ans;
516
+ }
517
+ };
518
+ ```
519
+
300
520
### ** ...**
301
521
302
522
```
0 commit comments