leetcode 312 戳氣球

原題:
有 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個元素可以按照如下的方式設置狀態。

dp[i][j]=max(dp[i][j],dp[i][k1]+dp[k+1][j]+fun(i,j,k)dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j]+fun(i,j,k)

此題設置狀態dp[i][j]dp[i][j]表示戳爆i到j個氣球后得到的最大金幣數,且金幣的計數方式與相鄰的氣球有關。那麼需要將所有“戳爆”後的狀態的兩邊作爲計算的參數

如下
dp[i][j]=max(dp[i][j],dp[i][k1]+dp[k+1][j]+ball[i1]ball[k]+ball[j+1]dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j]+ball[i-1]*ball[k]+ball[j+1]
注意ball[i1]ball[i-1]ball[j+1]ball[j+1]爲戳爆的氣球的兩邊

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