原題:
有 n 個氣球,編號爲0 到 n-1,每個氣球上都標有一個數字,這些數字存在數組 nums 中。
現在要求你戳破所有的氣球。每當你戳破一個氣球 i 時,你可以獲得 nums[left] * nums[i] * nums[right] 個硬幣。 這裏的 left 和 right 代表和 i 相鄰的兩個氣球的序號。注意當你戳破了氣球 i 後,氣球 left 和氣球 right 就變成了相鄰的氣球。
求所能獲得硬幣的最大數量。
說明:
你可以假設 nums[-1] = nums[n] = 1,但注意它們不是真實存在的所以並不能被戳破。
0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
示例:
輸入: [3,1,5,8]
輸出: 167
解釋: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 315 + 358 + 138 + 181 = 167
代碼:
class Solution {
public:
int dp[501][501];
int ball[505];
int maxCoins(vector<int>& nums)
{
if(nums.empty())
return 0;
memset(dp,0,sizeof(dp));
int n = nums.size();
for(int i=1;i<=n;i++)
ball[i]=nums[i-1];
ball[0]=ball[n+1]=1;
for(int len=1;len<=n;len++)
{
for(int l=1;l<=n-len+1;l++)
{
int r=l+len-1;
for(int k=l;k<=r;k++)
dp[l][r]=max(dp[l][r],dp[l][k-1]+dp[k+1][r]+ball[l-1]*ball[k]*ball[r+1]);
}
}
return dp[1][n];
}
};
解答:
區間dp
每次戳爆一個氣球,兩邊的氣球會合並。這樣會減少一個氣球。
區間合併類的問題使用區間dp比較形象,如果是區間當中通過減少或者去掉某個元素得到狀態轉移,如去掉或者改變區間第k個元素可以按照如下的方式設置狀態。
此題設置狀態表示戳爆i到j個氣球后得到的最大金幣數,且金幣的計數方式與相鄰的氣球有關。那麼需要將所有“戳爆”後的狀態的兩邊作爲計算的參數
如下
注意與爲戳爆的氣球的兩邊