题目

思路

博弈问题
这道题是博弈问题,猫和老鼠都按照最优策略参与游戏。

在阐述具体解法之前,首先介绍博弈问题中的三个概念:必胜状态、必败状态与必和状态。

对于特定状态,如果游戏已经结束,则根据结束时的状态决定必胜状态、必败状态与必和状态。

如果分出胜负,则该特定状态对于获胜方为必胜状态,对于落败方为必败状态。

如果是平局,则该特定状态对于双方都为必和状态。

从特定状态开始,如果存在一种操作将状态变成必败状态,则当前玩家可以选择该操作,将必败状态留给对方玩家,因此该特定状态对于当前玩家为必胜状态。

从特定状态开始,如果所有操作都会将状态变成必胜状态,则无论当前玩家选择哪种操作,都会将必胜状态留给对方玩家,因此该特定状态对于当前玩家为必败状态。

从特定状态开始,如果任何操作都不能将状态变成必败状态,但是存在一种操作将状态变成必和状态,则当前玩家可以选择该操作,将必和状态留给对方玩家,因此该特定状态对于双方玩家都为必和状态。

对于每个玩家,最优策略如下:

争取将必胜状态留给自己,将必败状态留给对方玩家。

在自己无法到达必胜状态的情况下,争取将必和状态留给自己。

方法

动态规划
dp[mouse][cat][turns]表示从老鼠位于节点mouse、猫位于节点cat、游戏进行了turns轮的状态开始,猫和老鼠都按照最优策略的情况下的游戏结果。
由于游戏的初始状态是老鼠位于节点 1,猫位于节点 2,因此 dp[1][2][0] 为从初始状态开始的游戏结果。
三种结果:
1.如果mouse=0, 老鼠躲入洞里,则老鼠获胜,因此dp[0][][]=1;
2.如果cat=mouse,猫捉到老鼠,猫赢,然而猫不能进洞,则mouse=0时,cat≠mouse;
3.如果turns≥2n,则为平局。

如果游戏已经进行了 2n 轮,但是仍然没有任何一方获胜,此时猫和老鼠各移动了 n 次,该移动次数等于图中的节点数,因此一定存在一个老鼠到达过至少两次的节点,以及一定存在一个猫到达过至少两次的节点。

对于老鼠而言,即使按照最优策略,也无法躲入洞内,而是只能回到一个已经到达过的节点。当老鼠回到一个在过去的某个回合已经到达过的节点时,猫可能回到在相同回合已经到达过的节点,也可能移动到一个更有利于猫获胜的节点,不可能移动到一个更有利于老鼠获胜的节点(否则猫就不是按照最优策略参与游戏)。如果猫回到在相同回合已经到达过的节点,则形成循环,因此是平局;如果猫移动到一个更有利于猫获胜的节点,则老鼠的获胜机会更小,因此老鼠无法获胜。

同理可知,如果猫按照最优策略也只能回到一个已经到达过的节点,则猫无法获胜。
因此当猫和老鼠分别回到一个已经到达过的节点时,猫和老鼠都无法获胜,游戏结果是平局。

具体算法

turns为偶数,老鼠移动,繁殖猫移动
如果轮到老鼠移动,则对于老鼠从当前节点移动一次之后可能到达的每个节点,进行如下操作:

  1. 如果存在一个节点,老鼠到达该节点之后,老鼠可以获胜,则老鼠到达该节点之后的状态为老鼠的必胜状态,猫的必败状态,因此在老鼠移动之前的当前状态为老鼠的必胜状态。

  2. 如果老鼠到达任何节点之后的状态都不是老鼠的必胜状态,但是存在一个节点,老鼠到达该节点之后,结果是平局,则老鼠到达该节点之后的状态为双方的必和状态,因此在老鼠移动之前的当前状态为双方的必和状态。

  3. 如果老鼠到达任何节点之后的状态都不是老鼠的必胜状态或必和状态,则老鼠到达任何节点之后的状态都为老鼠的必败状态,猫的必胜状态,因此在老鼠移动之前的当前状态为老鼠的必败状态。

如果轮到猫移动,则对于猫从当前节点移动一次之后可能到达的每个节点,进行如下操作:

  1. 如果存在一个节点,猫到达该节点之后,猫可以获胜,则猫到达该节点之后的状态为猫的必胜状态,老鼠的必败状态,因此在猫移动之前的当前状态为猫的必胜状态。

  2. 如果猫到达任何节点之后的状态都不是猫的必胜状态,但是存在一个节点,猫到达该节点之后,结果是平局,则猫到达该节点之后的状态为双方的必和状态,因此在猫移动之前的当前状态为双方的必和状态。

  3. 如果猫到达任何节点之后的状态都不是猫的必胜状态或必和状态,则猫到达任何节点之后的状态都为猫的必败状态,老鼠的必胜状态,因此在猫移动之前的当前状态为猫的必败状态。

实现方面,由于双方移动的策略相似,因此可以使用一个函数实现移动策略,根据游戏已经进行的轮数的奇偶性决定当前轮到的玩家。对于特定玩家的移动,实现方法如下:

  1. 如果当前玩家存在一种移动方法到达非必败状态,则用该状态更新游戏结果。
    如果该移动方法到达必胜状态,则将当前状态(移动前的状态)设为必胜状态,结束遍历其他可能的移动。
    如果该移动方法到达必和状态,则将当前状态(移动前的状态)设为必和状态,继续遍历其他可能的移动,因为可能存在到达必胜状态的移动方法。
  2. 如果当前玩家的任何移动方法都到达必败状态,则将当前状态(移动前的状态)设为必败状态。

特别地,如果当前玩家是猫,则不能移动到节点 00。

