前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >我能赢吗

我能赢吗

作者头像
你的益达
发布于 2020-08-17 01:44:11
发布于 2020-08-17 01:44:11
88200
代码可运行
举报
运行总次数:0
代码可运行

问题描述:

在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到 100 的玩家,即为胜者。

如果我们将游戏规则改为 “玩家不能重复使用整数” 呢?

例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。

给定一个整数 maxChoosableInteger (整数池中可选择的最大数)和另一个整数 desiredTotal(累计和),判断先出手的玩家是否能稳赢(假设两位玩家游戏时都表现最佳)?

你可以假设 maxChoosableInteger 不会大于 20, desiredTotal 不会大于 300。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
示例:

输入:
maxChoosableInteger = 10
desiredTotal = 11

输出:
false

解释:
无论第一个玩家选择哪个整数,他都会失败。
第一个玩家可以选择从 110 的整数。
如果第一个玩家选择 1,那么第二个玩家只能选择从 210 的整数。
第二个玩家可以通过选择整数 10(那么累积和为 11 >= desiredTotal),从而取得胜利.
同样地,第一个玩家选择任意其他整数,第二个玩家都会赢。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/can-i-win
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解决方案:

对于博弈类问题,一般做法都是定于fun()为先手能否获胜。fun计算过程中,枚举出先手方的所有可能,如果存在后手方不能获胜,则此时先手方采取该决策即可获胜,若对于先手方的所有选择后手方均可获胜,则此时先手方不能获胜返回false。

对于该问题,由于题目要求不放回的拿元素,因此需定义一布尔型的visted数组用于存储该元素是否被拿。其dfs实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    int total = 0;
    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        this.total = desiredTotal;
        boolean[] visted = new boolean[maxChoosableInteger + 1];
        return step(visted, 0);
    }
    // sum 为当前的和
    public boolean step(boolean[] visted, int sum){
        for(int i = visted.length - 1; i > 0; i--){
            if(visted[i]){
                continue;
            }
            if(sum + i >= total){
                return true;
            }
            visted[i] = true;
            if(!step(visted, sum + i)){
                visted[i] = false;
                return true;
            }
            visted[i] = false;
        }
        return false;

    }
}

上述解法的时间复杂度为O(n!),其中n为能拿元素的最大值。

由于该过程转移顺序不能确定,因此采用dfs + 记忆集的方式求解。

由于此时的状态为一布尔型的数组,难以存储,因此使用状态压缩的方式,由于题目说道maxChoosableInteger 总是小于20的,因此可以使用一整型变量status,当前位为0表示可用,为1表示不可用。由于是从1开始的,因此i值在status中对应的是i - 1位。由于通过status可以唯一的确定状态,因此不需要加入sum(其实可以通过status得出此时的sum)。

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    int total = 0;
    int maxInte = 0;
    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        if(maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal){
            return false;
        }
        this.total = desiredTotal;
        this.maxInte = maxChoosableInteger;
        int status = 0; // 当前位为0表示未取 1表示已取
        Map<Integer, Boolean> map = new HashMap<>();
        return step(status, map, 0);
    }
    public boolean step(int status, Map<Integer, Boolean> map, int sum){
        if(map.containsKey(status)){
            return map.get(status);
        }
        boolean ans = false;
        for(int i = 0; i < maxInte; i++){
            if((status >> i & 1) == 1){
                continue;
            }

            if(sum + i + 1 >= total){
                ans = true;
                break;
            }
            if(!step(status | (1 << i), map, sum + i + 1)){
                ans = true;
                break;
            }
        }
        map.put(status, ans);
        return ans;   
    }
}

