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
Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
这道题当时是通过分析最后一次操作状态和前一次操作状态上的关系。这里我们可以从最后一次burst重新考虑这个题。如果i是最后burst的,那么在这之前0~i-1,i+1~n-1这两个区间的气球都已经被消除了,而且。。。最重要的是,由于i是最后被消除的,所以左右两个区间的过程是完全被分开的,也就是说,我们找到了子问题。这里我们看一下
max(left) + left(左边左后被消除) * nums[i] * right(右边最后别消除) + max(right)
最后,对于上面这个公式枚举每一个i, 同样左右两个区间也需要枚举,不断的划分到更小的空间。需要注意的是,位于两端的数由于nums[-1] = nums[n+1] = 1, 而且如果存在0,是可以直接去除的,因为不会带来任何的coins。
编程思路:1.首先去除里面包含的0,然后扩充大小,首尾添加元素1,代表-1,n+1位。
2.使用一个二维数组,记录已left和right之间的元素能够获得的最大coins数。
3.left从0开始到n-1,(扩充后应该是n-2),right应该是从left出发不同间隔的值。注意,left和right都是作为边界。
4.使用公式:coins[left][right] = max(coins[left][right], coins[left] [j] * nums[j] * coins[j][right])
class Solution(object):
def boom(self,nums,res,left,right):
#print left,right
if right - left <= 1:
return 0
if res[left][right] >0:
return res[left][right]
maxx = 0
for i in range(left+1,right):
#print i
maxx = max(maxx,nums[i]*nums[left]*nums[right] +
self.boom(nums,res,left,i)+self.boom(nums,res,i,right))
res[left][right] = maxx
return res[left][right]
def maxCoins(self, nums):
#res = [1]
res = [0]*(len(nums)+2)
#res += [1]
res1 = []
for i in xrange(len(nums)+2):
res1.append(res[:])
res = res1[:]
nums = [1] + nums +[1]
nums = nums[:]
return self.boom(nums,res,0,len(nums)-1)