AlgoNote 算法通关手册:0913 猫和老鼠(Cat and Mouse)博弈论与拓扑排序解法深度解析
教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载导读本文围绕《算法通关手册》题库中的困难题 0913. 猫和老鼠 展开完整讲解猫鼠博弈这一经典零和博弈 图论综合题的题面建模、状态设计以及如何用逆向思维 拓扑排序在 $O(n^3)$ 时间内判定在双方均采用最优策略时的胜负结果。读完本文你将掌握一套可迁移的从终局状态反推初始状态的博弈求解框架并能在 LeetCode 上直接运行给出的 Python 实现同时理解它与仓库中 Kahn 拓扑排序、DFS 拓扑排序 的底层联系。一、题目总览猫和老鼠的无向图追逐游戏1.1 题目大意两位玩家分别扮演猫和老鼠在一张无向图上进行追逐游戏两人轮流行动图以邻接表形式给出graph[a]是由所有满足「$ab$ 是一条边」的节点 $b$ 组成的列表老鼠从节点1出发并先手行动猫从节点2出发后手行动节点0是老鼠的洞每个玩家每次行动必须沿一条边移动到相邻节点如老鼠在节点 1就必须移动到graph[1]中的某个节点特殊限制猫不能进入洞节点 0。游戏在以下三种情形之一出现时结束猫与老鼠出现在同一节点→ 猫获胜老鼠到达洞节点 0→ 老鼠获胜某一位置重复出现玩家的位置与移动顺序和上一次行动完全相同→ 平局。要求在双方都采取最优策略的前提下返回游戏结果——老鼠获胜返回1猫获胜返回2平局返回0。1.2 数据范围$3 \le graph.length \le 50$节点数 $n$ 至多 50$1 \le graph[i].length graph.length$每个节点至少有一条出边游戏总能进行$0 \le graph[i][j] graph.length$且 $graph[i][j] \ne i$无自环各节点的邻接列表互不相同。1.3 示例示例 1输入graph [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]] 输出0猫和老鼠在这张图上各自有多个策略分支双方都可以通过最优走法回避对方的必胜陷阱最终进入重复局面判定为平局。示例 2输入graph [[1,3],[0],[3],[0,2]] 输出1此时老鼠可以凭借更优的走位率先抵达节点 0洞从而获得胜利。提示示例配图为官方题面示意图重点在于理解邻接表结构与洞 0 / 起点 1 / 起点 2的位置关系本仓库文档仅以文本方式复述读者可直接在力扣题面查看原图。二、解题思路博弈论 拓扑排序2.1 为什么不能直接模拟猫鼠双方轮流行动、目标相互对立属于典型的零和博弈。若直接按当前局面谁优进行贪心或暴力搜索会陷入两个困难状态空间大$mouse \in [0, n)$、$cat \in [0, n)$、行动方 $turn \in {1, 2}$共 $2n^2$ 个状态存在平局循环某些状态既不是任何一方的必胜态也不会通向终结局面而是会陷入重复循环。因此需要一种能够同时处理必胜 / 必败 / 平局三类结果的确定性算法——**逆向拓扑排序Retrograde Analysis**恰好满足需求。2.2 状态与结果定义定义三元组状态$(mouse, cat, turn)$老鼠在节点 $mouse$猫在节点 $cat$当前轮到 $turn$ 行动$1$ 表示老鼠$2$ 表示猫。状态结果取值$0$平局DRAW$1$老鼠获胜MOUSE_WIN$2$猫获胜CAT_WIN。2.3 逆向思维从终局反推初始状态与正向模拟不同拓扑排序解法从已知结果的终结状态出发反向推导前驱状态。其正确性依据是博弈论的经典递推规则若某一状态存在一个后继状态对当前行动方有利则当前状态对当前行动方有利当前玩家会主动选择这条最优路线若某一状态的所有后继状态都对对手有利即对当前行动方全部不利则当前状态对当前行动方不利。具体分三步初始化终结状态老鼠到达洞口$mouse 0$→ 老鼠获胜结果置为1猫抓到老鼠$mouse cat$且 $cat \ne 0$→ 猫获胜结果置为2。按逆拓扑序传播结果从已知结果的状态出队考察所有可能的前驱状态。前驱状态若存在通往己方获胜的后继直接判胜否则将其剩余未定后继数出度减一当出度归零时说明所有后继都对己方不利判负。返回初始状态结果$(1, 2, 1)$即老鼠在 1、猫在 2、老鼠先手时的最终胜负值。这一从终局反推的技巧在仓库 06_05_graph_topological_sorting.md 讲解的拓扑排序思想上一脉相承——只不过经典拓扑排序通过入度归零确定依赖顺序这里通过出度归零确定所有分支均不利的必败状态。三、完整代码实现3.1 Python 实现可直接提交class Solution: def catMouseGame(self, graph: List[List[int]]) - int: n len(graph) DRAW, MOUSE_WIN, CAT_WIN 0, 1, 2 # 状态(mouse, cat, turn)turn1 表示老鼠turn2 表示猫 # 结果0平局1老鼠赢2猫赢 result [[[DRAW] * 3 for _ in range(n)] for _ in range(n)] degree [[[0] * 3 for _ in range(n)] for _ in range(n)] # 计算每个状态的出度后继状态数 for mouse in range(n): for cat in range(n): degree[mouse][cat][1] len(graph[mouse]) # 猫不能移动到洞节点 0因此出度要去掉 0 degree[mouse][cat][2] len([node for node in graph[cat] if node ! 0]) # 初始化队列已知结果的状态 from collections import deque queue deque() for cat in range(n): for turn in [1, 2]: # 老鼠到达洞口老鼠赢 result[0][cat][turn] MOUSE_WIN queue.append((0, cat, turn)) # 猫抓到老鼠但猫不能在洞口猫赢 if cat 0: result[cat][cat][turn] CAT_WIN queue.append((cat, cat, turn)) # 拓扑排序逆向传播 while queue: mouse, cat, turn queue.popleft() current_result result[mouse][cat][turn] if turn 1: # 当前是老鼠的回合推导上一步猫的状态 for prev_cat in graph[cat]: if prev_cat 0: # 猫不能进洞 continue if result[mouse][prev_cat][2] ! DRAW: continue if current_result CAT_WIN: # 如果老鼠这步后猫赢说明猫的上一步可以导致猫赢 result[mouse][prev_cat][2] CAT_WIN queue.append((mouse, prev_cat, 2)) else: # 否则减少出度 degree[mouse][prev_cat][2] - 1 if degree[mouse][prev_cat][2] 0: # 所有后继状态都对猫不利猫输 result[mouse][prev_cat][2] MOUSE_WIN queue.append((mouse, prev_cat, 2)) else: # 当前是猫的回合推导上一步老鼠的状态 for prev_mouse in graph[mouse]: if result[prev_mouse][cat][1] ! DRAW: continue if current_result MOUSE_WIN: # 如果猫这步后老鼠赢说明老鼠的上一步可以导致老鼠赢 result[prev_mouse][cat][1] MOUSE_WIN queue.append((prev_mouse, cat, 1)) else: # 否则减少出度 degree[prev_mouse][cat][1] - 1 if degree[prev_mouse][cat][1] 0: # 所有后继状态都对老鼠不利老鼠输 result[prev_mouse][cat][1] CAT_WIN queue.append((prev_mouse, cat, 1)) return result[1][2][1]3.2 关键实现细节逐行解读出度计算第 1418 行$turn1$老鼠回合的出度是len(graph[mouse])$turn2$猫回合的出度必须过滤掉节点 0因为猫不能进洞这与题面约束严格对应。终结状态初始化第 2331 行对任意 $cat$ 与任意 $turn$$(0, cat, turn)$ 都是老鼠必胜$(cat, cat, turn)$$cat0$ 时都是猫必胜。它们作为拓扑排序的源点入队。回合反向传播第 3362 行当前结果对上一步行动方不利时如当前老鼠回合得到CAT_WIN说明猫的上一步 $(mouse, prev_cat, 2)$ 存在一个导致猫赢的后继直接给前驱状态判胜否则将前驱状态的degree减一代表这个前驱状态的一个后继分支已确定对己方不利当degree归零时说明其所有后继都对己方不利从而判定前驱状态必败。返回初始局面result[1][2][1]即老鼠在 1、猫在 2、老鼠先手的最终结果。3.3 复杂度分析时间复杂度$O(n^3)$其中 $n$ 是图中节点数$n \le 50$。每个状态至多入队一次每次出队需要遍历前驱边总边数为 $O(n^2)$ 量级状态总数为 $O(n^2)$综合为 $O(n^3)$。空间复杂度$O(n^2)$需要存储全部状态的result与degree数组各为 $n \times n \times 3$。在 $n50$ 的规模下$O(n^3)$ 完全可接受这也是该解法能在力扣通过全部测试用例的原因。四、与仓库源码的联动拓扑排序在 AlgoNote 中的完整脉络4.1 算法分类归属在《算法通关手册》的分类体系中本题被归入图、拓扑排序、记忆化搜索、数学、动态规划、博弈复合标签可见于 00_06_categories_list.md 的题解总表同时被收录进 00_05_solutions_list.md 的完整题解清单。4.2 底层的拓扑排序实现对照本解法本质上是在博弈状态图上做逆向拓扑排序其队列驱动的核心结构与仓库中 Graph-Topological-Sorting-Kahn.py 一脉相承Kahn 算法维护indegrees入度字典将入度为 0 的节点入队出队时将其所有后继节点的入度减一入度归零者继续入队直至队列为空若最终拓扑序列长度不等于节点总数则说明图中存在环。本题的逆向版本则维护degree剩余未定后继数将结果已定的终结状态入队出队时将其前驱状态的剩余后继数减一归零者判定为必败并入队。可以对照观察# 来自 codes/python/06_graph/Graph-Topological-Sorting-Kahn.py while S: u S.pop() # 从集合中选择一个没有前驱的顶点 order.append(u) # 将其输出到拓扑序列 order 中 for v in graph[u]: # 遍历顶点 u 的邻接顶点 v indegrees[v] - 1 # 删除从顶点 u 出发的有向边 if indegrees[v] 0: # 如果删除该边后顶点 v 的入度变为 0 S.append(v) # 将其放入集合 S 中同样的度归零 → 入队 → 扩散模式前者用于判断有向无环图中的依赖顺序后者用于在博弈状态图中扩散必胜 / 必败结论。仓库还提供 DFS 版本 Graph-Topological-Sorting-DFS.py可作为理解拓扑序两种实现方式的补充阅读材料。4.3 从题库到手册的延伸学习本题的逆向博弈思想与以下仓库资源相互印证适合按序进阶06_05_graph_topological_sorting.md拓扑排序完整理论Kahn 与 DFS 两种实现、环检测、典型应用07_04_backtracking_algorithm.md博弈类问题另一常用手段——带记忆化搜索的回溯配合turn轮换与结果缓存可处理较小规模的类似博弈题题库中的其他两人最优博弈类题目如 0292 Nim 游戏、0486 预测赢家等可分别从 nims 相关文档 与 predict-the-winner.md 入手对照练习。五、总结0913 猫和老鼠是一道把零和博弈与图论逆向拓扑排序结合到极致的困难题其核心方法论可以提炼为三步建模把局面压缩为 $(mouse, cat, turn)$ 三元组状态明确三类结果鼠胜 / 猫胜 / 平局逆向从老鼠到洞猫鼠同点两个确定终局反向传播用存在有利后继 → 胜全部不利 → 负的规则在状态图上扩散结论收敛未被任何结果覆盖的状态自然就是平局循环局面最终返回初始状态 $(1, 2, 1)$ 的结果即可。掌握这套终局反推 出度归零的框架后遇到任何双方最优博弈 平局处理的题目你都可以快速套用这也正是《算法通关手册》在 0913. 猫和老鼠 中沉淀下来的核心解题范式。赞分享教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载相关推荐LeetCode 207「课程表」用图论拓扑排序判断课程依赖环AlgoNote 算法通关手册实战解析LeetCode 207「课程表」用图论拓扑排序判断课程依赖环AlgoNote 算法通关手册实战解析 导读 本篇技术指南基于 AlgoNote「算法通关手教程文档知识库AlgoNote 算法通关手册LeetCode 0046「全排列」回溯算法深度解析AlgoNote 算法通关手册LeetCode 0046「全排列」回溯算法深度解析 全排列Permutations是回溯算法最经典的入门问题也是算法面试教程文档知识库AlgoNote 算法通关手册LeetCode 0444 序列重建题解——用「唯一拓扑排序」判断最短超序列AlgoNote 算法通关手册LeetCode 0444 序列重建题解——用「唯一拓扑排序」判断最短超序列 本篇是「算法通关手册」AlgoNote 中 Lee教程文档知识库上一篇NSC_BUILDER30功能集成的Switch游戏文件处理全能工具下一篇QKeyMapper按键映射工具终极指南让游戏手柄玩转所有PC游戏创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