其时间复杂度降为O(2^N)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
golang刷leetcode:我能赢吗
在 "100 game" 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和 达到或超过 100 的玩家,即为胜者。
golangLeetcode
2022/08/02
1950
leetcode第30场双周赛
Day 是集合 {“1st”, “2nd”, “3rd”, “4th”, …, “30th”, “31st”} 中的一个元素。 Month 是集合 {“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, “Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”} 中的一个元素。 Year 的范围在 [1900, 2100] 之间。 请你将字符串转变为 YYYY-MM-DD 的格式,其中:
你的益达
2020/08/05
5090
​LeetCode刷题实战464:我能赢吗
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/12/15
3070
博弈专题入门总结(Nim 巴什 SG等证明+例题)
一堆n个物品,两个人轮流从这堆物品中取物, 规定每次取[1,m]个,最后取光者得胜,问先手必胜还是后手必胜。
Here_SDUT
2022/06/29
2.1K0
博弈专题入门总结(Nim 巴什 SG等证明+例题)
LeetCode 464. 我能赢吗(状态压缩+记忆化递归 / 博弈)
在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到或超过 100 的玩家,即为胜者。
Michael阿明
2021/02/19
7750
除数博弈
选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。 如果玩家无法执行这些操作,就会输掉游戏。
你的益达
2020/08/05
5860
程序员进阶之算法练习(六十三)
按照上面的规则,迭代k次之后,得到a[k]; 现在给出a[1]和k,求最终迭代出来的a[k]值是多少?
落影
2022/09/02
2470
程序员进阶之算法练习(六十三)
运用「博弈论」分析「先手必胜态」序列具有何种性质,以及如何思考「博弈论」问题
Alice 和 Bob 轮流从黑板上擦掉一个数字,Alice 先手。如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0 的话,当前玩家游戏失败。 (另外,如果只剩一个数字,按位异或运算得到它本身;如果无数字剩余,按位异或运算结果为 0。)
宫水三叶的刷题日记
2023/01/03
4870
程序员进阶之算法练习(十三)
前言 比赛就在这周末,这篇是比赛前最后一篇训练总结。 正文 hdu 5980(简单题) 题目大意 一个32位的数字,每个bytes包括8bit,所以一个整数是由4bytes组成; 现给出n个数字,问组成数字的bytes中,有多少个'a'。 Sample Input 3 97 24929 100 Sample Output 3 题目解析 对于每个数字,用0x000000ff进行与操作,取出最后8位,然后与'a'判断,然后右移8位,知道数字为0即可; hdu 5978(简单题) 题目大意
落影
2018/04/27
5840
[LeetCode]动态规划求解博弈问题
博弈论是有趣又有用的知识,可以用来预测在特定的规则下,人们会做出怎样的行为,又会导致怎样的结果。利用博弈论来指导人们的行事法则甚至商业操作,比如著名的囚徒困境就被很好的利用在了商业竞争上。同样,LeetCode也利用博弈论出了几道有意思的题目。
用户6557940
2022/07/24
6110
[LeetCode]动态规划求解博弈问题
公平组合游戏-巴什游戏、尼姆游戏和SG函数
公平组合游戏(Impartral Combinatorial Game)是满足以下特征的一类问题:
唔仄lo咚锵
2020/10/09
1.5K0
公平组合游戏-巴什游戏、尼姆游戏和SG函数
【面试高频题】难度 3/5,既是经典区间 DP,也是经典博弈论
亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。
宫水三叶的刷题日记
2021/11/15
7160
数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」
在不和小B商量的情况下,作为小A的你是选择招供坐牢5年或0年,还是会选择抵赖坐牢10年或1年呢?
全栈程序员站长
2022/11/04
7.8K0
数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题「建议收藏」
一天一大 lee(预测赢家)难度:中等-Day20200901
给定一个表示分数的非负整数数组。玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。
前端小书童
2020/09/24
3340
一天一大 lee(预测赢家)难度:中等-Day20200901
CCF考试——201609-3炉石传说
  《炉石传说:魔兽英雄传》(Hearthstone: Heroes of Warcraft,简称炉石传说)是暴雪娱乐开发的一款集换式卡牌游戏(如下图所示)。游戏在一个战斗棋盘上进行,由两名玩家轮流进行操作,本题所使用的炉石传说游戏的简化规则如下:
AI那点小事
2020/04/20
4920
CCF考试——201609-3炉石传说
leetcode464. Can I Win
In the "100 game," two players take turns adding, to a running total, any integer from 1..10. The player who first causes the running total to reach or exceed 100 wins.
眯眯眼的猫头鹰
2020/05/11
3120
招商银行校招题二
题目描述 考虑你从家出发步行去往一处目的地,该目的地恰好离你整数单位步长(大于等于1)。你只能朝向该目的地或者背向该目的地行走,而你行走的必须为单位步长的整数倍,且要求你第N次行走必须走N步。 请就给出目的地离你距离,判断你是否可以在有限步内到达该目的地。如果可以到达的话,请计算到达目的地的最短总步数(不能到达则输出-1)。 输入描述: 1个整数:目的地离你距离T 输出描述: 1个整数:最短总步数(进行了多少次行走)
Tim在路上
2020/08/04
4900
脚撕LeetCode(877)Medium
题目地址:https://leetcode-cn.com/problems/stone-game/
JathonKatu
2021/07/14
2560
博弈论基础_博弈论基础罗伯特
博弈论这个环节特别好玩,游戏嘛(不会的话做题就不好玩了,当年打比赛比赛结束后两三分钟才推出来,一看答案想撕草稿纸)
全栈程序员站长
2022/11/03
6810
博弈论基础_博弈论基础罗伯特
【计算机本科补全计划】CCF计算机职业资格认证 2016-09-03(炉石传说)详解
正文之前 这是2016年九月份的CCF考试的第三题,按照高分标准来算,应该是在30min内解决??然而。我昨晚花了10mins看完了题目,今天上午有限元课的时候想数据结构,想流程花了我1h 然后,计算
用户1687088
2018/05/07
9200
【计算机本科补全计划】CCF计算机职业资格认证 2016-09-03(炉石传说)详解
推荐阅读
相关推荐
golang刷leetcode:我能赢吗
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档