题目:
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
题解:
一开始没有看到题目说,要求获得尽可能多的coin,用递归做的error之后,发现了题目要求没有看清。因为题目说nums[-1]和nums[n]都当做1来计算,所以我直接另声明了一个vector,第一个和最后一个元素为1,中间为数组元素。
第一个想法是用回溯来做,后来发现很难实现,而且复杂度太大;后来查询了资料之后,发现应该用动态规划算法,特意百度了一下相关资料。此题目每一次戳破气球都会影响下一次戳破气球的情况,所以用分治法子问题太多;而动态规划可以解决这个问题,因为适用于动态规划的问题就是子问题互相影响的。用一个二维数组来记录每一个子问题的结果,dp[left][right]为当前子问题,即left和right之前气球的maxcoin。right=left和right=left+1时,dp为0。
答案:
class Solution {
public:
int maxCoins(vector<int>& nums)
{
vector<int> a;
a.push_back(1);
for(int i=0;i<nums.size();i++)
{
a.push_back(nums[i]);
}
a.push_back(1);
int dp[a.size()][a.size()]={};
for(int i=2;i<a.size();i++)
{
for(int left=0;left<a.size()-i;left++)
{
int right=left+i;
for(int k=left+1;k<right;k++)
{
dp[left][right]=max(dp[left][right],a[left]*a[k]*a[right]+dp[left][k]+dp[k][right]);
}
}
}
return dp[0][a.size()-1];
}
};