Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 74c17f5

Browse files
✨feat: Add 913
1 parent f99a2b2 commit 74c17f5

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

‎Index/记忆化搜索.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
| [494. 目标和](https://leetcode-cn.com/problems/target-sum/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/target-sum/solution/gong-shui-san-xie-yi-ti-si-jie-dfs-ji-yi-et5b/) | 中等 | 🤩🤩🤩🤩 |
77
| [552. 学生出勤记录 II](https://leetcode-cn.com/problems/student-attendance-record-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/student-attendance-record-ii/solution/gong-shui-san-xie-yi-ti-san-jie-ji-yi-hu-fdfx/) | 困难 | 🤩🤩🤩🤩 |
88
| [576. 出界的路径数](https://leetcode-cn.com/problems/out-of-boundary-paths/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/out-of-boundary-paths/solution/gong-shui-san-xie-yi-ti-shuang-jie-ji-yi-asrz/) | 中等 | 🤩🤩🤩🤩 |
9+
| [913. 猫和老鼠](https://leetcode-cn.com/problems/cat-and-mouse/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/cat-and-mouse/solution/gong-shui-san-xie-dong-tai-gui-hua-yun-y-0bx1/) | 困难 | 🤩🤩🤩🤩 |
910
| [1137. 第 N 个泰波那契数](https://leetcode-cn.com/problems/n-th-tribonacci-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/n-th-tribonacci-number/solution/gong-shui-san-xie-yi-ti-si-jie-die-dai-d-m1ie/) | 简单 | 🤩🤩🤩🤩 |
1011
| [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/) | 简单 | 🤩🤩🤩🤩🤩 |
1112

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[913. 猫和老鼠](https://leetcode-cn.com/problems/cat-and-mouse/solution/gong-shui-san-xie-dong-tai-gui-hua-yun-y-0bx1/)** ,难度为 **困难**
4+
5+
Tag : 「动态规划」、「记忆化搜索」
6+
7+
8+
9+
两位玩家分别扮演猫和老鼠,在一张**无向**图上进行游戏,两人轮流行动。
10+
11+
图的形式是:`graph[a]` 是一个列表,由满足 `ab` 是图中的一条边的所有节点 `b` 组成。
12+
13+
老鼠从节点 `1` 开始,第一个出发;猫从节点 `2` 开始,第二个出发。在节点 `0` 处有一个洞。
14+
15+
在每个玩家的行动中,他们 必须 沿着图中与所在当前位置连通的一条边移动。
16+
17+
例如,如果老鼠在节点 `1` ,那么它必须移动到 `graph[1]` 中的任一节点。
18+
19+
此外,猫无法移动到洞中(节点 `0`)。
20+
21+
然后,游戏在出现以下三种情形之一时结束:
22+
23+
如果猫和老鼠出现在同一个节点,猫获胜。
24+
如果老鼠到达洞中,老鼠获胜。
25+
如果某一位置重复出现(即,玩家的位置和移动顺序都与上一次行动相同),游戏平局。
26+
给你一张图 `graph`,并假设两位玩家都都以最佳状态参与游戏:
27+
* 如果老鼠获胜,则返回 `1`;
28+
* 如果猫获胜,则返回 `2`;
29+
* 如果平局,则返回 `0`
30+
31+
示例 1:
32+
![](https://assets.leetcode.com/uploads/2020/11/17/cat1.jpg)
33+
```
34+
输入:graph = [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
35+
36+
输出:0
37+
```
38+
示例 2:
39+
![](https://assets.leetcode.com/uploads/2020/11/17/cat2.jpg)
40+
```
41+
输入:graph = [[1,3],[0],[3],[0,2]]
42+
43+
输出:1
44+
```
45+
46+
提示:
47+
* 3 <= graph.length <= 50
48+
* 1 <= graph[i].length < graph.length
49+
* 0 <= graph[i][j] < graph.length
50+
* graph[i][j] != i
51+
* graph[i] 互不相同
52+
* 猫和老鼠在游戏中总是移动
53+
54+
---
55+
56+
### 动态规划
57+
58+
数据范围只有 50ドル,ドル使得本题的难度大大降低。
59+
60+
**定义 $f[k][i][j]$ 为当前进行了 $k$ 步,老鼠所在位置为 $i,ドル猫所在的位置为 $j$ 时,最终的获胜情况(0ドル$ 为平局,1ドル$ 和 2ドル$ 分别代表老鼠和猫获胜),起始我们让所有的 $f[i][j][k] = -1$(为无效值),最终答案为 $f[0][1][2]$。**
61+
62+
不失一般性的考虑 $f[i][j][k]$ 该如何转移,根据题意,将当前所在位置 $i$ 和 $j$ 结合「游戏结束,判定游戏」的规则来分情况讨论:
63+
64+
* 若 $i = 0,ドル说明老鼠位于洞中,老鼠获胜,此时有 $f[k][i][j] = 1$;
65+
* 若 $i = j,ドル说明两者为与同一位置,猫获胜,此时有 $f[k][i][j] = 2$;
66+
* 考虑如何定义平局,即 $f[k][i][j] = 0$ 的情况?
67+
68+
我们最多有 $n$ 个位置,因此 $(i, j)$ 位置对组合数最多为 $n^2$ 种,然后 $k$ 其实代表的是老鼠先手还是猫先手,共有 2ドル$ 种可能,因此状态数量数据有明确上界为 2ドル * n^2$。
69+
70+
所以我们可以设定 $k$ 的上界为 2ドル * n^2$(抽屉原理,走超过 2ドル * n^2$ 步,必然会有相同的局面出现过至少两次),但是这样的计算量为 2ドル * 50^2 * 50 * 50 = 1.25 * 10^7,ドル有 `TLE` 风险,转移过程增加剪枝,可以过。
71+
72+
而更小的 $k$ 值需要证明:在最优策略中,相同局面(状态)成环的最大长度的最小值为 $k$。
73+
74+
题目规定轮流移动,且只能按照 $graph$ 中存在的边进行移动。
75+
76+
1. 如果当前 $k$ 为偶数(该回合老鼠移动),此时所能转移所有点为 $f[k + 1][ne][j],ドル其中 $ne$ 为 $i$ 所能到达的点。由于采用的是最优移动策略,因此 $f[k][i][j]$ 会优先往 $f[k + 1][ne][j] = 1$ 的点移动(自身获胜),否则往 $f[k + 1][ne][j] = 0$ 的点移动(平局),再否则才是往 $f[k + 1][ne][j] = 2$ 的点移动(对方获胜);
77+
78+
2. 同理,如果当前 $k$ 为奇数(该回合猫移动),此时所能转移所有点为 $f[k + 1][i][ne],ドル其中 $ne$ 为 $j$ 所能到达的点。由于采用的是最优移动策略,因此 $f[k][i][j]$ 会优先往 $f[k + 1][i][ne] = 2$ 的点移动(自身获胜),否则往 $f[k + 1][i][ne] = 0$ 的点移动(平局),再否则才是往 $f[k + 1][i][ne] = 1$ 的点移动(对方获胜)。
79+
80+
使用该转移优先级进行递推即可,为了方便我们使用「记忆化搜索」的方式来实现动态规划。
81+
82+
注意,该优先级转移其实存在「贪心」决策,但证明这样的决策会使得「最坏情况最好」是相对容易的,而证明存在更小的 $k$ 值才是本题难点。
83+
84+
> 一些细节:由于本身就要对动规数组进行无效值的初始化,为避免每个样例都 `new` 大数组,我们使用 `static` 来修饰大数组,可以有效减少一点时间(不使用 `static` 的话,`N` 只能取到 51ドル$)。
85+
86+
代码:
87+
```Java
88+
class Solution {
89+
static int N = 55;
90+
static int[][][] f = new int[2 * N * N][N][N];
91+
int[][] g;
92+
int n;
93+
public int catMouseGame(int[][] graph) {
94+
g = graph;
95+
n = g.length;
96+
for (int k = 0; k < 2 * n * n; k++) {
97+
for (int i = 0; i < n; i++) {
98+
for (int j = 0; j < n; j++) {
99+
f[k][i][j] = -1;
100+
}
101+
}
102+
}
103+
return dfs(0, 1, 2);
104+
}
105+
// 0:draw / 1:mouse / 2:cat
106+
int dfs(int k, int a, int b) {
107+
int ans = f[k][a][b];
108+
if (a == 0) ans = 1;
109+
else if (a == b) ans = 2;
110+
else if (k >= 2 * n * n) ans = 0;
111+
else if (ans == -1) {
112+
if (k % 2 == 0) { // mouse
113+
boolean win = false, draw = false;
114+
for (int ne : g[a]) {
115+
int t = dfs(k + 1, ne, b);
116+
if (t == 1) win = true;
117+
else if (t == 0) draw = true;
118+
if (win) break;
119+
}
120+
if (win) ans = 1;
121+
else if (draw) ans = 0;
122+
else ans = 2;
123+
} else { // cat
124+
boolean win = false, draw = false;
125+
for (int ne : g[b]) {
126+
if (ne == 0) continue;
127+
int t = dfs(k + 1, a, ne);
128+
if (t == 2) win = true;
129+
else if (t == 0) draw = true;
130+
if (win) break;
131+
}
132+
if (win) ans = 2;
133+
else if (draw) ans = 0;
134+
else ans = 1;
135+
}
136+
}
137+
f[k][a][b] = ans;
138+
return ans;
139+
}
140+
}
141+
```
142+
* 时间复杂度:状态的数量级为 $n^4,ドル可以确保每个状态只会被计算一次。复杂度为 $O(n^4)$
143+
* 空间复杂度:$O(n^4)$
144+
145+
---
146+
147+
### 最后
148+
149+
这是我们「刷穿 LeetCode」系列文章的第 `No.913` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
150+
151+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
152+
153+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
154+
155+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
156+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /