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
使用动态规划的方法:关键是确定状态转移方程
其dp数组dp[i, j]代表区间[i, j]的最大爆破money,所以其区间的确定顺序应该是根据长度从小到大,先确定dp[i][i], 再确定dp[i][i+2].....直到填满整个右上方的区域,以此图为例,其区间确定顺序应该是([3], 3) -> ([1], 15) -> ([5], 40) -> ([8], 40) -> ([3, 1], 30) -> ([1, 5], 135) -> ([5, 8], 48) -> ([3, 1, 5], 159) -> ([1, 5, 8], 159) -> ([3, 1, 5, 8], 167)
所以遍历应该是按长度从1到4:然后确定start和end,然后确定start, end窗口中的最大值,这是就需要依赖状态转移方程,已经知道了小区间内的最大爆破值,在遍历的时候爆破第k个气球的时候最大值为左边的爆破值和右边的爆破值相加和当前爆破值的和,即 dp[start][end] = max(dp[start][end], nums[start-1] * nums[k] * nums[end+1] + dp[start][k-1] + dp[k+1][end])
0 0 0 0 0 0 0 3 30 159 167 0 0 0 15 135 159 0 0 0 0 40 48 0 0 0 0 0 40 0 0 0 0 0 0 0
class Solution(object):
def maxCoins(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums = [1] + nums + [1]
size = len(nums)
dp =[[0 for col in range(size)] for row in range(size)]
for length in range(1, size-1):
for start in range(1, size-length):
end = start + length - 1
for k in range(start, end+1):
dp[start][end] = max(dp[start][end], nums[start-1] * nums[k] * nums[end+1] + dp[start][k-1] + dp[k+1][end])
return dp[1][size-2]
if __name__ == "__main__":
nums = [3, 1, 5, 8]
solution = Solution()
print(solution.maxCoins(nums))