lintcode 硬币排成线3

lintcode 硬币排成线3

描述

有 n 个硬币排成一条线,每一枚硬币有不同的价值。两个参赛者轮流从任意一边取一枚硬币,知道没有硬币为止。计算拿到的硬币总价值,价值最高的获胜。

请判定 第一个玩家 是输还是赢?

样例

给定数组 A = [3,2,2], 返回 true.

给定数组 A = [1,2,4], 返回 true.

给定数组 A = [1,20,4], 返回 false.

挑战

Follow Up Question:

If n is even. Is there any hacky algorithm that can decide whether first player will win or lose in O(1) memory and O(n) time?

思路

因为不确定从左边拿还是右边拿,所以设置一个二维数组dp[i][j]来表示从i到j这个区间,先手能比后手多拿的分数。
对于某一时刻的状态i,j,只有两个拿硬币的方法,一个是从左,一个是从右,选取其中的最大值,也就是
dp[i][j] = max(values[i]-dp[i+1][j], values[j]-dp[i][j-1])
对于初始状态,dp[i][i] = values[i],因为只有一个硬币。

代码

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<vector<int>> dp;
        dp.resize(n, vector<int>(n));
        
        for (int i = 0; i < n; i++)
            dp[i][i] = values[i];
            
        for (int i = n-2; i >= 0; i--)
            for (int j = i+1; j < n; j++)
                dp[i][j] = max(values[i] - dp[i+1][j], values[j]-dp[i][j-1]);
        
        return dp[0][n-1] > 0;
    }
};

follow up

如果n是一个偶数,是否可以在On的时间复杂度和O1的空间复杂度内判断出先手的胜负?

暂留

猜你喜欢

转载自blog.csdn.net/qq_40147449/article/details/87876091