与矩阵连乘问题很相似:
Given
n
balloons, indexed from0
ton-1
. Each balloon is painted with a number on it represented by arraynums
. You are asked to burst all the balloons. If the you burst ballooni
you will getnums[left] * nums[i] * nums[right]
coins. Hereleft
andright
are adjacent indices ofi
. After the burst, theleft
andright
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]
≤ 100Example:
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,将nums转化为 a[1000],a[0] = a[n + 1] = 1,即可解决乘以1的问题,这题与矩阵连乘问题很相似,解决办法也很相似。设 k 是最后一个扎破的气球,dp[i][k - 1] 以及dp[k + 1][j]都是已经完全得到的具体数值,因为长度更短的区间的 dp 值都已经求得了,那么仅需加上 a[i - 1] * a[k] * a[j + 1],i , j 分别为所求区间的端点,L从1开始,经过判断,对长度为 1 的dp也可以按正确求得,注意 k = i; k <= j; 是正确的,虽然可能出现 k - 1 > i 的情况,但是由于已经初始化dp数组为0,则不会产生影响。
class Solution {
public:
int a[1000];
int dp[501][501] = {0};
int maxCoins(vector<int>& nums) {
int n = nums.size();
for(int i = 0; i < n; i++)
a[i + 1] = nums[i];
a[0] = 1;
a[n + 1] = 1;
for(int L = 1; L <= n; L++)
{
for(int i = 1; i <= n - L + 1; i++)
{
int j = i + L - 1;
for(int k = i; k <= j; k++)
{
dp[i][j] = max(dp[i][j], dp[i][k - 1] + a[i - 1] * a[k] * a[j + 1] + dp[k + 1][j]);
}
}
}
return dp[1][n];
}
};