除数博弈

本文介绍了LeetCode中一道关于动态规划的题目——除数博弈,讨论了解决思路,包括状态转移的表达式修正以及使用双指针法的代码实现,重点在于分析游戏规则和确定Alice获胜条件。
摘要由CSDN通过智能技术生成

 1. 题目

这道题是Leetcode中动态规划类型的一道题,题目难度为简单。

题目链接:除数博弈

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 n 。在每个玩家的回合,玩家需要执行以下操作:

  • 选出任一 x,满足 0 < x < n 且 n % x == 0 。
  • 用 n - x 替换黑板上的数字 n 。

如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回 true 。假设两个玩家都以最佳状态参与游戏。

2.思路

由于我们是为了训练动态规划的解题思路,因此我们不考虑其它的方法。在这道题中,如果数字为1的话,它没有任何操作,因此Alice必定输。

dp数组初始化

那么我们可以定义一个dp数组,并初始化数组元素为[0,0],这里定义两个是因为游戏是从1开始,为了方便下标计算才定义两个。

状态转移表达式

接着,我们需要找到它们的状态转移表达式,假设a + b = c,如果dp[a]和dp[b]都为1,那么我们不妨大胆猜测dp[c]=1。为啥呢?因为如果alice对于a和b都能赢,那么对于c,他可以分两步来减数。

那么我们初步的状态表达式为:

dp[i] = dp[i-a] & dp[a]

那还有其它的情况吗?有,对于动态规划的题目来说,前面几个数是最特殊的,对于数字1和2,我们可以很容易发现我们前面的状态转移有问题,因为2 = 1 + 1,而dp[1]=0,那么dp[2]如果根据前面的表达式就是有问题的。对于这个情况,我们猜测:如果a + b = c,同时dp[a]和dp[b]相等,那么dp[c]就为1。这个猜测是包含前面的表达式,同时也包含刚才的特殊情况。

因此改正的状态表达式为:

dp[i] = ! dp[i-a] ^ dp[a]

代码实现

有了刚才的状态表达式,那我们用代码如何实现呢?我们该如何考虑多种情况呢?因为一个数不止两个加数(想了好久才想到,大学白读了),因此我们需要用双指针来寻找这些子状态,然后进行判断,如果存在子状态符合上述情况则当前dp[i]为1。

3.代码

class Solution:
    def divisorGame(self, n: int) -> bool:
        dp = [0,0]
        for i in range(2,n+1):
            left,right = 1,i-1
            isT = False
            while left <= right:
                if dp[left] ^ dp[right] == 0:
                    dp.append(1)
                    isT = True
                    break
                left += 1
                right -= 1
            if not isT:
                dp.append(0)
        return dp[-1] == 1
                
            
            
                    

            
                

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小人物₍˄·͈༝·͈˄*₎◞ ̑̑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值