292:Nim游戏

问题描述

你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。

示例

输入: 4
输出: false 
解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
     因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。

思路

这题一开始蒙圈了。后来发现这是个dp问题。即,状态转移方程为dp[i] = dp[i-3]&&dp[i-2]&&dp[i-1]。为啥呢?设想一下。你可以拿1块,拿两块,拿三块。当你拿走一块的时候,你朋友就要拿dp[i-1],你拿走两块你朋友就要拿dp[i-2],你拿走三块你朋友就要拿dp[i-3]. 所以说你能不能赢要看你拿走之后你朋友能不能赢。
想清楚这点之后,我就开始用dp写(方法一)。结果TLE了。我日???O(n)的dp你给我TLE?
看来有更简单的办法。多写了几项看了看:
如果前面的3个都是true,那么dp[i]肯定是false.
如果前面3个有false,那么dp[i]肯定就是true.
好像发现了什么:
1,2,3赢了。
4,输了
5,赢了
6,赢了
7,赢了
8,输了

好像是4个一组的。如果n%4之后等于0,则输了。否则就是赢了。(方法二)

方法一

Java版

public boolean canWinNim1(int n) {
        if(n < 4){
            return true;
        }
        boolean[] res = new boolean[n+1];
        res[1] = true;
        res[2] = true;
        res[3] = true;
        for(int i = 4; i <= n; i++){
            boolean win = false;
            for(int j = 1; j <= 3; j++){
                if(!res[i-j]){
                    win = true;
                    break;
                }
            }
            res[i] = win;
        }
        return res[n];
    }

方法二

Java版

class Solution {
    public boolean canWinNim(int n){
        return n%4 > 0;
    }
}
发布了396 篇原创文章 · 获赞 22 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_41687289/article/details/104889197
今日推荐