栈与队列核心考点:双栈模拟、括号匹配与逆波兰表达式

栈与队列核心考点:双栈模拟、括号匹配与逆波兰表达式

代码随想录算法训练营刷到 Day10,主题是栈与队列。很多刷题的人会觉得,栈和队列属于“我早就懂了”的数据结构——一个先进后出、一个先进先出,概念一两句话就能讲完。但真到了笔试现场,被“用栈实现队列”“用队列实现栈”这种题…

2026/10/10 2:17:54 阅读更多 →
StackExchange.Redis 中的 Redis Vector Sets 实战指南:从向量写入到相似度搜索的完整 API 解析

StackExchange.Redis 中的 Redis Vector Sets 实战指南:从向量写入到相似度搜索的完整 API 解析

后端缓存数据库客户端消息队列 【免费下载链接】StackExchange.Redis The Redis client for .NET 项目地址: https://gitcode.com/gh_mirrors/st/StackExchange.Redis 点击查看 免费下载 Redis Vector Sets(向量集合)是 Redis 8.0 起提供的向…

2026/10/10 2:17:54 阅读更多 →
Panda CSS 虚拟 styled-system 指南:npm 设计系统消费与 Overlay 代码生成

Panda CSS 虚拟 styled-system 指南:npm 设计系统消费与 Overlay 代码生成

