Skip to content

Commit 474988c

Browse files
authored
feat: add solutions to lc problem: No.3283 (#3496)
No.3283.Maximum Number of Moves to Kill All Pawns
1 parent 4574dce commit 474988c

File tree

6 files changed

+746
-11
lines changed

6 files changed

+746
-11
lines changed

solution/3200-3299/3283.Maximum Number of Moves to Kill All Pawns/README.md

Lines changed: 253 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,32 +99,279 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3283.Ma
9999

100100
<!-- solution:start -->
101101

102-
### 方法一
102+
### 方法一:BFS + 状态压缩 + 记忆化搜索
103103

104-
<!-- tabs:start -->
104+
我们首先预处理出每个兵到棋盘上任意一个位置的马的最短距离,记录在数组 $\textit{dist}$ 中,即 $\textit{dist}[i][x][y]$ 表示第 $i$ 个兵到 $(x, y)$ 位置的马的最短距离。
105+
106+
接下来,我们设计一个函数 $\text{dfs}(\textit{last}, \textit{state}, \textit{k})$,其中 $\textit{last}$ 表示上一个吃掉的兵的编号,而 $\textit{state}$ 表示当前还剩下的兵的状态,而 $\textit{k}$ 表示当前是 Alice 还是 Bob 的回合。函数的返回值表示当前回合的最大移动次数。那么答案为 $\text{dfs}(n, 2^n-1, 1)$。这里我们初始时上一个吃掉的兵的编号记为 $n$,这也是马所在的位置。
107+
108+
函数 $\text{dfs}$ 的具体实现如下:
109+
110+
- 如果 $\textit{state} = 0$,表示没有兵了,返回 $0$;
111+
- 如果 $\textit{k} = 1$,表示当前是 Alice 的回合,我们需要找到一个兵,使得吃掉这个兵后的移动次数最大,即 $\text{dfs}(i, \textit{state} \oplus 2^i, \textit{k} \oplus 1) + \textit{dist}[\textit{last}][x][y]$;
112+
- 如果 $\textit{k} = 0$,表示当前是 Bob 的回合,我们需要找到一个兵,使得吃掉这个兵后的移动次数最小,即 $\text{dfs}(i, \textit{state} \oplus 2^i, \textit{k} \oplus 1) + \textit{dist}[\textit{last}][x][y]$。
113+
114+
为了避免重复计算,我们使用记忆化搜索,即使用哈希表记录已经计算过的状态。
115+
116+
时间复杂度 $O(n \times m^2 + 2^n \times n^2)$,空间复杂度 $O(n \times m^2 + 2^n \times n)$。其中 $n$ 和 $m$ 分别为兵的数量和棋盘的大小。
105117

106118
#### Python3
107119

108120
```python
109-
121+
class Solution:
122+
def maxMoves(self, kx: int, ky: int, positions: List[List[int]]) -> int:
123+
@cache
124+
def dfs(last: int, state: int, k: int) -> int:
125+
if state == 0:
126+
return 0
127+
if k:
128+
res = 0
129+
for i, (x, y) in enumerate(positions):
130+
if state >> i & 1:
131+
t = dfs(i, state ^ (1 << i), k ^ 1) + dist[last][x][y]
132+
if res < t:
133+
res = t
134+
return res
135+
else:
136+
res = inf
137+
for i, (x, y) in enumerate(positions):
138+
if state >> i & 1:
139+
t = dfs(i, state ^ (1 << i), k ^ 1) + dist[last][x][y]
140+
if res > t:
141+
res = t
142+
return res
143+
144+
n = len(positions)
145+
m = 50
146+
dist = [[[-1] * m for _ in range(m)] for _ in range(n + 1)]
147+
dx = [1, 1, 2, 2, -1, -1, -2, -2]
148+
dy = [2, -2, 1, -1, 2, -2, 1, -1]
149+
positions.append([kx, ky])
150+
for i, (x, y) in enumerate(positions):
151+
dist[i][x][y] = 0
152+
q = deque([(x, y)])
153+
step = 0
154+
while q:
155+
step += 1
156+
for _ in range(len(q)):
157+
x1, y1 = q.popleft()
158+
for j in range(8):
159+
x2, y2 = x1 + dx[j], y1 + dy[j]
160+
if 0 <= x2 < m and 0 <= y2 < m and dist[i][x2][y2] == -1:
161+
dist[i][x2][y2] = step
162+
q.append((x2, y2))
163+
164+
ans = dfs(n, (1 << n) - 1, 1)
165+
dfs.cache_clear()
166+
return ans
110167
```
111168

112169
#### Java
113170

114171
```java
115-
172+
class Solution {
173+
private Integer[][][] f;
174+
private Integer[][][] dist;
175+
private int[][] positions;
176+
private final int[] dx = {1, 1, 2, 2, -1, -1, -2, -2};
177+
private final int[] dy = {2, -2, 1, -1, 2, -2, 1, -1};
178+
179+
public int maxMoves(int kx, int ky, int[][] positions) {
180+
int n = positions.length;
181+
final int m = 50;
182+
dist = new Integer[n + 1][m][m];
183+
this.positions = positions;
184+
for (int i = 0; i <= n; ++i) {
185+
int x = i < n ? positions[i][0] : kx;
186+
int y = i < n ? positions[i][1] : ky;
187+
Deque<int[]> q = new ArrayDeque<>();
188+
q.offer(new int[] {x, y});
189+
for (int step = 1; !q.isEmpty(); ++step) {
190+
for (int k = q.size(); k > 0; --k) {
191+
var p = q.poll();
192+
int x1 = p[0], y1 = p[1];
193+
for (int j = 0; j < 8; ++j) {
194+
int x2 = x1 + dx[j], y2 = y1 + dy[j];
195+
if (x2 >= 0 && x2 < m && y2 >= 0 && y2 < m && dist[i][x2][y2] == null) {
196+
dist[i][x2][y2] = step;
197+
q.offer(new int[] {x2, y2});
198+
}
199+
}
200+
}
201+
}
202+
}
203+
f = new Integer[n + 1][1 << n][2];
204+
return dfs(n, (1 << n) - 1, 1);
205+
}
206+
207+
private int dfs(int last, int state, int k) {
208+
if (state == 0) {
209+
return 0;
210+
}
211+
if (f[last][state][k] != null) {
212+
return f[last][state][k];
213+
}
214+
int res = k == 1 ? 0 : Integer.MAX_VALUE;
215+
for (int i = 0; i < positions.length; ++i) {
216+
int x = positions[i][0], y = positions[i][1];
217+
if ((state >> i & 1) == 1) {
218+
int t = dfs(i, state ^ (1 << i), k ^ 1) + dist[last][x][y];
219+
res = k == 1 ? Math.max(res, t) : Math.min(res, t);
220+
}
221+
}
222+
return f[last][state][k] = res;
223+
}
224+
}
116225
```
117226

118227
#### C++
119228

120229
```cpp
121-
230+
class Solution {
231+
public:
232+
int maxMoves(int kx, int ky, vector<vector<int>>& positions) {
233+
int n = positions.size();
234+
const int m = 50;
235+
const int dx[8] = {1, 1, 2, 2, -1, -1, -2, -2};
236+
const int dy[8] = {2, -2, 1, -1, 2, -2, 1, -1};
237+
int dist[n + 1][m][m];
238+
memset(dist, -1, sizeof(dist));
239+
for (int i = 0; i <= n; ++i) {
240+
int x = (i < n) ? positions[i][0] : kx;
241+
int y = (i < n) ? positions[i][1] : ky;
242+
queue<pair<int, int>> q;
243+
q.push({x, y});
244+
dist[i][x][y] = 0;
245+
for (int step = 1; !q.empty(); ++step) {
246+
for (int k = q.size(); k > 0; --k) {
247+
auto [x1, y1] = q.front();
248+
q.pop();
249+
for (int j = 0; j < 8; ++j) {
250+
int x2 = x1 + dx[j], y2 = y1 + dy[j];
251+
if (x2 >= 0 && x2 < m && y2 >= 0 && y2 < m && dist[i][x2][y2] == -1) {
252+
dist[i][x2][y2] = step;
253+
q.push({x2, y2});
254+
}
255+
}
256+
}
257+
}
258+
}
259+
260+
int f[n + 1][1 << n][2];
261+
memset(f, -1, sizeof(f));
262+
auto dfs = [&](auto&& dfs, int last, int state, int k) -> int {
263+
if (state == 0) {
264+
return 0;
265+
}
266+
if (f[last][state][k] != -1) {
267+
return f[last][state][k];
268+
}
269+
int res = (k == 1) ? 0 : INT_MAX;
270+
271+
for (int i = 0; i < positions.size(); ++i) {
272+
int x = positions[i][0], y = positions[i][1];
273+
if ((state >> i) & 1) {
274+
int t = dfs(dfs, i, state ^ (1 << i), k ^ 1) + dist[last][x][y];
275+
if (k == 1) {
276+
res = max(res, t);
277+
} else {
278+
res = min(res, t);
279+
}
280+
}
281+
}
282+
return f[last][state][k] = res;
283+
};
284+
return dfs(dfs, n, (1 << n) - 1, 1);
285+
}
286+
};
122287
```
123288

124289
#### Go
125290

126291
```go
127-
292+
func maxMoves(kx int, ky int, positions [][]int) int {
293+
n := len(positions)
294+
const m = 50
295+
dx := []int{1, 1, 2, 2, -1, -1, -2, -2}
296+
dy := []int{2, -2, 1, -1, 2, -2, 1, -1}
297+
dist := make([][][]int, n+1)
298+
for i := range dist {
299+
dist[i] = make([][]int, m)
300+
for j := range dist[i] {
301+
dist[i][j] = make([]int, m)
302+
for k := range dist[i][j] {
303+
dist[i][j][k] = -1
304+
}
305+
}
306+
}
307+
308+
for i := 0; i <= n; i++ {
309+
x := kx
310+
y := ky
311+
if i < n {
312+
x = positions[i][0]
313+
y = positions[i][1]
314+
}
315+
q := [][2]int{[2]int{x, y}}
316+
dist[i][x][y] = 0
317+
318+
for step := 1; len(q) > 0; step++ {
319+
for k := len(q); k > 0; k-- {
320+
p := q[0]
321+
q = q[1:]
322+
x1, y1 := p[0], p[1]
323+
for j := 0; j < 8; j++ {
324+
x2 := x1 + dx[j]
325+
y2 := y1 + dy[j]
326+
if x2 >= 0 && x2 < m && y2 >= 0 && y2 < m && dist[i][x2][y2] == -1 {
327+
dist[i][x2][y2] = step
328+
q = append(q, [2]int{x2, y2})
329+
}
330+
}
331+
}
332+
}
333+
}
334+
f := make([][][]int, n+1)
335+
for i := range f {
336+
f[i] = make([][]int, 1<<n)
337+
for j := range f[i] {
338+
f[i][j] = make([]int, 2)
339+
for k := range f[i][j] {
340+
f[i][j][k] = -1
341+
}
342+
}
343+
}
344+
var dfs func(last, state, k int) int
345+
dfs = func(last, state, k int) int {
346+
if state == 0 {
347+
return 0
348+
}
349+
if f[last][state][k] != -1 {
350+
return f[last][state][k]
351+
}
352+
353+
var res int
354+
if k == 0 {
355+
res = math.MaxInt32
356+
}
357+
358+
for i, p := range positions {
359+
x, y := p[0], p[1]
360+
if (state>>i)&1 == 1 {
361+
t := dfs(i, state^(1<<i), k^1) + dist[last][x][y]
362+
if k == 1 {
363+
res = max(res, t)
364+
} else {
365+
res = min(res, t)
366+
}
367+
}
368+
}
369+
f[last][state][k] = res
370+
return res
371+
}
372+
373+
return dfs(n, (1<<n)-1, 1)
374+
}
128375
```
129376

130377
<!-- tabs:end -->

0 commit comments

Comments
 (0)