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

我能赢吗

作者头像
你的益达
发布于 2020-08-17 01:44:11
发布于 2020-08-17 01:44:11
90100
代码可运行
举报
运行总次数: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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
​LeetCode刷题实战464:我能赢吗
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/12/15
3080
程序员进阶之算法练习(十三)
前言 比赛就在这周末,这篇是比赛前最后一篇训练总结。 正文 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
5850
2022-05-03:Alice 和 Bob 再次设计了一款新的石子游戏。
2022-05-03:Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stonesi 是第 i 个石子的价值。
福大大架构师每日一题
2022/05/03
3080
图解LeetCode——1145. 二叉树着色游戏(难道:中等)
有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中,给出二叉树的根节点 root,树上总共有 n 个节点,且 n 为奇数,其中每个节点上的值从 1 到 n 各不相同。 最开始时:
爪哇缪斯
2023/05/10
1400
图解LeetCode——1145. 二叉树着色游戏(难道:中等)
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
5100
程序员进阶之算法练习(六十三)
按照上面的规则,迭代k次之后,得到a[k]; 现在给出a[1]和k,求最终迭代出来的a[k]值是多少?
落影
2022/09/02
2490
程序员进阶之算法练习(六十三)
运用「博弈论」分析「先手必胜态」序列具有何种性质,以及如何思考「博弈论」问题
Alice 和 Bob 轮流从黑板上擦掉一个数字,Alice 先手。如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0 的话,当前玩家游戏失败。 (另外,如果只剩一个数字,按位异或运算得到它本身;如果无数字剩余,按位异或运算结果为 0。)
宫水三叶的刷题日记
2023/01/03
4880
洛谷P3235 [HNOI2014]江南乐(Multi-SG)
题目描述 小A是一个名副其实的狂热的回合制游戏玩家。在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏。 游戏的规则是这样的,首先给定一个数F,然后游戏系统会产生T组游戏。每一组游戏包含N堆石子,小A和他的对手轮流操作。每次操作时,操作者先选定一个不小于2的正整数M (M是操作者自行选定的,而且每次操作时可不一样),然后将任意一堆数量不小于F的石子分成M堆,并且满足这M堆石子中石子数最多的一堆至多比石子数最少的一堆多1(即分的尽量平均,事实上按照这样的分石子万法,
attack
2018/04/10
8560
LeetCode 464. 我能赢吗(状态压缩+记忆化递归 / 博弈)
在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到或超过 100 的玩家,即为胜者。
Michael阿明
2021/02/19
7780
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
3130
博弈专题入门总结(Nim 巴什 SG等证明+例题)
一堆n个物品,两个人轮流从这堆物品中取物, 规定每次取[1,m]个,最后取光者得胜,问先手必胜还是后手必胜。
Here_SDUT
2022/06/29
2.1K0
博弈专题入门总结(Nim 巴什 SG等证明+例题)
一天一大 lee(预测赢家)难度:中等-Day20200901
给定一个表示分数的非负整数数组。玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。
前端小书童
2020/09/24
3340
一天一大 lee(预测赢家)难度:中等-Day20200901
脚撕LeetCode(877)Medium
题目地址:https://leetcode-cn.com/problems/stone-game/
JathonKatu
2021/07/14
2560
除数博弈
选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。 如果玩家无法执行这些操作,就会输掉游戏。
你的益达
2020/08/05
5870
招商银行校招题二
题目描述 考虑你从家出发步行去往一处目的地,该目的地恰好离你整数单位步长(大于等于1)。你只能朝向该目的地或者背向该目的地行走,而你行走的必须为单位步长的整数倍,且要求你第N次行走必须走N步。 请就给出目的地离你距离,判断你是否可以在有限步内到达该目的地。如果可以到达的话,请计算到达目的地的最短总步数(不能到达则输出-1)。 输入描述: 1个整数:目的地离你距离T 输出描述: 1个整数:最短总步数(进行了多少次行走)
Tim在路上
2020/08/04
4930
原创 | codeforces 1451D,一道有趣的博弈论问题
今天选择的问题是Contest 1451场的D题,这是一道有趣简单的伪博弈论问题,全场通过的人有3203人。难度不太高,依旧以思维为主,坑不多,非常友好。
TechFlow-承志
2020/12/08
4340
原创 | codeforces 1451D,一道有趣的博弈论问题
【计算机本科补全计划】CCF计算机职业资格认证 2016-09-03(炉石传说)详解
正文之前 这是2016年九月份的CCF考试的第三题,按照高分标准来算,应该是在30min内解决??然而。我昨晚花了10mins看完了题目,今天上午有限元课的时候想数据结构,想流程花了我1h 然后,计算
用户1687088
2018/05/07
9220
【计算机本科补全计划】CCF计算机职业资格认证 2016-09-03(炉石传说)详解
【LeetCode每日一题】810. 黑板异或游戏
黑板上写着一个非负整数数组 nums[i] 。Alice 和 Bob 轮流从黑板上擦掉一个数字,Alice 先手。如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0 的话,当前玩家游戏失败。 (另外,如果只剩一个数字,按位异或运算得到它本身;如果无数字剩余,按位异或运算结果为 0。)
公众号guangcity
2021/05/31
3470
第十届蓝桥杯决赛JavaC组真题——详细答案对照(完整版)
请你找到最小的整数 X 同时满足: X 是 2019 的整倍数 X 的每一位数字都是奇数
红目香薰
2022/11/29
4670
第十届蓝桥杯决赛JavaC组真题——详细答案对照(完整版)
相关推荐
​LeetCode刷题实战464:我能赢吗
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档