@@ -82,41 +82,341 @@ tags:
82
82
83
83
<!-- solution:start -->
84
84
85
- ### 方法一
85
+ ### 方法一:记忆化搜索 + 二进制枚举
86
+
87
+ 我们定义一个函数 $\text{dfs}(l, r, n)$,表示在当前回合中,编号为 $l$ 和 $r$ 的运动员在 $n$ 名运动员中比拼的最早和最晚回合数。
88
+
89
+ 函数 $\text{dfs}(l, r, n)$ 的执行逻辑如下:
90
+
91
+ 1 . 如果 $l + r = n - 1$,说明两名运动员在当前回合中比拼,返回 $[ 1, 1] $。
92
+ 2 . 如果 $f[ l] [ r ] [ n] \neq 0$,说明之前已经计算过这个状态,直接返回结果。
93
+ 3 . 初始化最早回合数为正无穷大,最晚回合数为负无穷大。
94
+ 4 . 计算当前回合中前半部分的运动员数目 $m = n / 2$。
95
+ 5 . 枚举前半部分的所有可能的胜者组合(使用二进制枚举),对于每一种组合:
96
+ - 根据当前组合确定哪些运动员获胜。
97
+ - 确定当前回合中编号为 $l$ 和 $r$ 的运动员在当前回合中的位置。
98
+ - 统计当前回合中编号为 $l$ 和 $r$ 的运动员在剩余运动员中的位置,记为 $a$ 和 $b$,以及剩余运动员的总数 $c$。
99
+ - 递归调用 $\text{dfs}(a, b, c)$,获取当前状态的最早和最晚回合数。
100
+ - 更新最早回合数和最晚回合数。
101
+ 6 . 将计算结果存储在 $f[ l] [ r ] [ n] $ 中,并返回最早和最晚回合数。
102
+
103
+ 答案为 $\text{dfs}(\text{firstPlayer} - 1, \text{secondPlayer} - 1, n)$。
86
104
87
105
<!-- tabs:start -->
88
106
89
107
#### Python3
90
108
91
109
``` python
110
+ @cache
111
+ def dfs (l : int , r : int , n : int ):
112
+ if l + r == n - 1 :
113
+ return [1 , 1 ]
114
+ res = [inf, - inf]
115
+ m = n >> 1
116
+ for i in range (1 << m):
117
+ win = [False ] * n
118
+ for j in range (m):
119
+ if i >> j & 1 :
120
+ win[j] = True
121
+ else :
122
+ win[n - 1 - j] = True
123
+ if n & 1 :
124
+ win[m] = True
125
+ win[n - 1 - l] = win[n - 1 - r] = False
126
+ win[l] = win[r] = True
127
+ a = b = c = 0
128
+ for j in range (n):
129
+ if j == l:
130
+ a = c
131
+ if j == r:
132
+ b = c
133
+ if win[j]:
134
+ c += 1
135
+ x, y = dfs(a, b, c)
136
+ res[0 ] = min (res[0 ], x + 1 )
137
+ res[1 ] = max (res[1 ], y + 1 )
138
+ return res
139
+
140
+
92
141
class Solution :
93
142
def earliestAndLatest (
94
143
self , n : int , firstPlayer : int , secondPlayer : int
95
144
) -> List[int ]:
96
- # dp[i][j][k] := (earliest, latest) pair w/ firstPlayer is i-th player from
97
- # Front, secondPlayer is j-th player from end, and there're k people
98
- @functools.lru_cache (None )
99
- def dp (l : int , r : int , k : int ) -> List[int ]:
100
- if l == r:
101
- return [1 , 1 ]
102
- if l > r:
103
- return dp(r, l, k)
104
-
105
- a = math.inf
106
- b = - math.inf
107
-
108
- # Enumerate all possible positions
109
- for i in range (1 , l + 1 ):
110
- for j in range (l - i + 1 , r - i + 1 ):
111
- if not l + r - k // 2 <= i + j <= (k + 1 ) // 2 :
112
- continue
113
- x, y = dp(i, j, (k + 1 ) // 2 )
114
- a = min (a, x + 1 )
115
- b = max (b, y + 1 )
116
-
117
- return [a, b]
118
-
119
- return dp(firstPlayer, n - secondPlayer + 1 , n)
145
+ return dfs(firstPlayer - 1 , secondPlayer - 1 , n)
146
+ ```
147
+
148
+ #### Java
149
+
150
+ ``` java
151
+ class Solution {
152
+ static int [][][] f = new int [30 ][30 ][31 ];
153
+
154
+ public int [] earliestAndLatest (int n , int firstPlayer , int secondPlayer ) {
155
+ return dfs(firstPlayer - 1 , secondPlayer - 1 , n);
156
+ }
157
+
158
+ private int [] dfs (int l , int r , int n ) {
159
+ if (f[l][r][n] != 0 ) {
160
+ return decode(f[l][r][n]);
161
+ }
162
+ if (l + r == n - 1 ) {
163
+ f[l][r][n] = encode(1 , 1 );
164
+ return new int [] {1 , 1 };
165
+ }
166
+ int min = Integer . MAX_VALUE , max = Integer . MIN_VALUE ;
167
+ int m = n >> 1 ;
168
+ for (int i = 0 ; i < (1 << m); i++ ) {
169
+ boolean [] win = new boolean [n];
170
+ for (int j = 0 ; j < m; j++ ) {
171
+ if (((i >> j) & 1 ) == 1 ) {
172
+ win[j] = true ;
173
+ } else {
174
+ win[n - 1 - j] = true ;
175
+ }
176
+ }
177
+ if ((n & 1 ) == 1 ) {
178
+ win[m] = true ;
179
+ }
180
+ win[n - 1 - l] = win[n - 1 - r] = false ;
181
+ win[l] = win[r] = true ;
182
+ int a = 0 , b = 0 , c = 0 ;
183
+ for (int j = 0 ; j < n; j++ ) {
184
+ if (j == l) {
185
+ a = c;
186
+ }
187
+ if (j == r) {
188
+ b = c;
189
+ }
190
+ if (win[j]) {
191
+ c++ ;
192
+ }
193
+ }
194
+ int [] t = dfs(a, b, c);
195
+ min = Math . min(min, t[0 ] + 1 );
196
+ max = Math . max(max, t[1 ] + 1 );
197
+ }
198
+ f[l][r][n] = encode(min, max);
199
+ return new int [] {min, max};
200
+ }
201
+
202
+ private int encode (int x , int y ) {
203
+ return (x << 8 ) | y;
204
+ }
205
+
206
+ private int [] decode (int val ) {
207
+ return new int [] {val >> 8 , val & 255 };
208
+ }
209
+ }
210
+ ```
211
+
212
+ #### C++
213
+
214
+ ``` cpp
215
+ int f[30 ][30 ][31 ];
216
+ class Solution {
217
+ public:
218
+ vector<int > earliestAndLatest(int n, int firstPlayer, int secondPlayer) {
219
+ return dfs(firstPlayer - 1, secondPlayer - 1, n);
220
+ }
221
+
222
+ private:
223
+ vector<int > dfs(int l, int r, int n) {
224
+ if (f[ l] [ r ] [ n] != 0) {
225
+ return decode(f[ l] [ r ] [ n] );
226
+ }
227
+ if (l + r == n - 1) {
228
+ f[ l] [ r ] [ n] = encode(1, 1);
229
+ return {1, 1};
230
+ }
231
+
232
+ int min = INT_MAX, max = INT_MIN;
233
+ int m = n >> 1;
234
+
235
+ for (int i = 0; i < (1 << m); i++) {
236
+ vector<bool> win(n, false);
237
+ for (int j = 0; j < m; j++) {
238
+ if ((i >> j) & 1) {
239
+ win[j] = true;
240
+ } else {
241
+ win[n - 1 - j] = true;
242
+ }
243
+ }
244
+ if (n & 1 ) {
245
+ win[m] = true;
246
+ }
247
+
248
+ win[n - 1 - l] = false;
249
+ win[n - 1 - r] = false;
250
+ win[l] = true;
251
+ win[r] = true;
252
+
253
+ int a = 0, b = 0, c = 0;
254
+ for (int j = 0; j < n; j++) {
255
+ if (j == l) a = c;
256
+ if (j == r) b = c;
257
+ if (win[j]) c++;
258
+ }
259
+
260
+ vector<int> t = dfs(a, b, c);
261
+ min = std::min(min, t[0] + 1);
262
+ max = std::max(max, t[1] + 1);
263
+ }
264
+
265
+ f[l][r][n] = encode(min, max);
266
+ return {min, max};
267
+ }
268
+
269
+ int encode(int x, int y) {
270
+ return (x << 8) | y;
271
+ }
272
+
273
+ vector<int> decode(int val) {
274
+ return {val >> 8, val & 255};
275
+ }
276
+ };
277
+ ```
278
+
279
+ #### Go
280
+
281
+ ``` go
282
+ var f [30 ][30 ][31 ]int
283
+
284
+ func earliestAndLatest (n int , firstPlayer int , secondPlayer int ) []int {
285
+ return dfs (firstPlayer-1 , secondPlayer-1 , n)
286
+ }
287
+
288
+ func dfs (l , r , n int ) []int {
289
+ if f[l][r][n] != 0 {
290
+ return decode (f[l][r][n])
291
+ }
292
+ if l+r == n-1 {
293
+ f[l][r][n] = encode (1 , 1 )
294
+ return []int {1 , 1 }
295
+ }
296
+
297
+ min , max := 1 <<30 , -1 <<31
298
+ m := n >> 1
299
+
300
+ for i := 0 ; i < (1 << m); i++ {
301
+ win := make ([]bool , n)
302
+ for j := 0 ; j < m; j++ {
303
+ if (i>>j)&1 == 1 {
304
+ win[j] = true
305
+ } else {
306
+ win[n-1 -j] = true
307
+ }
308
+ }
309
+ if n&1 == 1 {
310
+ win[m] = true
311
+ }
312
+ win[n-1 -l] = false
313
+ win[n-1 -r] = false
314
+ win[l] = true
315
+ win[r] = true
316
+
317
+ a , b , c := 0 , 0 , 0
318
+ for j := 0 ; j < n; j++ {
319
+ if j == l {
320
+ a = c
321
+ }
322
+ if j == r {
323
+ b = c
324
+ }
325
+ if win[j] {
326
+ c++
327
+ }
328
+ }
329
+
330
+ t := dfs (a, b, c)
331
+ if t[0 ]+1 < min {
332
+ min = t[0 ] + 1
333
+ }
334
+ if t[1 ]+1 > max {
335
+ max = t[1 ] + 1
336
+ }
337
+ }
338
+
339
+ f[l][r][n] = encode (min, max)
340
+ return []int {min, max}
341
+ }
342
+
343
+ func encode (x , y int ) int {
344
+ return (x << 8 ) | y
345
+ }
346
+
347
+ func decode (val int ) []int {
348
+ return []int {val >> 8 , val & 255 }
349
+ }
350
+ ```
351
+
352
+ #### TypeScript
353
+
354
+ ``` ts
355
+ function earliestAndLatest(n : number , firstPlayer : number , secondPlayer : number ): number [] {
356
+ return dfs (firstPlayer - 1 , secondPlayer - 1 , n );
357
+ }
358
+
359
+ const f: number [][][] = Array .from ({ length: 30 }, () =>
360
+ Array .from ({ length: 30 }, () => Array (31 ).fill (0 )),
361
+ );
362
+
363
+ function dfs(l : number , r : number , n : number ): number [] {
364
+ if (f [l ][r ][n ] !== 0 ) {
365
+ return decode (f [l ][r ][n ]);
366
+ }
367
+ if (l + r === n - 1 ) {
368
+ f [l ][r ][n ] = encode (1 , 1 );
369
+ return [1 , 1 ];
370
+ }
371
+
372
+ let min = Number .MAX_SAFE_INTEGER;
373
+ let max = Number .MIN_SAFE_INTEGER;
374
+ const m = n >> 1 ;
375
+
376
+ for (let i = 0 ; i < 1 << m ; i ++ ) {
377
+ const win: boolean [] = Array (n ).fill (false );
378
+ for (let j = 0 ; j < m ; j ++ ) {
379
+ if ((i >> j ) & 1 ) {
380
+ win [j ] = true ;
381
+ } else {
382
+ win [n - 1 - j ] = true ;
383
+ }
384
+ }
385
+
386
+ if (n & 1 ) {
387
+ win [m ] = true ;
388
+ }
389
+
390
+ win [n - 1 - l ] = false ;
391
+ win [n - 1 - r ] = false ;
392
+ win [l ] = true ;
393
+ win [r ] = true ;
394
+
395
+ let a = 0 ,
396
+ b = 0 ,
397
+ c = 0 ;
398
+ for (let j = 0 ; j < n ; j ++ ) {
399
+ if (j === l ) a = c ;
400
+ if (j === r ) b = c ;
401
+ if (win [j ]) c ++ ;
402
+ }
403
+
404
+ const t = dfs (a , b , c );
405
+ min = Math .min (min , t [0 ] + 1 );
406
+ max = Math .max (max , t [1 ] + 1 );
407
+ }
408
+
409
+ f [l ][r ][n ] = encode (min , max );
410
+ return [min , max ];
411
+ }
412
+
413
+ function encode(x : number , y : number ): number {
414
+ return (x << 8 ) | y ;
415
+ }
416
+
417
+ function decode(val : number ): number [] {
418
+ return [val >> 8 , val & 255 ];
419
+ }
120
420
```
121
421
122
422
<!-- tabs:end -->
0 commit comments