前端构建工具开发工具 【免费下载链接】panda 🐼 Universal, Type-Safe, CSS-in-JS Framework for Design Systems ⚡️ 项目地址: https://gitcode.com/gh_mirrors/pa/panda 点击查看 免费下载 导读 本文讲解 Panda CSS 仓库中“虚拟 styled-system&a…

2026/10/10 2:17:53 阅读更多 →

最新新闻

【会议征稿】第三届数字经济与计算机科学国际学术会议(DECS 2026)

【会议征稿】第三届数字经济与计算机科学国际学术会议(DECS 2026)

第三届数字经济与计算机科学国际学术会议 (DECS 2026) 2026 3rdInternational Conference on Digital Economy and Computer Science 会议官网: 第三届数字经济与计算机科学国际学术会议(DECS 2026)https://ais.cn/…

2026/10/10 2:57:07 阅读更多 →
论文阅读-EATA

论文阅读-EATA

EATA:Efficient Test-Time Model Adaptation without Forgetting论文:Efficient Test-Time Model Adaptation without Forgetting 会议:ICML 2022 核心思想:不是所有测试样本都值得用于模型更新。EATA 在 TENT 的熵最小化基础上&a…

2026/10/10 2:57:07 阅读更多 →
安徽皖上好影视制作公司 擅长人物传记片、活动花絮视频的创意制作

