1. 程式人生 > 資訊 >成本激增,今年亞馬遜 Prime Day 促銷可能有點“摳”

成本激增,今年亞馬遜 Prime Day 促銷可能有點“摳”

定義二維陣列 \(\textit{dp}\),其行數和列數都等於陣列的長度,$\textit{dp}[i][j] $表示當陣列剩下的部分為下標 \(i\) 到下標 \(j\) 時,即在下標範圍 \([i, j]\) 中,當前玩家與另一個玩家的分數之差的最大值,注意當前玩家不一定是先手。

只有當 \(i \le j\) 時,陣列剩下的部分才有意義,因此當 \(i>j\) 時,\(\textit{dp}[i][j]=0\)

\(i=j\) 時,只剩一個數字,當前玩家只能拿取這個數字,因此對於所有 \(0 \le i < \textit{nums}.\text{length}\),都有 \(\textit{dp}[i][i]=\textit{nums}[i]\)

\(i<j\) 時,當前玩家可以選擇 \(\textit{nums}[i]\)\(\textit{nums}[j]\),然後輪到另一個玩家在陣列剩下的部分選取數字。在兩種方案中,當前玩家會選擇最優的方案,使得自己的分數最大化。因此可以得到如下狀態轉移方程:

\[\textit{dp}[i][j]=\max(\textit{nums}[i] - \textit{dp}[i + 1][j], \textit{nums}[j] - \textit{dp}[i][j - 1]) \]

最後判斷 \(\textit{dp}[0][\textit{nums}.\text{length}-1]\)

的值,如果大於或等於 \(0\),則先手得分大於或等於後手得分,因此先手成為贏家,否則後手成為贏家。

class Solution {
public:
    bool PredictTheWinner(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> f(n + 1, vector<int>(n));

        for(int i = n - 1; i >= 0; i--)
            for(int j = i; j < n; j++)
                if(i == j) f[i][j] = nums[i];
                else f[i][j] = max(nums[i] - f[i + 1][j], nums[j] - f[i][j - 1]);
        
        return f[0][n - 1] >= 0;
    }
};