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 <= 20
0 <= 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.. ...
随机推荐
- 从一道CTF题学习python字节码到源码逆向
概述: 该题来源为2022爱春秋冬季赛ezpython,难度不是很大刚好适合我这样的萌新入门 题目: 3 0 LOAD_CONST 1 (204) 3 LOAD_CONST 2 (141) 6 LOA ...
- .Net 7 的AOT的程序比托管代码更容易破解?
楔子 .Net 7的一个重要功能是把托管的源码编译成Native Code,也就是二进制文件.此举看似增加了程序反编译难度,实际上是减少了程序的破解难度.本篇在不触及整个程序架构的前提下,以简单的例子 ...
- 2022USACO-DEC-Silver
题目链接 T1.Barn Tree T2.Circular Barn T3.Range Reconstruction T1 下面均以\(1\)为根来进行分析. 算法思路: 首先,定义一个数组dis表示 ...
- spark任务报错java.io.IOException: Failed to send RPC xxxxxx to xxxx:xxx, but got no response. Marking as slave lost.
## 日志信息如下 ``` Attempted to get executor loss reason for executor id 17 at RPC address 192.168.48.172 ...
- 前端 - JaveScrip
今日内容 JS简介 全程JaveScript但是与Jave没有关系 知识为了蹭Jave热度 它是一门前端工程师的编程语言 但是它本身有很多逻辑错误 IT行业鄙视链:前端.运维.测试.产品 前端想一统天 ...
- 最新版 Proteus 8.15 Professional 图文安装教程 [ 附安装包 ]
前言 Proteus 是世界上唯一将电路仿真软件.PCB设计软件和虚拟模型仿真软件三合一的设计平台. Proteus 8.15 现已发布,本篇将带领大家安装此版本. 介绍 Proteus Proteu ...
- 解决angular11+zorro使用table组件排序失效以及分页组件失效问题,附完整DEMO代码
关于这个排序失效问题的核心点,跟这个有关系:[nzFrontPagination]="false" 关于分页组件失效的问题,是你获取数据以后,需要给页码,页数,总条数都要重新赋值, ...
- DQL_排序查询-DQL_聚合函数
DQL_排序查询 排序查询 语法: order by 子句 order by 排序字段1 排序方式1 , 排序字段2 排序方式2 , 排序字段3 排序方式3 ..... 排序方式 : A ...
- 异常处理的第二种方式-Throwable类中3个异常处理的方式
异常处理的第二种方式 如果异常出现的话,会立刻终止程序,所以我们得处理异常: 1.该方法不处理,而是声明抛出,由该方法的调用者来处理(throws). 2.在方法中使用try-catch的语句块来处理 ...
- 微信公众号签名错误(invalid signature)的问题排查
之前写好的代码,好多项目一直在用没啥问题,今天做新项目,在调用的时候,wx.config提示签名错误(invalid signature),这搞得相当郁闷,没办法,只能重新一点一点调试. 按照官方的说 ...