leetcode 戳氣球


有 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 =  3*1*5      +  3*5*8    +  1*3*8      + 1*8*1   = 167


class Solution {
    public int maxCoins(int[] nums) {
        int len = nums.length;
        int[] langarr = new int[len+2];
        langarr[0] = 1;
        for (int i = 0, j = 1; i < len; i++, j++) langarr[j] = nums[i];
        len = langarr.length;
        int[][] dp = new int[len][len];
        langarr[len-1] = 1;
        for (int i = 2; i < len; i++) {
            for (int j = 0; j+i < len; j++) {
                for (int k = j+1; k < j+i; k++) {
                    dp[j][j+i] = Math.max(dp[j][j+i], dp[j][k]+dp[k][j+i]+langarr[j]*langarr[k]*langarr[j+i]);
                }
            }
        }
        return dp[0][len-1];
    }
}

dp[i][j]的含義是 第i個氣球到第j個氣球(不包含i,j) ,最好的扎法能得多少分。

dp[j][j+i] = Math.max(dp[j][j+i], dp[j][k]+dp[k][j+i]+langarr[j]*langarr[k]*langarr[j+i]);

以上是最精華的遞推公式,這種屬於分治思想,分治的動態規划題 dp為二維的時候,從短的長度到長的長度去滲透,
k的含義是,假設k是最后一個扎破的氣球, 這個想法最關鍵(自己想到了分治,但是總是感覺左右會有依賴沒法分),也是這道題最難想到的點,最后一個扎破的氣球的左邊和右邊是完全沒有依賴關系的,可以分別運算的部分。
如果k是最后一個扎破的,那么最后一次的得分也可以得出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM