1025除数博弈——力扣算法系列2020.07.24 Python

本文介绍了LeetCode中的一道算法题1025,讨论了爱丽丝和鲍勃的分数博弈。文章通过归纳法找出了当N为奇数时Alice必败,偶数时Alice必胜的规律,并进行了证明。此外,还提供了两种解题思路,一是通过归纳法直接得出结论,二是利用动态规划进行求解,详细解释了动态规划的状态定义和状态转移方程,并给出了代码实现。
摘要由CSDN通过智能技术生成

第30天
2020.07.24 周五
难度系数:简单
题目:爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字N。在每个玩家的回合,玩家需要执行以下操作:
1.选出任一x,满足0 < x < NN % x == 0
2.用N - x替换黑板上的数字N
如果玩家无法执行这些操作,就会输掉游戏。

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

示例 1:

输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:

输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

提示:1 <= N <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divisor-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
——————————我是分割线——————————
解法:
思路一:归纳法(找规律)
对于博弈类的问题嘛,先试着写几项,写着写着就会发现规律啦:
N=1的时候,区间(0,1) 中没有整数是N的因数,所以此时 Alice败。
N=2的时候,Alice只能拿1,N变成1,Bob 无法继续操作,故 Alice 胜。
N=3的时候,Alice 只能拿1,N变成2,根据N=2的结论,此时Bob会获胜,Alice败。
N=4的时候,Alice能拿1或2,如果Alice拿1,根据N = 3结论,Bob 会失败,Alice会获胜。
N=5的时候,Alice只能拿1,根据N=4的结论,Alice会失败。

我们发现这样一个现象:N为奇数的时候 Alice(先手)必败;N为偶数的时候 Alice 必胜。
这个猜想是否正确?下面我们来想办法证明它。

证明
N=1和N=2 时结论成立。

N>2时,假设N≤k时该结论成立,则N=k+1时:
1.如果k为偶数,则k+1为奇数,x是k+1的因数,只可能是奇数,而奇数减去奇数等于偶数,且k+1−x≤k,故轮到Bob时都是偶数。而根据我们的猜想假设N≤k的时候偶数的时候先手必胜,故此时无论Alice拿什么,Bob必胜,所以Alice败。
2.如果k为奇数,则k+1为偶数,x可以是奇数也可以是偶数,若Alice拿一个奇数,那么k+1−x是一个小于等于k的奇数,此时 Bob拿它,败,则Alice胜。
综上所述,这个猜想是正确的。

所以我们只需要判断N的奇偶即可(奇返回False,偶返回True)。
代码:

# 一 归纳法(找规律)
class Solution(object):
    def divisorGame(self, N):
        """
        :type N: int
        :rtype: bool
        """
        return N%2==0 #A拿奇数败,偶数胜 判断奇偶即可

在这里插入图片描述

——————————我是分割线——————————
思路二:动态规划
状态定义:dp[i]表示爱丽丝拿到数字i时是胜还是败。
边界条件:dp[1]=[False],爱丽丝拿到1则败。
状态转移方程:dp[i] = [False] if dp[i-1]==[True] else [True]。如果爱丽丝拿到上一个数字可胜,则这个数字一定败。
最后返回dp[N][0]即可。

代码:

# 二 动态规划
class Solution(object):
    def divisorGame(self, N):
        """
        :type N: int
        :rtype: bool
        """
        dp = [[False] for i in range(N+1)] #定义dp
        dp[1] = [False] #爱丽丝拿到1则输

        for i in range(2,N+1): #从2开始遍历到N
            #如果爱丽丝拿到上一个数字能赢则拿到这个数字会输,反之亦然
            dp[i] = [False] if dp[i-1]==[True] else [True] 
        return dp[N][0] #最后返回爱丽丝拿到数字N的输赢情况

N=1
print(Solution().divisorGame(N))
# 结果False

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值