312. Burst Balloons

312. Burst Balloons
Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.

Find the maximum coins you can collect by bursting the balloons wisely.

Note:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

Example:

Given [3, 1, 5, 8]

Return 167

nums = [3,1,5,8] –> [3,5,8] –> [3,8] –> [8] –> []
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

已知我們有n個氣球,每個氣球有一個數,爆一個氣球可以獲得這個氣球的數*相鄰兩個氣球的數(越界默認爲1)個金幣,求爆破這n個氣球所能獲得的最大金幣額數。

首先枚舉法是不現實的,這將會是巨量的計算量。但是我們可以使用動態規劃來計算。

首先記每個氣球的數字存放在nums中,一共有len個氣球,dp[i][j]是從nums[i]到nums[j]的子串的最大金幣額數。顯而易見,一定有一個氣球是最後爆破的,假設它對應nums[k],那麼可知總金額爲爆破最後一個氣球獲得的金幣數,與爆破這個氣球的左邊的所有氣球的最大金幣數,和爆破這個氣球的右邊的所有氣球的最大金幣數之和。也就是

dp[0][len1]=1nums[k]1+dp[0][k1]+dp[k+1][len1]

而爲了確定這個最後爆破的氣球,只要將所有情況都遍歷一次,選出最終總金幣數最大的那個即可。而要求1*nums[k]*1+dp[0][k-1]+dp[k+1][len-1],我們首先得求出dp[0][k-1]和dp[k+1][len-1],那麼原理同求dp[0][len-1],但是要注意的是,由於dp[0][len-1]的左右兩端越界默認爲1,而其他子串的情況並不一定會產生越界,我們設子串的最左端爲left,最右端爲right,那麼

dp[left][right]=max(dp[left][right],nums[left1]nums[k]nums[right+1]+dp[left][k1]+dp[k+1][right])

對子串中的每個數都計算一次,求出最大值賦給dp[left][right]。一層一層求出來,最後便能求出dp[0][len-1],也就是我們想要的結果。

爲方便處理越界情況,我們在nums的前面插入1,後面添加1。dp矩陣在在外圍添加了一圈,並賦初值爲0。
參考代碼如下:

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        int len = nums.size();
        // init
        nums.insert(nums.begin(), 1);
        nums.push_back(1);
        int dp[len+2][len+2];
        for(int i = 0; i < nums.size(); i++)
            for(int j = 0; j < nums.size(); j++)
                dp[i][j] = 0;
        // calculate
        for(int l = 1; l <= len; l++) {
            for(int left = 1; left <= len - l + 1; left++) {
                int right = left + l -1;
                for(int i = left; i <= right; i++) {
                    int temp = nums[left-1]*nums[i]*nums[right+1] + dp[left][i-1] + dp[i+1][right];
                    dp[left][right] = max(dp[left][right], temp);
                }
            }
        }
        return dp[1][len];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章