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];
}
};
本文解析了一道经典的动态规划问题——气球爆破问题,通过详细的步骤和代码实现展示了如何最大化爆破气球获得的分数。关键在于理解动态规划的状态转移方程,并通过实例解释了算法的具体应用。
867

被折叠的 条评论
为什么被折叠?



