leetcode486. 預測贏家/877. 石子游戲(區間dp)
連結:https://leetcode-cn.com/problems/predict-the-winner/
連結:https://leetcode-cn.com/problems/stone-game/
題目
給你一個整數陣列 nums 。玩家 1 和玩家 2 基於這個陣列設計了一個遊戲。
玩家 1 和玩家 2 輪流進行自己的回合,玩家 1 先手。開始時,兩個玩家的初始分值都是 0 。每一回合,玩家從陣列的任意一端取一個數字(即,nums[0] 或 nums[nums.length - 1]),取到的數字將會從陣列中移除(陣列長度減 1 )。玩家選中的數字將會加到他的得分上。當陣列中沒有剩餘數字可取時,遊戲結束。
如果玩家 1 能成為贏家,返回 true 。如果兩個玩家得分相等,同樣認為玩家 1 是遊戲的贏家,也返回 true 。你可以假設每個玩家的玩法都會使他的分數最大化。
用例
示例 1:
輸入:nums = [1,5,2]
輸出:false
解釋:一開始,玩家 1 可以從 1 和 2 中進行選擇。
如果他選擇 2(或者 1 ),那麼玩家 2 可以從 1(或者 2 )和 5 中進行選擇。如果玩家 2 選擇了 5 ,那麼玩家 1 則只剩下 1(或者 2 )可選。
所以,玩家 1 的最終分數為 1 + 2 = 3,而玩家 2 為 5 。
因此,玩家 1 永遠不會成為贏家,返回 false 。
示例 2:
輸入:nums = [1,5,233,7]
輸出:true
解釋:玩家 1 一開始選擇 1 。然後玩家 2 必須從 5 和 7 中進行選擇。無論玩家 2 選擇了哪個,玩家 1 都可以選擇 233 。
最終,玩家 1(234 分)比玩家 2(12 分)獲得更多的分數,所以返回 true,表示玩家 1 可以成為贏家。
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 107
思路
877石子游戲實際上是486預測贏家的特殊情況,兩者的區間dp思路一致
區間dp主要是尋找區間內的最優解
預測贏家,主要判定在區間[0,n-1]之間玩家1和玩家2能取得的最大差值,在[x,y]區間上能取得的最大差值即為max(nums[x]-dp[x+1][y],nums[y]-dp[x][y-1])範圍,區間每縮小一步即為對手操作獲得最高分
class Solution {
public:
bool PredictTheWinner(vector<int>& nums) {
int n=nums.size();
vector<vector<int>>dp(n,vector<int>(n));
for(int i=0;i<n;++i){
dp[i][i]=nums[i];
}
for(int i=1;i<n;++i){
int x=0,y=i;
while(x<n&&y<n){
dp[x][y]=max(nums[x]-dp[x+1][y],nums[y]-dp[x][y-1]);
++x;
++y;
}
}
if(dp[0][n-1]>=0)
return true;
return false;
}
};
在石子游戲中由於不存在平局情況,而且每人拿到的石子數相同(石子堆數量為偶數),即先手者一定能取得偶數堆中的最大值和奇數堆中的最大值,所以先手必勝