# 312. Burst Balloons

**<font color=red>难度: Hard</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/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:

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
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N^3)******- 空间复杂度: O(N^2)******

典型dp, dp[left][right]代表爆掉left到right中间(not inclusive)所有的balloons, 所能得到的最大coins

状态方程为：
```dp[left][right] = max[(nums[i-1] * nums[i] * nums[i+1] + dp[left][i] + dp[i][right]) for i in range(left+1, right)]```
其中i为最后一个被爆掉的气球

这里的思考为：如果我们从第一个被爆掉的气球开始考虑，后面的情况我们不知道当前被爆掉的气球左右两边都是谁，也就写不出状态方程了

但是如果从最后一个被爆掉的气球开始考虑的话，那它的左右两边肯定都是1，即nums[-1]和nums[n]；
并且根据它分成的左右两边d[left][i]和dp[i][right]也可以通过同样的方法一步步算到最后


这里还有一个trick，就是对于nums[i] = 0的气球最开始就可以直接删掉了，因为对于我们的最终结果没有任何影响

beats 59.76%

```python
class Solution(object):
    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums = [1] + [i for i in nums if i > 0] + [1]
        dp = [[0] * len(nums) for _ in range(len(nums))]

        for gap in range(2, len(nums)):
            for left in range(len(nums) - gap):
                right = left + gap
                for i in range(left + 1, right):
                    dp[left][right] = max(dp[left][right],
                           nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right]) # i为最后一个被爆掉的气球
        return dp[0][-1]
```


另外看到一个很有意思的[post](https://leetcode.com/problems/burst-balloons/discuss/76241/Another-way-to-think-of-this-problem-(Matrix-chain-multiplication))

```
If you think of bursting a balloon as multiplying two adjacent matrices, then this problem is exactly the classical DP problem
Matrix-chain multiplication found in section 15.2 in the book Introduction to Algorithms (2nd edition).

For example, given [3,5,8] and bursting 5, the number of coins you get is the number of scalar multiplications you need to do
to multiply two matrices A[3*5] and B[5*8]. So in this example, the original problem is actually the same as given a matrix 
chain A[1*3]*B[3*5]*C[5*8]*D[8*1], fully parenthesize it so that the total number of scalar multiplications is maximized, 
although the orignal matrix-chain multiplication problem in the book asks to minimize it. Then you can see it clearly as a 
classical DP problem.
```



