class Solution {const int MOUSE_WIN = 1;const int CAT_WIN = 2;const int DRAW = 0;const int MAXN = 51;
public:int n;vector<vector<vector<int>>> dp;vector<vector<int>> graph;int catMouseGame(vector<vector<int>>& graph) {this->n = graph.size();this->graph = graph;this->dp = vector<vector<vector<int>>>(n, vector<vector<int>>(n, vector<int>(n * 2 + 1, -1)));return getResult(1, 2, 0);}int getResult(int mouse, int cat, int turns) {if (turns >= n << 1)return DRAW;if (dp[mouse][cat][turns] < 0)if (mouse == 0)dp[mouse][cat][turns] = MOUSE_WIN;else if (cat == mouse)dp[mouse][cat][turns] = CAT_WIN;elsegetNextResult(mouse, cat, turns);return dp[mouse][cat][turns];}void getNextResult(int mouse, int cat, int turns) {int cur_move = turns % 2 == 0 ? mouse : cat;int default_result = cur_move == mouse ? CAT_WIN : MOUSE_WIN;int result = default_result;for (int index : graph[cur_move]) {if (cur_move == cat && index == 0)continue;int next_mouse = cur_move == mouse ? index : mouse;int next_cat = cur_move == cat ? index : cat;int next_result = getResult(next_mouse, next_cat, turns + 1);if (next_result != default_result) {result = next_result;if (result != DRAW)break;}}dp[mouse][cat][turns] = result;}
};

leetcode——【猫和老鼠】相关推荐

  1. leetcode 猫和老鼠

    #include<iostream> #include<vector> #include<math.h> using namespace std; int max( ...

  2. LeetCode 1185. 一周中的第几天 / 913. 猫和老鼠(博弈,动态规划) / 1576. 替换所有的问号

    1185. 一周中的第几天 2022.1.3 每日一题 题目描述 给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天. 输入为三个整数:day.month 和 year,分别表示日.月.年. ...

  3. LeetCode题解(1728):猫和老鼠II(Python)

    题目:原题链接(困难) 标签:动态规划 解法 时间复杂度 空间复杂度 执行用时 Ans 1 (Python) – – 520ms (96.20%) Ans 2 (Python) Ans 3 (Pyth ...

  4. [leetcode 913] 猫和老鼠(博弈、dp)

    题目链接: https://leetcode-cn.com/problems/cat-and-mouse/ 题目大意: 在一张无向图中,老鼠开始处于1号点,猫开始处于2号点,0号点是洞(猫不能进入), ...

  5. Leetcode每日一题总目录(动态更新。。。)

    0. 概要 leecode每日一题(也可能多题)题解跟踪记录及总目录. 常用算法解题思路和技巧及数据结构: 预处理:数组排序(954),哈希表... 双指针法 682,125,905 单向链表 2 双 ...

  6. leetcode 转载

    转载: https://blog.csdn.net/love905661433/article/details/84980135 LeetCode 1- 100 1. 两数之和 : https://b ...

  7. leetcode 分tag

    leetcode 分tag 数组问题(复杂度先时间再空间,/表示或者) 两数之和✔ O(n), O(n) 三数之和 ✔ 排序+双指针 (O(n2), O(logn)/O(n)) 四数之和✔ 排序+双指 ...

  8. leetcode 5. Longest Palindromic Substring 字符串中的最长回文数 逐步从O(n^2)优化至线性时间

    题目 解析 思路一 暴力解法 思路二 指针+最大长度 思路3 由中间至两边找回数 思路4 Manacher's algorithm 线性时间 参考文档 题目 链接 给定一个字符串 s,找到 s 中最长 ...

  9. LeetCode 10. Regular Expression Matching python特性、动态规划、递归

    前言 本文主要提供三种不同的解法,分别是利用python的特性.动态规划.递归方法解决这个问题 使用python正则属性 import reclass Solution2:# @return a bo ...

最新文章

  1. Java 8 实战 P4 Beyond Java 8
  2. SAP UI5 初学者教程之二十四 - 如何使用 OData 数据模型试读版
  3. python可以帮机器人编程吗_Python如何实现机器人聊天
  4. 前端学习(239):渐进增强和优雅降级
  5. Spring Boot -Shiro配置多Realm 1
  6. bzoj2878 [Noi2012]迷失游乐园——概率期望DP
  7. Reactor线程模型
  8. (转)策略回测的框架、实现、测试
  9. Swift3.0P1 语法指南——控制流
  10. MDF文件查看器(SQL MDF Viewer) 1.0 绿色版
  11. G29Prescan半实物仿真流程
  12. 【解决方案】智慧机场:基于视频智能融合平台EasyCVR让机场数字化转型高飞
  13. phper must-have
  14. 第6堂视频课:看到词句就会读-下
  15. 美丽的秋天秋天是多么美丽呀!
  16. 微信Windows客户端版本无法打开小程序问题的解决
  17. c#上位机开发(三)——简易串口发送数据
  18. 练习3-7 成绩转换(15 分)
  19. html地球转动效果,使用纯 CSS3 动画实现地球转动
  20. CDN加速,App与Big-man

热门文章

  1. 公司服务器架设邮箱服务器,如何搭建企业邮箱服务器
  2. 计算机三级网络技术知识点
  3. 前端 html,css 经典面试题 16道 (20220322)
  4. 谈谈你对 Spring 的理解
  5. OpenStack核心组件原理与应用之Keystone
  6. 关于Linux中批量配置SSH免密的一些笔记
  7. Oracle10g ora12170,ORA-3136、TNS-12535 12170 12606
  8. PEiD0.95 - 经典查壳工具
  9. Invalid bound statement (not found): com.xx.dao.TypeMapper.selectAll
  10. 苹果微信换行怎么打_微信空白朋友圈怎么发?安卓苹果双平台教程