• lintcode 394. Coins in a Line 、leetcode 292. Nim Game 、lintcode 395. Coins in a Line II


    变型:如果是最后拿走所有石子那个人输,则f[0] = true

    394. Coins in a Line

    dp[n]表示n个石子,先手的人,是必胜还是必输。拿1个石子,2个石子之后都是必胜,则当前必败;拿1个石子,2个石子之后都是必败,则当前必胜;如果拿1个石子,2个石子之后有必败,则当前必胜。

    class Solution {
    public:
        /**
         * @param n: An integer
         * @return: A boolean which equals to true if the first player will win
         */
        bool firstWillWin(int n) {
            // write your code here
            if(n == 0)
                return false;
            if(n == 1)
                return true;
            vector<int> dp(n+1);
            dp[0] = false,dp[1] = true;
            for(int i = 2;i <= n;i++){
                if(dp[i-1] == true && dp[i-2] == true)
                    dp[i] = false;
                else if(dp[i-1] == false && dp[i-2] == false)
                    dp[i] = true;
                else
                    dp[i] = dp[i-1] || dp[i-2];
            }
            return dp[n];
        }
    };

    292. Nim Game

    这个题几乎与Coins in a Line一模一样。

    解法一:

    这个解法超内存了

    class Solution {
    public:
        bool canWinNim(int n) {
            if(n == 0)
                return false;
            if(n == 1 || n == 2)
                return true;
            vector<int> dp(n+1);
            dp[0] = false,dp[1] = true,dp[2] = true;
            for(int i = 3;i <= n;i++){
                if(dp[i-1] == true && dp[i-2] == true && dp[i-3] == true)
                    dp[i] = false;
                else if(dp[i-1] == false && dp[i-2] == false && dp[i-3] == false)
                    dp[i] = true;
                else
                    dp[i] = true;
            }
            return dp[n];
        }
    };

    解法二:

    因为只与前3个有关系,所以用变量替代,能不超内存,但超时了

    class Solution {
    public:
        bool canWinNim(int n) {
            if(n == 0)
                return false;
            if(n == 1 || n == 2)
                return true;
            bool num1 = false,num2 = true,num3 = true;
            for(int i = 3;i <= n;i++){
                bool tmp;
                if(num1 == true && num2 == true && num3 == true){
                    tmp = false;
                }
                else
                    tmp = true;
                num1 = num2;
                num2 = num3;
                num3 = tmp;
            }
            return num3;
        }
    };

    解法三:

    class Solution {
    public:
        bool canWinNim(int n) {
            return n%4 ? true : false;
        }
    };

    395. Coins in a Line II

    https://www.cnblogs.com/grandyang/p/5864323.html

    与Coins in a Line相同的是,这个题每次也只能拿一个或者两个。不同的是,最终的胜负是谁拥有的金币的价值更多。

    dp[i]表示从i到end可取的最大钱数

    如果取一个,dp[i] = values[i] + min(dp[i+2],dp[i+3])

    如果取两个,dp[i] = values[i] + values[i+1] + min(dp[i+3],dp[i+4])

    所以最终的递归就是dp[i] = max(values[i] + min(dp[i+2], dp[i+3]), values[i] + values[i + 1] + min(dp[i+3], dp[i+4]))

    代码实际上是可以解决n = 1和n = 2的情况,只是因为n-2,n-3这种会造成越界的错误。

    class Solution {
    public:
        /**
         * @param values: a vector of integers
         * @return: a boolean which equals to true if the first player will win
         */
        bool firstWillWin(vector<int> &values) {
            // write your code here
            int n = values.size();
            if(n <= 2)
                return true;
            vector<int> dp(n+1,0);
            dp[n-1] = values[n-1];
            dp[n-2] = values[n-2] + values[n-1];
            dp[n-3] = values[n-3] + values[n-2];
            for(int i = n - 4;i >= 0;i--)
                dp[i] = max(values[i] + min(dp[i+2],dp[i+3]),values[i] + values[i+1] + min(dp[i+3],dp[i+4]));
            int sum = 0;
            for(int i = 0;i < n;i++)
                sum += values[i];
            return dp[0] > sum - dp[0];
        }
    };
  • 相关阅读:
    optparse--强大的命令行参数处理包
    B/S和C/S架构的区别
    Document
    Document
    Document
    Document
    Document
    Document
    Document
    Document
  • 原文地址:https://www.cnblogs.com/ymjyqsx/p/10827210.html
Copyright © 2020-2023  润新知