@@ -99,32 +99,279 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3200-3299/3283.Ma
99
99
100
100
<!-- solution:start -->
101
101
102
- ### 方法一
102
+ ### 方法一:BFS + 状态压缩 + 记忆化搜索
103
103
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$ 分别为兵的数量和棋盘的大小。
105
117
106
118
#### Python3
107
119
108
120
``` 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
110
167
```
111
168
112
169
#### Java
113
170
114
171
``` 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
+ }
116
225
```
117
226
118
227
#### C++
119
228
120
229
``` 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
+ };
122
287
```
123
288
124
289
#### Go
125
290
126
291
``` 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
+ }
128
375
```
129
376
130
377
<!-- tabs:end -->
0 commit comments