312. 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:
(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
真的是很难想的一题,参考了在线疯狂的博客的思路:
(看到这个思路时我发现我一直想不出是因为我没有仔细考虑 “(1) You may imagine nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them.” 这句话)
1.子问题的解是父问题解的一部分,满足这个条件,符合动态规划的要求
2.注意到“求数组得到的最大值在最前和最后分别加一个1,1不能爆”,用dp[i][j]代表子序列(i,j)产生的最大值,不包括 i 和 j ,value[]表示每一位置的数值,value的大小是nums大小(size)加2,首位分别都是1,我们最后想得到的结果就可以用dp[0][size+1]表示
3.dp[i,j] = max(dp[i,last]+dp[last,j]+value[last]*value[i]*value[j]),i < last < j ,last的含义是在i和j之间最后爆的气球,last可以将一个序列分隔为2部分,序列的最大值就是2个子序列的最大值加上last爆时产生的值
代码(c++):
class Solution {
public:
int maxCoins(vector<int>& nums) {
int size = nums.size();
int dp[502][502] = {0};
int value[502];
value[0] = 1;
for (int i = 1; i <= size; i++) value[i] = nums[i-1];
value[size+1] = 1;
for (int i = 0; i < size-1; i++) dp[i][i+1] = 0;
for (int len = 2; len < size+2; len++) {
for (int i = 0; i < size; i++) {
int j = i+len;
for (int last = i+1; last <= j-1; last++) {
dp[i][j] = max(dp[i][j], dp[i][last] + dp[last][j] + value[last]*value[i]*value[j]);
}
}
}
return dp[0][size+1];
}
};