OJ题目6--数字游戏问题

在OJ题目中经常会出现两个玩家分先后手玩数字游戏的问题,两个玩家会遵循相同的规则,题目还会特别注明,两个玩家在每一步上都会做最优解,事实上,看到这句话时,说明这道题一定是有规律可循的,而且规律往往相当简单(如果玩家不按套路出牌或者瞎玩的话,整个游戏过程也一定不可能用简单的程序模拟),当找到规律时,这一类问题也就被解决了。

1,292. Nim 游戏 - 力扣(LeetCode) (leetcode-cn.com)

这个游戏的规则是有一堆石子,我和另一个人玩,我先拿,另一个人后拿,每一次可以拿1,2,3个。假设每一个人在游戏时做的都是最优解,石子拿完之前最后一个拿石子的人获胜。

分析这道题,什么是最优解。由于一个人一次最多只能拿3个石子,当桌子上有4个石子时,我先拿,那么无论我拿多少个,总会给我的对手剩下一次能够拿完的石子数。当然,如果桌子上还有5个石子,那么我可以只拿一个,这样就留给对手必输的局面了,桌子上有6,7个石子时的情况也同理,我都可以按情况选择我所要拿走的石子数量,以留给对手4个石子的死局。但是,如果桌子上有8个,那么无论我怎么拿石子,对手都可以选择拿走石子的数量,留给我4个石子的死局。再往上,9,10,11,12也是同理。这就是我和对手都要遵循的“最优解”,即尽可能的将只剩4个石子的死局留给对手,为达到这样的目的,就要根据初始石子的总数,尽可能的保证在对手拿石子时桌子上有4的倍数个石子,这样无论对手怎样拿,我都可以让对手每次拿石子时桌子上有4的倍数个石子,这样一直保持到还剩4个石子,对手拿一回,剩下的我全拿走。因此,当游戏开始时,桌子上的石子不是4的倍数,那我只要严格遵循上面最优解的思路,那就一定会赢,但如果桌子上的石子数量是4的倍数的话,那我一定会输。

bool canWinNim(int n)
{
    if(n%4==0)
    {
        return false;
    }
    return true;
}

2,​​​​​​1025. 除数博弈 - 力扣(LeetCode) (leetcode-cn.com)

给定一个数字n,在1到n-1之间任选一个数字x,保证n%x==0并用n-x替换x。两个人反复玩,且都会做最优解,不能完成前面所说规则的玩家会输。分析本题,对于先手的玩家而言,当n=1时,不存在小于n且大于0的数字,因此先手败。n=2时,先手取1,到后手时,后手面对的是n=1的败局,后手败。n=3时,先手仍然只能选1,后手开始时n=2,根据前面,当玩家拿到n=2的局面时必赢(默认做最优解),此时先手败。n=4时,先手可以拿1或2,但是默认先手会做最优解,先手为了赢,一定会拿1,以留给后手n=3的必输局,此时后手败。n=5时,先手只能选1,这时留给后手n=4,当玩家拿到n=4时,根据前面所说,这时必胜局,此时先手剩。n=6时,情况更加复杂,先手可以选1,2,3,但是在默认玩家做最优解的时候,玩家应该合理选择以留给对手必败的局面,因此这时先手应该选择1或3,留给后手5或3的必败局。推演到这里,虽然后面的情况越来越复杂,但在默认两个玩家都会做最优解的前提下,再大的数在经过几次操作后,也可以变成前面已经有确定结局的n的情况,两个玩家哪怕是在未知的情况下也是尽可能的让处理后的n变成让对方进入死局的状态。因此可以有一个大致的猜想,当n为奇数时,先手败,n为偶数时,后手败。(或者说哪位玩家拿到了n=偶数的局面,在做最优解的前提下,哪位玩家就一定会赢)

下面利用数学归纳法证明:

假设从1到k的所有数都符合上面的结论。当k为奇数时(此时先手败),k+1为偶数,当先手选择时,至少可以选择1,2,那么做最优解的情况下先手一定会选择2,留给后手n=k-1,即n为偶数的必败局。当k为偶数时,k+1为奇数,这时对于先手而言,不可能取偶数,只能取奇数,如果取奇数的话,留给后手的会是n=奇数-奇数,即一个偶数,亦即后手获得了n=偶数的必胜局。综上可以得出结论,初始时,无论n的值为多少,只要n为奇数时,先手必败,n为偶数时,先手必胜。

bool divisorGame(int n)
{
    if(n%2==0)
    {
        return  true;
    }
    return false;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值