两个玩家分别扮演猫(Cat)和老鼠(Mouse)在无向图上进行游戏,他们轮流行动。
该图按下述规则给出:graph[a] 是所有结点 b 的列表,使得 ab 是图的一条边。
老鼠从结点 1 开始并率先出发,猫从结点 2 开始且随后出发,在结点 0 处有一个洞。
在每个玩家的回合中,他们必须沿着与他们所在位置相吻合的图的一条边移动。例如,如果老鼠位于结点 1,那么它只能移动到 graph[1] 中的(任何)结点去。
此外,猫无法移动到洞(结点 0)里。
然后,游戏在出现以下三种情形之一时结束:
如果猫和老鼠占据相同的结点,猫获胜。
如果老鼠躲入洞里,老鼠获胜。
如果某一位置重复出现(即,玩家们的位置和移动顺序都与上一个回合相同),游戏平局。
给定 graph,并假设两个玩家都以最佳状态参与游戏,如果老鼠获胜,则返回 1;如果猫获胜,则返回 2;如果平局,则返回 0。
示例:
输入:[[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
输出:0
解释:
4---3---1
| |
2---5
\ /
0
提示:
3 <= graph.length <= 200
保证 graph[1] 非空。
保证 graph[2] 包含非零元素。
设图中节点数为n
dp数组dp[c][m][d]c为cat的位置,m是mouse的位置,d是当前已经走的步数
判断是够会平局就是判断是否会出现重复的路线,当每个人都走n步,共计2n步时一定会出现重复路线,即可返回0(平局)
当c==m的时候老鼠和猫在同一位置,返回2,猫胜,当m==0时老鼠回到洞里,返回1,老鼠胜
但要注意c不能等于0
dfs实现中通过当前d的奇偶判断到谁的回合,在猫的回合中假设猫会选择最优解,所以所有下一可行节点中只要有一个是可以返回2的,就直接返回dp[c][m][d]=2,若没有一定获胜的可能性,也不能直接判断当前dp[c][m][d]是等于0还是等于1,因为猫会选择最优解,所以除非所有可行节点全部返回1(老鼠胜),否则一定会反会0
老鼠的回合同理
具体实现看代码
class Solution {
public:
int catMouseGame(vector>& graph) {
int n = graph.size();
vector>> dp(n, vector>(n, vector(n * 2, -1)));
return dfs(2, 1, 0, graph, dp);
}
int dfs(int c, int m, int d, vector>& v, vector>>& dp) {
if(d == 2 * v.size()) return 0;
if(c == m) return dp[c][m][d] = 2;
if(m == 0) return dp[c][m][d] = 1;
if(dp[c][m][d] != -1) return dp[c][m][d];
if(d & 1) {
bool mw = 1;
for(int i = 0; i < v[c].size(); i++) {
if(v[c][i] == 0) continue;
int next = dfs(v[c][i], m, d + 1, v, dp);
if(next == 2) return dp[c][m][d] = 2;
else if(next != 1) mw = 0;
}
if(mw) return dp[c][m][d] = 1;
else return dp[c][m][d] = 0;
} else {
bool cw = 1;
for(int i = 0; i < v[m].size(); i++) {
int next = dfs(c, v[m][i], d + 1, v, dp);
if(next == 1) return dp[c][m][d] = 1;
else if(next != 2) cw = 0;
}
if(cw) return dp[c][m][d] = 2;
else return dp[c][m][d] = 0;
}
}
};