作者: 负雪明烛
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:

  1. 3 <= graph.length <= 50
  2. It is guaranteed that graph[1] is non-empty.
  3. It is guaranteed that graph[2] contains a non-zero element.

题目大意

猫鼠游戏。

有一张无向图,包含最多50个结点。有两个玩家(Mouse和Cat)在图上,Mouse的起始位置是1,Cat的起始位置是2,0处有一个洞,Cat不能移动到0。Mouse和Cat在图上轮流移动,每次必须移动到与当前结点相邻的一个结点。

游戏有三种结束的可能:

  1. Cat和Mouse进入同一结点,则Cat胜利
  2. Mouse进入0结点,则Mouse胜利
  3. 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)的更多相关文章

  1. [LeetCode] 913. Cat and Mouse 猫和老鼠

    A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns. The grap ...

  2. 【LeetCode】62. Unique Paths 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...

  3. 【LeetCode】376. Wiggle Subsequence 解题报告(Python)

    [LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...

  4. 【LeetCode】649. Dota2 Senate 解题报告(Python)

    [LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...

  5. 【LeetCode】911. Online Election 解题报告(Python)

    [LeetCode]911. Online Election 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ ...

  6. 【LeetCode】886. Possible Bipartition 解题报告(Python)

    [LeetCode]886. Possible Bipartition 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu ...

  7. 【LeetCode】36. Valid Sudoku 解题报告(Python)

    [LeetCode]36. Valid Sudoku 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址 ...

  8. 【LeetCode】870. Advantage Shuffle 解题报告(Python)

    [LeetCode]870. Advantage Shuffle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn ...

  9. 【LeetCode】593. Valid Square 解题报告(Python)

    [LeetCode]593. Valid Square 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...

随机推荐

  1. C 语言do while 循环

    do while 循环小练习 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) 5 { 6 int a ...

  2. 利用plink软件基于LD信息过滤SNP

    最近有需求,对WGS测序获得SNP信息进行筛减,可问题是测序个体少,call rate,maf,hwe,等条件过滤后,snp数量还是千万级别,所以后面利用plink工具根据LD信息来滤除大量SNP标记 ...

  3. web自动化,selenium环境配置

    1,首先我们需要在python编译器中添加selenium插件,我用的是pycharm 点击下方的Terminal,然后在命令行输入: pip install selenium 也可以在设置里面手动添 ...

  4. java多线程 并发编程

    一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进程的地址空间是互相隔离的:进程拥有各种 ...

  5. Linux基础命令---vmstat显示虚拟内存状态

    vmstat vmstat指令用来显示虚拟内存使用状态,同时也可以显示进程.cpu活动情况.vmstat报告有关进程.内存.分页.块IO.陷阱和CPU活动的信息.生成的第一份报告给出了自上次重新启动以 ...

  6. redis入门到精通系列(八):redis的高可用--主从复制详解

    (一)主从复制介绍 前面所讲的关于redis的操作都属于单机操作,单机操作虽然操作简单,但是处理能力有限,无法高可用.所谓高可用性,就是指当一台服务器宕机的时候,有备用的服务器能顶替上,在单机操作上这 ...

  7. Spring MVC入门(一)—— RestTemplate组件

    ClientHttpRequestFactory 它是个函数式接口,用于根据URI和HttpMethod创建出一个ClientHttpRequest来发送请求~ ClientHttpRequest它代 ...

  8. Consumer方法结合Lambda表达式的应用

    package com.itheima.demo05.Consumer;import java.util.function.Consumer;/** * @author newcityman * @d ...

  9. 12.Vue.js 表单

    这节我们为大家介绍 Vue.js 表单上的应用. 你可以用 v-model 指令在表单控件元素上创建双向数据绑定. <div id="app"> <p>in ...

  10. 『与善仁』Appium基础 — 21、元素的基本操作

    目录 1.元素的基本操作说明 (1)点击操作 (2)清空操作 (3)输入操作 2.综合练习 1.元素的基本操作说明 (1)点击操作 点击操作:click()方法.(同Selenium中使用方式一致) ...