安徽皖上好影视制作公司 擅长人物传记片、活动花絮视频的创意制作

影视制作行业发展态势与皖上好的业务定位随着数字化传播时代的全面到来,视频内容已经成为政企单位与商业品牌对外展示形象、传递价值的核心载体。无论是政务宣传、校园文化传播,还是企业品牌推广、活动记录留存,人物传记片与活动花絮视频的需…

2026/10/10 2:57:07 阅读更多 →
工业智能体:小白也能学会的大模型应用指南(收藏必备)

工业智能体:小白也能学会的大模型应用指南(收藏必备)

本文介绍了工业智能体的概念、发展现状、产业生态布局以及典型应用案例。工业智能体以大模型为核心,深度融合工业知识与AI技术,实现环境感知、逻辑推理、任务规划等功能。文章还分析了工业智能体推动“人工智能制造”落地的机理,包括知识内化…

2026/10/10 2:57:07 阅读更多 →
Solidity 基础语法:用五个小案例,把语法学成肌肉记忆

Solidity 基础语法:用五个小案例,把语法学成肌肉记忆

前两篇我们聊了学习路径和三个实战合约。但有个问题一直悬着:很多人的语法是"拼凑"出来的,不是"理解"出来的。他们能写 mapping(address > uint256),但说不清为什么不用数组;能用 modifier,但不…

2026/10/10 2:57:07 阅读更多 →
同城跑腿系统:骑手端同步和下单收款怎么拆

同城跑腿系统:骑手端同步和下单收款怎么拆

同城跑腿系统联调时,常见做法是支付一通就对外宣称上线。更稳的做法是把「下单与订单状态」和「收款回调」拆阶段验收:前者不依赖真实通道,后者用沙箱 profile,避免支付未过却改订单写入口。结论 订单状态推进应由领域事件驱动&am…

2026/10/10 2:56:07 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →