LeetCode 292. Nim Game(博弈问题)

题目链接:点击这里
在这里插入图片描述

考察 n = 4 n=4 时:

  • 你取走 1 1 ,对手取走 3 3 ,对手赢
  • 你取走 2 2 ,对手取走 2 2 ,对手赢
  • 你取走 3 3 ,对手取走 1 1 ,对手赢
  • 所以 n = 4 n=4 是一种必输策略

初始状态:

  • f [ 0 ] f[0] 必输, f [ 1 ] f [ 2 ] f [ 3 ] f[1]、f[2]、f[3] 必胜
  • f [ 4 ] f[4] 必输, f [ 5 ] f [ 6 ] f [ 7 ] f[5]、f[6]、f[7] 必胜

所以,若存在一种 x   ( 1 x 3 ) x \ (1 \leq x \leq 3) ,使得 f [ n x ] f[n-x] 必输,那么 f [ n ] f[n] 则是必胜。不存在这种 x x 就是必输状态,就是怎么走别人都必胜。

到这里就可以循环打表了。

class Solution {
public:
    bool canWinNim(int n) {
        vector<bool> f(n+1, false);
        for(int i = 0; i < n ; i++) {
            if(!f[i]) {
                for(int j = 1; j <= 3; j++) {
                    f[i+j] = true;
                }
            }
        }
        return f[n];
    }
};

超时。我们再接着推。

由于每次取走的 1 3 1 \sim 3 ,记 b a s e = 3 base=3

  • f [ 0 ] f[0] 必输, f [ 1 ] f [ b a s e ] f[1] \sim f[base] 必胜
  • f [ b a s e + 1 ] f[base+1] 必输, f [ b a s e + 2 ] f [ 2 b a s e + 1 ] f[base+2] \sim f[2*base+1] 必胜
  • f [ k ( b a s e + 1 ) ] f[k*(base+1)] 必输, f [ k ( b a s e + 1 ) + p ] f[k*(base+1)+p] 必胜 ( 1 p b a s e ) (1 \leq p \leq base)

所以,

  • n % ( b a s e + 1 ) = = 0 n \% (base+1)==0 必输
  • n % ( b a s e + 1 ) < > 0 n\%(base+1)<>0 必胜,此时我们每次都取走余数,对方就变成了必输状态。

AC代码如下:

class Solution {
public:
    bool canWinNim(int n) {
        if(n%4==0)  return false;
        else    return true;
    }
};
发布了690 篇原创文章 · 获赞 103 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104062707
今日推荐