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 解析:典型的DP问题,从dp[1][1]迭代推出dp[1][n],n表示数组最后一个数的下标,递推关系为:dp[i][j] = max(dp[i][k-1] + nums[i-1]*nums[k]*nums[j+1]+dp[k+1][j]),这里的k范围是【i,j】,这里比较难的一点是nums[i-1]*nums[k]*nums[j+1]这一项的含义,为什么是这个,如果我们burst到最后的一个气球的时候,那么最后一次可获得的分数为nums[-1]*nums[k]*nums[n],再假设两个气球的情况下(如果1是最优k值),dp[1][2] = dp[1][1] + dp[2][2] + nums[1]*nums[2]*1,由此类推,可以总结出上面的迭代公式。(此处没有给出明确的证明过程,如果有大神能够给出完整推导,还望能指点迷津)
Code:
class Solution { public: int maxCoins(vector<int>& nums) { for(int i=0; i<nums.size(); i++){ if(nums[i] == 0){ nums.erase(nums.begin()+i); --i; } } const int n = nums.size(); if(n == 0) return 0; nums.insert(nums.begin(),1); nums.insert(nums.end(),1); int m = nums.size(); vector<vector<int>> dp(m,vector<int>(m,0)); for(int k=1; k <= n; k++){ for(int s = 1; s+k-1 <= n; s++){ int best = 0; for(int b=0; b<k; b++){ best = max(best,dp[s][s+b-1]+nums[s-1]*nums[s+b]*nums[s+k]+dp[s+b+1][s+k-1]); } dp[s][s+k-1] = best; } } return dp[1][n]; } };
时间: 2024-10-21 13:20:48