292. Nim Game

来源:互联网 发布:linux启动ftp服务 编辑:程序博客网 时间:2024/06/05 11:46

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.

s思路:
1. 本来看着是dp,如下图:在每个位置是否赢就是看前三个位置是否有输的情况,如有有,则这个位置就赢,否则就输,这么把所有情况列出来,发现信息量很小,不用dp都可以,因为结果很规则,就是逢4就输,其他时候则赢!

index 0 1 2 3 4 5 6 7 8 9 10 11 12 count 0 1 1 1 0 1 1 1 0 1 1 1 0

2. 为啥是dp?再不厌其烦的给自己掰扯掰扯。因为每次就remove一个到3个之间,选项很有限,也就是说问题的边界很明朗,然后是否赢就看去掉(1~3个)后,对方如果有输的情况,可以看出来,没操作一次,就进入一个新的层次,所以适合迭代/recursive。也就是说,从程序上来说,操作一次,就进入一个新的level,因此特别适合迭代/recursive,迭代到最后必然看到元问题,也就是问题的最边界,即:只剩1~3个的时候。也就是说,这个问题还是一个recursive。
3. 但又不能用recursive的方法来做,因为直接recursive的话,会有大量重复计算,比如上文:看n=12是否赢,要看n=11,n=10,n=9的情况,而n=11呢,又要看n=10,n=9,n=8的情况。看见没有,n=10,n=9就需要计算两次,所以如果非要用recursive的话,那也是top-down+memorization的方法。而top-down+memorization本质上就是bottom-up的dp。
4. 通过这么一分析,发现dp和recursive/iterative本质是一回事,但又不是简单的一回事,是当recursive/itrative有重复运算时的一种优化方法。或者说是从数学角度来弥补recursive/itrative的缺陷,从而避免重复计算!大妙!为啥说是数学角度?因为dp都需要有递推公式,这个递推公式起始就是数学咯!

class Solution {public:    bool canWinNim(int n) {        //        return n%4;    }};
0 0
原创粉丝点击