【LeetCode】913. Cat and Mouse 解题报告(Python)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/cat-and-mouse/description/
题目描述
A game on an undirected
graph is played by two players, Mouse and Cat, who alternate turns.
The graph is given as follows: graph[a]
is a list of all nodes b
such that ab
is an edge of the graph.
Mouse starts at node 1 and goes first, Cat starts at node 2 and goes second, and there is a Hole at node 0.
During each player’s turn, they must travel along one edge of the graph that meets where they are. For example, if the Mouse is at node 1
, it must
travel to any node in graph[1]
.
Additionally, it is not allowed for the Cat to travel to the Hole (node 0.)
Then, the game can end in 3 ways:
- If ever the Cat occupies the same node as the Mouse, the Cat wins.
- If ever the Mouse reaches the Hole, the Mouse wins.
- If ever a position is repeated (ie. the players are in the same position as a previous turn, and it is the same player’s turn to move), the game is a draw.
Given a graph
, and assuming both players play optimally, return 1
if the game is won by Mouse, 2
if the game is won by Cat, and 0
if the game is a draw.
Example 1:
Input: [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
Output: 0
Explanation:
4---3---1
| |
2---5
\ /
0
Note:
- 3 <= graph.length <= 50
- It is guaranteed that graph[1] is non-empty.
- It is guaranteed that graph[2] contains a non-zero element.
题目大意
猫鼠游戏。
有一张无向图,包含最多50个结点。有两个玩家(Mouse和Cat)在图上,Mouse的起始位置是1,Cat的起始位置是2,0处有一个洞,Cat不能移动到0。Mouse和Cat在图上轮流移动,每次必须移动到与当前结点相邻的一个结点。
游戏有三种结束的可能:
- Cat和Mouse进入同一结点,则Cat胜利
- Mouse进入0结点,则Mouse胜利
- Cat和Mouse的位置和回合发生了重复,则平局
问:如果Cat和Mouse都以最优策略行动,最后的结果是什么?
解题方法
这个题实在太难了,我只能参考别人的做法了。正确的做法应该是BFS,而且是已知结果倒着求过程的BFS。
设计节点状态是(m,c,turn),用color[m][c][turn]来记忆该状态的输赢情况.
首先我们将所有已知的确定状态加入一个队列.已知状态包括(0,c,turn)肯定是老鼠赢,(x,x,turn)且x!=0肯定是猫赢。我们尝试用BFS的思路,将这些已知状态向外扩展开去.
扩展的思路是:从队列中取出队首节点状态(m,c,t),找到它的所有邻接的parent的状态(m2,c2,t2).这里的父子关系是指,(m2,c2,t2)通过t2轮(老鼠或猫)的操作,能得到(m,c,t).我们发现,如果(m,c,t)是老鼠赢而且t2是老鼠轮,那么这个(m2,c2,t2)一定也是老鼠赢.同理,猫赢的状态也类似.于是,我们找到了一种向外扩展的方法.
向外扩展的第二个思路是:对于(m2,c2,t2),我们再去查询它的所有children(必定是对手轮)是否都已经标注了赢的状态.如果都是赢的状态,那么说明(m2,c2,t2)无路可走,只能标记为输的状态.特别注意的是,第一条规则通过child找parent,和第二条规则通过parent找child的算法细节是不一样的,一定要小心.
这样我们通过BFS不断加入新的探明输赢的节点.直到队列为空,依然没有探明输赢的节点状态,就是平局的意思!
最后输出(1, 2, MOUSE)的颜色。没有被染过色说明是平局。
时间复杂度是O(VE),空间复杂度是O(V).
class Solution(object):
def catMouseGame(self, graph):
"""
:type graph: List[List[int]]
:rtype: int
"""
N = len(graph)
MOUSE, CAT = 1, 2
# mouse, cat, turn
color = [[[0] * 3 for i in range(N)] for j in range(N)]
q = collections.deque()
for i in range(1, N):
for t in range(1, 3):
color[0][i][t] = 1
q.append((0, i, t))
color[i][i][t] = 2
q.append((i, i, t))
while q:
curStatus = q.popleft()
cat, mouse, turn = curStatus
for preStatus in self.findAllPrevStatus(graph, curStatus):
preCat, preMouse, preTurn = preStatus
if color[preCat][preMouse][preTurn] != 0:
continue
if color[cat][mouse][turn] == 3 - turn:
color[preCat][preMouse][preTurn] = preTurn
q.append(preStatus)
elif self.allNeighboursWin(color, graph, preStatus):
color[preCat][preMouse][preTurn] = 3 - preTurn
q.append(preStatus)
return color[1][2][1]
def findAllPrevStatus(self, graph, curStatus):
ret = []
mouse, cat, turn = curStatus
if turn == 1:
for preCat in graph[cat]:
if preCat == 0:
continue
ret.append((mouse, preCat, 2))
else:
for preMouse in graph[mouse]:
ret.append((preMouse, cat, 1))
return ret
def allNeighboursWin(self, color, graph, status):
mouse, cat, turn = status
if turn == 1:
for nextMouse in graph[mouse]:
if color[nextMouse][cat][2] != 2:
return False
elif turn == 2:
for nextCat in graph[cat]:
if nextCat == 0:
continue
if color[mouse][nextCat][1] != 1:
return False
return True
参考资料
https://zhanghuimeng.github.io/post/leetcode-913-cat-and-mouse/
https://github.com/wisdompeak/LeetCode/tree/master/BFS/913.Cat-and-Mouse
日期
2018 年 10 月 24 日 —— 程序员节被严重炒作了啊
【LeetCode】913. Cat and Mouse 解题报告(Python)的更多相关文章
- [LeetCode] 913. Cat and Mouse 猫和老鼠
A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns. The grap ...
- 【LeetCode】62. Unique Paths 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...
- 【LeetCode】376. Wiggle Subsequence 解题报告(Python)
[LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...
- 【LeetCode】649. Dota2 Senate 解题报告(Python)
[LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
- 【LeetCode】911. Online Election 解题报告(Python)
[LeetCode]911. Online Election 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ ...
- 【LeetCode】886. Possible Bipartition 解题报告(Python)
[LeetCode]886. Possible Bipartition 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu ...
- 【LeetCode】36. Valid Sudoku 解题报告(Python)
[LeetCode]36. Valid Sudoku 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址 ...
- 【LeetCode】870. Advantage Shuffle 解题报告(Python)
[LeetCode]870. Advantage Shuffle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn ...
- 【LeetCode】593. Valid Square 解题报告(Python)
[LeetCode]593. Valid Square 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
随机推荐
- python-django-模板标签
注意:这个控制语句和python的差不多,但是记住必须有endfor 和endif 结尾 模板文件的django格式的注释是不会出现再网页渲染的源代码当中的 使用列子: <!DOCTYPE ht ...
- Markdown—.md文件是什么?怎么打开?
md全称markdown,markdown也是一种标记语言. md文件其实可以用常用的文本编辑器都可以打开. 用记事本打开,把markdown文件拖到记事本图标上就可以打开 . 用 subli ...
- 学习java的第八天
一.今日收获 1.学习完全学习手册上2.3转义字符与2.4运算符两节 二.今日难题 1.没有什么难理解的问题 三.明日目标 1.哔哩哔哩教学视频 2.Java学习手册
- Set && Map
ES6 提供了新的数据结构 Set, Map Set成员的值都是唯一的,没有重复的值,Set内的元素是强类型,会进行类型检查. let set = new Set([1, true, '1', 'tr ...
- css通配样式初始化(多款,供君自选)
腾讯官网 body,ol,ul,h1,h2,h3,h4,h5,h6,p,th,td,dl,dd,form,fieldset,legend,input,textarea,select{margin:0; ...
- 【STM8】添加头文件、加入库函数
下面顺便放上STM8L15x-16x-05x的固件库,以及固件库里没有的<stm8l15x_conf.h> 链接打开后,还会发现另外两个文件夹,<src><inc> ...
- spring注解-扩展原理
AnnotationConfigApplicationContext(IOC容器)的有参构造方法中,在refresh()里对这些组件进行初始化 BeanPostProcessor bean后置处理器, ...
- malloc() vs new
Following are the differences between malloc() and operator new. (1)new calls constructors, while ma ...
- 【Matlab】求矩阵行和/列和
行和 sum(a, 2) 列和 sum(a) 所有元素之和 sum(sum(a)) 某一列元素之和 sum(a(:,1)) %a矩阵的第一列之和 某一行元素之和 sum(a(1,:)) %a矩阵的第一 ...
- Java高精度基础+开根
在焦作站的acm网络赛中遇到了一个高精度开根的水题--但是那时候WA了 后面学写java补题还T了orz 所以写一篇文章来记录一下java的大整数类型的基础和开根还有一点心得体会吧 首先给那一题的题面 ...