Leetcode_1690_石子游戲 Ⅶ_動態規劃
阿新 • • 發佈:2020-12-18
技術標籤:daily_algorithm動態規劃動態規劃leetcode
12/17
後有詳細解答步驟
class Solution {
public int stoneGameVII(int[] stones) {
int n=stones.length;
//從第一個到第i個,石頭的總數
int []sum=new int[n];
sum[0]=stones[0];
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+stones[i];
}
//從第i個到第j個兩者最大的差值
int [][]dp=new int[n][n];
/*
dp[x][x]=0;
dp[x-1][x-1]=0;
dp[x-1][x]=min(stones[x-1],stones[x]);
dp[x-2][x]=max(sum[x-1,x]-dp[x-1][x],sum[x-2,x-1]-dp[x-2][x-1]);
*/
for(int st=n-2;st>=0;st--){
for(int ed= st+1;ed<n;ed++){
dp[st][ed]=Math.max(-dp[st+1][ed]+sum[ed]-sum[st],-dp[st][ed-1]+sum[ed-1]-(st==0?0:sum[st-1]));
}
}
return dp[0][n-1];
}
}
第一步:觀察
觀察到這題無法用貪心完成,需要用動態規劃
第二步:思考轉移的狀態是什麼
我們首先先明確一點,先取的一定比後取的拿的多 最終需要返回的是第0到第n-1個的石子時候,二者的最大差值 我們將其前進一步 很容易發現就兩種轉換方式 要麼取左邊,要麼取右邊 取左邊的價值是獲得第1到第n-1個石子的總和 代價是減少(從1到第n-1個石子時,二者的最大差值) 取右邊的價值是獲得第0到第n-2個石子的總和 取右邊的代價是減少(從第0到第n-2個石子時,二者的最大差值) 寫成公式就是 dp[0][n-1]=max(sum[1,n-1]-dp[1][n-1],sum[0,n-2]-dp[0][n-2]);
第三步:思考轉移的順序
很容易發現我們的公式是從外向內轉移的
也就是我們為了獲取最終dp[0,n-1],
我們必須先獲取內部的dp[1][n-1]與dp[0][n-2],
也就是我們的轉移順序是從內而外
即先算出內部,再慢慢向外部轉移
我們觀察到
當起始點和終止點重合時:dp[x][x]=0;
而當起始點和終止點相差為1時,dp[x-1][x]=min(stones[x-1],stones[x]);
仍滿足轉移方程,並且dp[x][x]的值為int陣列初值,我們不必提前賦值