464. 我能赢吗 (Medium)
问题描述
在 "100 game" 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和
达到或超过 100 的玩家,即为胜者。
如果我们将游戏规则改为 “玩家 不能 重复使用整数” 呢?
例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。
给定两个整数 maxChoosableInteger (整数池中可选择的最大数)和
desiredTotal(累计和),若先出手的玩家能稳赢则返回 true ,否则返回 false
。假设两位玩家游戏时都表现 最佳 。
示例 1:
输入:maxChoosableInteger = 10, desiredTotal = 11
输出:false
解释:
无论第一个玩家选择哪个整数,他都会失败。
第一个玩家可以选择从 1 到 10 的整数。
如果第一个玩家选择 1,那么第二个玩家只能选择从 2 到 10 的整数。
第二个玩家可以通过选择整数 10(那么累积和为 11 >= desiredTotal),从而取得胜利.
同样地,第一个玩家选择任意其他整数,第二个玩家都会赢。
示例 2:
输入:maxChoosableInteger = 10, desiredTotal = 0
输出:true
示例 3:
输入:maxChoosableInteger = 10, desiredTotal = 1
输出:true
提示:
1 <= maxChoosableInteger <= 200 <= desiredTotal <= 300
解题思路
dfs
首先从递归的角度来思考,(事实上这里博弈的角度并没有那么强),第一个玩家选了x,那么对下一个玩家而言,他的desiredTotal就变成了desiredTotal - x,而如果下一个玩家赢了,那么第一个玩家就输了。
状态压缩 + 记忆化搜索
首先注意到,这个题中maxChoosableInteger <= 20,因此我们可以用一个最长不超过20位的二进制数mask来表示数的选择过程,如果mask的第i位为1,说明i还没有被选择过,即还能选;
同时我们可以注意到,desired_total的值直接由mask来决定,因为mask的初始值为2^n - 1,所以写cache数组的时候无需加上desired_total的维度;
注意位运算的优先级是很低的,建议加括号。
代码
class Solution {
public:
// 改写成位运算的形式
bool dfs(int desired_total, int cur_total, int bit20, int max_int, unordered_map<int, int> &ump) {
if (desired_total <= 0) {
return false;
}
if (bit20 == 0) {
return true;
}
if (ump.find(bit20) != ump.end()) {
return ump[bit20];
}
bool tmp = false;
int cnt = 1;
for (int i = max_int - 1; i >= 0; --i) {
if ((bit20 & (1 << i)) != 0) { // 说明数i + 1还没有被选
int mask = (bit20 ^ (1 << i));
tmp = tmp || (!dfs(desired_total - i - 1, cur_total + i + 1, mask, max_int, ump));
}
if (tmp) {
ump[bit20] = true;
return ump[bit20];
}
}
ump[bit20] = false;
return ump[bit20];
}
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= maxChoosableInteger) {
return true;
}
if ((maxChoosableInteger + 1) * maxChoosableInteger / 2 < desiredTotal)
return false;
unordered_map<int, int> ump;
int bit20 = (1 << maxChoosableInteger) - 1;
return dfs(desiredTotal, 0, bit20, maxChoosableInteger, ump);
}
};
464. 我能赢吗 (Medium)的更多相关文章
- Leetcode 464.我能赢吗
我能赢吗 在 "100 game" 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到 100 的玩家,即为胜者. 如果我们将游戏规则改为 ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- leetcode动态规划题目总结
Hello everyone, I am a Chinese noob programmer. I have practiced questions on leetcode.com for 2 yea ...
- C#LeetCode刷题-极小化极大
极小化极大篇 # 题名 刷题 通过率 难度 375 猜数字大小 II 23.4% 中等 464 我能赢吗 25.5% 中等 486 预测赢家 40.4% 中等 843 猜猜这个单词 2 ...
- C#LeetCode刷题-动态规划
动态规划篇 # 题名 刷题 通过率 难度 5 最长回文子串 22.4% 中等 10 正则表达式匹配 18.8% 困难 32 最长有效括号 23.3% 困难 44 通配符匹配 17.7% ...
- LeetCode刷题总结-动态规划篇
本文总结LeetCode上有动态规划的算法题,推荐刷题总数为54道.具体考点分析如下图: 1.中心扩展法 题号:132. 分割回文串 II,难度困难 2.背包问题 题号:140. 单词拆分 II,难度 ...
- [LeetCode] 464. Can I Win 我能赢吗
In the "100 game," two players take turns adding, to a running total, any integer from 1.. ...
- 464 Can I Win 我能赢吗
详见:https://leetcode.com/problems/can-i-win/description/ C++: class Solution { public: bool canIWin(i ...
- [leetcode] 464. Can I Win (Medium)
原题链接 两个人依次从1~maxNum中选取数字(不可重复选取同一个),累和.当一方选取数字累和后结果大于等于给定的目标数字,则此人胜利. 题目给一个maxNum和targetNum,要求判断先手能否 ...
- [LeetCode] Can I Win 我能赢吗
In the "100 game," two players take turns adding, to a running total, any integer from 1.. ...
随机推荐
- JavaScript:七大基础数据类型:数值number及其表示范围
数值number类型,用来表示任何类型的数字:整数或者浮点数都可以: 实际上,JS中的数值,是一个64位的浮点数,这与Java中的double类型的浮点数是一致的: 但是它有表示的范围,在范围内,JS ...
- 回顾Vue计算属性VS其他语法有感
回顾Vue计算属性VS其他语法有感 重新回顾官方教程中的到计算属性和侦听器,发觉获益良多,主要就是两点: 计算属性和其他语法的比较 计算属性.侦听属性.方法.模板变量的使用 计算属性和其他语法的比较 ...
- 5、基于EasyExcel的导入导出
一.Apach POI处理Excel的方式: 传统Excel操作或者解析都是利用Apach POI进行操作,POI中处理Excel有以下几种方式: 1.HSSFWorkbook: HSSFWorkbo ...
- 小H的小屋
题解 [NOI2004]小H的小屋 前记 又鸽了好久,这回可要努力更新了 2019.6.2,痛下杀心,把电脑上所有的游戏都删掉了,提前160天奋力备考NOIP.目标:A类省队! 我是传送门 题解 这道 ...
- 基于 VScode 搭建 STM32 运行环境
所需软件 vscode: 是我们的代码编辑器 STM32CubeMX: 是我们配置和初始化的软件 OpenOCD: 是开源片上调试器, 他下载完是一个压缩包, 需要配置环境 arm-none-eabi ...
- Three.js 进阶之旅:新春特典-Rabbit craft go 🐇
声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 摘要 兔年到了,祝大家身体健,康万事顺利.本文内容作为兔年新春纪念页面,将使用 ...
- 腾讯出品小程序自动化测试框架【Minium】系列(二)项目配置及测试套件使用说明
一.写在前面 真的人这一散漫惯了,收心就很难了,上午把小程序开发环境启动后,在QQ游戏里,杀了三把象棋,5把2D桌球,一上午没了,还是没法心静下来去学点东西. 那就老样子,逼着自己开始,找到 &quo ...
- npm 中设置环境NODE_ENV变量,判断失败打印process.env.NODE_ENV确实是"development",但是判断process.env.NODE_ENV === "development" 是false
通过package.json 的scripts脚本 修改NODE_ENV的值来区分开发环境和生产环境. "scripts": { "build": " ...
- Linux音频采集和在国产化平台中遇到的坑(一)
Linux音频采集和在国产化平台中遇到的坑(一) 最近在做一个国产化平台的软件项目的开发,是基于国产芯片的银河麒麟系统.其中有一个重要模块,是采集和播放音频数据,播放不用多说了,采集的话,包括采集麦克 ...
- 在Spring Boot中整合Katharsis,来快速开发JSON API的Web应用
1 简介 我们进行Web API开发的时候,经常会使用Json格式的消息体,而Json格式非常灵活,不同的人会有不同的设计风格和实现,而JSON API提供了一套标准.但它并不提供直接实现. Kath ...