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
题目 任意顺序击破小球(球被击破后,剩余球合拢),每次得分为击破球和相邻球分数乘积。求最大总得分。
分治法思路,确定一个球为最后被击破的球,问题可以分解为两个子问题。例如最后击破nums[i]有 f(i) = maxCoins(nums[0:i-1])+maxCoins(nums[i+1:]) + nums[-1]*nums[i]+nums[n](在这里如果越界了,值等于1)。如果DFS不缓存局部解显然会超时。缓存局部解可以得到不错的时间。不过也可以转成DP,速度更快。代码如下:
int max(int i1,int i2){
return i1 > i2 ? i1 : i2;
}
int maxCoins(int* nums, int numsSize){
if(numsSize == 0){
return 0;
}
int tmp[numsSize][numsSize];
for(int rightIndex = 0; rightIndex <numsSize;++rightIndex){
for(int leftIndex = rightIndex; leftIndex >= 0; --leftIndex){
int leftRightValue = 1;
if(leftIndex > 0){
leftRightValue *= nums[leftIndex-1];
}
if(rightIndex < numsSize-1){
leftRightValue *= nums[rightIndex + 1];
}
int maxValue = 0;
//遍历最后一个击破位置,得到最大值
for(int lastBurstIndex = leftIndex;
lastBurstIndex <= rightIndex;
++ lastBurstIndex){
int tmpValue = leftRightValue*nums[lastBurstIndex];
if(lastBurstIndex > leftIndex){
tmpValue += tmp[leftIndex][lastBurstIndex-1];
}
if(lastBurstIndex < rightIndex){
tmpValue += tmp[lastBurstIndex+1][rightIndex];
}
maxValue = max(maxValue,tmpValue);
}
tmp[leftIndex][rightIndex] = maxValue;
}
}
return tmp[0][numsSize-1];
}