Total Accepted: 2119
Total Submissions: 7425
Difficulty: Hard
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
思路我是看了这篇之后写的:https://leetcode.com/discuss/72216/share-some-analysis-and-explanations
思路:这道DP要从最后出发,慢慢向前推。并不是常规的从头开始想。如果我们从头开始分析的话,比如3,1,5,8这个数组,如果我们现在扎破了5,那我们这一步可以得到1*5*8 = 40分,但是他的后面状态318,并不是3158的一部分,故没有办法从头到尾DP分析。
如果从尾到头来倒推的话,3,1,5,8,我们假设,最后扎破的是5。因为最后扎的是5,所以扎5得的分数是5。 那么在扎破5之前,我们的两个子状态是什么呢? 分别是31 (5) 和 (5)8,因为最后扎的是5,所以31和8的时候,5都在他们的边界上。这样就很容易分析。扎8的时候得到的是5*8,扎31的时候,得到的是dp[31] * 5.
代码如下:
class Solution {
public:
int maxCoins(vector<int>& nums) {
int size = nums.size();
nums.insert(nums.begin(),1);
nums.push_back(1);
vector<vector<int>> dp(size+2,vector<int>(size+2,0));
int result = 0;
//dp[i][j]: when two sides still exist, maximum points can get from burst ballons from i to j
for (int j = 1; j <= size; j++) {
for (int i = j; i >= 1; i--) {
for (int k = i; k <= j; k++) {
dp[i][j] = max(dp[i][j],nums[k]*nums[i-1]*nums[j+1] + dp[i][k-1]+dp[k+1][j]);
result = max(result,dp[i][j]);
}
}
}
return result;
}
};