1. 程式人生 > >leetcode 312 hard

leetcode 312 hard

問題如下:

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:

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

Input: [3,1,5,8]
Output: 167 
Explanation: 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:
    def maxCoins(self, nums):
        """
        : type nums: List[int]
        : rtype: int
        """
        # 方法說明
        # 迭代式: 
        # maxcoins(i,j) = nums[i]*nums[k]*nums[j] + maxcoins(i,k) + maxcoins(k,j)
        # k是最後刪除的一個氣球,maxcoins是nums[i...j]能戳破氣球的最大值
        # maxcoins(i,k)表示i,k之間的氣球被刪除
        # maxcoins(k,j)表示k,j之間的氣球被刪除
        # 由於i,k之間和k,j之間的氣球被刪除,所以nums[k]只能與更外圍的數字相乘(nums[i]*nums[k]*nums[j])
        # maxcoins用dp替代
        # 
        # 按照 j-i == 2,3,4,5 的順序計算
        # 參考:https://blog.csdn.net/zly9923218/article/details/51059664
        
        # 空間換時間

        # 首尾新增1
        nums_len = len(nums)
        nums.insert(0,1)
        nums.append(1)
        
        n = nums_len+2
        dp = []
        for i in range(n):
            temp_list = [0 for j in range(n)]
            dp.append(temp_list)
        
        for i in range(n-2):
            dp[i][i+2] = nums[i]*nums[i+1]*nums[i+2]
        
        for l in range(3,n):
            for i in range(0,n-l):
                j = i+l
                for k in range(i+1,j):
                    dp[i][j] = max(dp[i][j], nums[i]*nums[k]*nums[j] + dp[i][k] + dp[k][j] )
        
        return dp[0][n-1]