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
这道题的题意是:给出从0到n-1共n个热气球,每一个热气球都标记有一个数字,数字存储在nums数组中,我们需要戳爆一个热气球i,得到nums[left] * nums[i] * nums[right],其中left和right表示i相邻的两个标号,如果戳爆了i,left和right会相邻。
这道题的难度还是比较大的,不太容易想到好的做法,我尝试了多种方式后,没能解决这个问题,查阅了很多博客之后才了解了这道题的解法。这是一道动态规划的题,我们用dp[l][r]表示戳爆left和right之间所有的热气球得到的值,注意这里并不包括边界left和right。另k = l - r,表示从左到右的跨度,我们最终只需要返回k = nums.size() - 1时,也就是dp[0][nums.size() - 1]的值即可。
dp[l][r]的计算方法则是遍历l和r之间所有i,取nums[l] * nums[i] * nums[r]的最大值即可。
我们在nums的开头和结尾添加一个1来定义边界,然后从2到nums.size()遍历k,对每个k又遍历所有l和k,此时r = l + k, 计算dp[l][r]的值,遍历结束后,dp[0][nums.size() - 1]就是我们所要求的结果。
class Solution {
public:
int maxCoins(vector<int>& nums) {
nums.insert(nums.begin(), 1);
nums.push_back(1);
vector<vector<int> > dp;
for(int i = 0; i < nums.size(); i++) {
vector<int> temp;
for (int j = 0; j < nums.size(); j++) {
temp.push_back(0);
}
dp.push_back(temp);
}
for (int k = 2; k < nums.size(); k++) {
for (int l = 0; l < nums.size() - k; l++) {
int r = l + k;
for (int i = l + 1; i < r; i++) {
dp[l][r] = max(dp[l][r], dp[l][i] + nums[l] * nums[i] * nums[r] + dp[i][r]);
}
}
}
return dp[0][nums.size()-1];
}
};