Leetcode:292. Nim Game

Leetcode题解

292.Nim Game-Easy

题目

You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.

Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.

For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.
中文简述:
你和你的朋友在玩游戏, 一共有一堆n个石头,每次你们分别能拿1/2/3个,你先手,假设你们两个都极其聪明选择最优策略,求给n个石头决定你是否能赢。

分析&解答

这一题,是一个非常明显的博弈论问题。Nim游戏就是这么一种游戏:它的每个状况的输赢情况,不由其上一手决定,而是由这个状况本身决定。
经过大致分析,我们能得到以下输赢情况:
1颗石头,先手胜
2颗石头,先手胜
3颗石头,先手胜
4颗石头,先手输
那么之后的情况,我们应该怎么分析?其实问题可以转化成一个非常简单的动态规划问题,设dx[i],dh[i]分别为i颗石头先手和后手的输赢情况,由于题目中先手赢==后手输的情况,即dx[i]==!dh[i],所以还可以把问题简化为只用先手输赢的状况表示即可。这里我们用d[i]表示先手的输赢情况。
首先通过分析5颗石头的状态来管中窥豹,由于你是先手,你拿了x颗石头,则情况变为你是后手的5-x颗石头的状态,所以对你来说最优策略就是找到一个后手5-x石头必赢的状态,x取值为1,2,3。
所以d[5]=dh[5-1] || dh[5-2] || dh[5-3]
因为dh[x] = !d[x], 式子可以改写成:
d[5] = !d[5-1]||!d[5-2]||!d[5-3]
同理,我们可以总结出了动态规划的转台转移式子:
d[i]=d[i-1]+d[i-2]+d[i-3] (布尔代数)
其实到这里,动态规划的代码基本可以打出来了。但是为了一个给定的n,我们要创建一个n大小的数组,当n很大时就无法解决。而且这么简单的状态转移式子,显然有着更加迷人的解答。
对,最后的答案就是 d[i] = (i%4==0)

class Solution {
public:
    bool canWinNim(int n) {
        return n%4==0;
    }
};

不难发现,先手的玩家总是能个优先选择拿的石头数目总是能使其达到一个后手必赢的状态,对于开始的石头4+1/2/3个时就是先手能拿掉对应的石头。而当石头数目是4的倍数时,则先手无论如何都打不到后手必赢的状态。

你可能感兴趣的:(Leetcode~)