leetcode 1140. Stone Game II 的解法(動態規劃標準例題)

題目是:

亞歷克斯和李繼續他們的石子游戲。許多堆石子 排成一行,每堆都有正整數顆石子 piles[i]。遊戲以誰手中的石子最多來決出勝負。
亞歷克斯和李輪流進行,亞歷克斯先開始。最初,M = 1。
在每個玩家的回合中,該玩家可以拿走剩下的 前 X 堆的所有石子,其中 1 <= X <= 2M。然後,令 M = max(M, X)。
遊戲一直持續到所有石子都被拿走。
假設亞歷克斯和李都發揮出最佳水平,返回亞歷克斯可以得到的最大數量的石頭。

粗略思路:

(1)求最大值,採用動態規劃可減少重複計算;

(2)亞歷克斯和李均表現爲最佳水平,即採用同一策略進行遊戲,所以動態規劃數組唯一。

詳細思路:

(1)選取結果受M和當前的座標i 影響,所以是動態規劃的數據是二維數組;

(2)剩下的石頭如果小於2M,可以把剩下的所有石頭拿走,可作爲動態規劃的起始條件;

(3)當前可取的石子爲,剩下的所有石頭 - 上一次取走的石頭,求當前可取石頭的最大值,所以遞歸式爲

          

dp[i][j]=max(dp[i][j],resum[i]-dp[i+x][max(j,x)]);

其中resum[i]爲剩下的所有石頭,上一次取走的石頭dp[i+x][max(j,x)],x爲這次取的石頭堆數,max(j,x)即M = max(M, X)。

代碼如下:

class Solution {
public:
    int stoneGameII(vector<int>& piles) {
        int n=piles.size();
        //設置二維動態規劃數組,分別式當前回合的起始座標和M
        vector<vector<int>> dp(n,vector<int>(n,0));
        //求剩下的所有石頭總和
        vector<int> resum(n,0);
        int sum=0;
        for(int i=n-1;i>=0;i--)
        {
            sum+=piles[i];
            resum[i]=sum;
        }
        //初始化動態規劃初始條件,剩下的石頭如果小於2M,可以把剩下的所有石頭拿走
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i+2*j>=n)
                {
                    dp[i][j]=resum[i];
                }
            }
        }
        //遞歸
        for(int i=n-1;i>=0;i--)
        {
            for(int j=n-1;j>=0;j--)
            {
                for(int x=1;x<=2*j && i+x<n;x++)
                    dp[i][j]=max(dp[i][j],resum[i]-dp[i+x][max(j,x)]);
            }
        }
        //返回起始座標爲0,M爲1時,亞歷克斯可以得到的最大數量的石頭
        return dp[0][1];
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章