Skip to content

Commit 445369a

Browse files
committed
feat: add solutions to lc problem: No.0773
No.0773.Sliding Puzzle
1 parent 9280ded commit 445369a

File tree

5 files changed

+582
-168
lines changed

5 files changed

+582
-168
lines changed

solution/0700-0799/0773.Sliding Puzzle/README.md

Lines changed: 222 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,15 @@
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

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\* 算法只能保证终点第一次出队时,即找到了一条从起点到终点的最小路径,不能保证其他点出队时也是从起点到当前点的最短路径。
6270

6371
<!-- tabs:start -->
6472

@@ -76,7 +84,7 @@ class Solution:
7684
for j in range(3):
7785
t[i * 3 + j] = str(board[i][j])
7886
return ''.join(t)
79-
87+
8088
def setb(s):
8189
for i in range(2):
8290
for j in range(3):
@@ -121,6 +129,58 @@ class Solution:
121129
return -1
122130
```
123131

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+
124184
### **Java**
125185

126186
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -214,6 +274,91 @@ class Solution {
214274
}
215275
```
216276

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+
217362
### **C++**
218363

219364
```cpp
@@ -297,6 +442,81 @@ public:
297442
};
298443
```
299444
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+
300520
### **...**
301521

302522
```

0 commit comments

Comments
 (0)