题目:Burst Balloons
原题链接:https://leetcode.com/problems/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
给出 n 个气球,序号从 0 到 n-1 ,每个气球上面印着一个数字代表数组元素,让你来弄爆气球,每弄爆一个气球 i ,你会得到nums[left] * nums[i] * nums[right] 的钱币,其中 left 和 right 是当前气球旁边相邻气球上面的数字,当气球爆掉之后, left 和 right 两个气球变成相邻,依次往复。求能得到的最多的钱币的数值。
注意:如果要弄爆的气球的左边或者右边没有气球的话,假设nums[ left ]或者nums[ right ]为1,当然它们不是真实存在的,你不能引爆它们。题目保证0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100。
用动态规划来做,开一个dp[ ][ ]数组,其中dp[ i ][ j ]表示从第 i 到第 j 个气球所能得到的最大硬币值,初始状态都置为0。在nums数组的头和尾插入 1 用来辅助计算。
用一个下标start把从 i 到 j 分成两块,其中dp[ i ][ j ]的值可以用dp[ i ][start - 1] + nums[ i - 1 ] * nums[ start ] * nums[ j + 1 ] +dp[ start + 1 ][ j ]来表示,将start从 i 到 j 循环一遍找出最大的值即可。
代码如下:
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size();
nums.insert(nums.begin(), 1);
nums.push_back(1);
vector<vector<int> > dp(nums.size(),vector<int>(nums.size(), 0));
for(int len = 1; len <= n; ++len) { // len是长度,逐步扩大
for(int left = 1; left <= n - len + 1; ++left) {
int right = left + len - 1;
for(int start = left; start <= right; ++start) {
dp[left][right] = max(dp[left][right], dp[left][start - 1] + nums[left - 1] * nums[start] * nums[right + 1] + dp[start + 1][right]);
}
}
}
return dp[1][n];
}
};