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 ballooni
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 1671
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
Credits:
Special thanks to @peisi for adding this problem and creating all test cases.
像这种求极值问题,我们一般都要考虑用动态规划Dynamic Programming来做,我们维护一个二维动态数组dp,其中dp[i][j]表示打爆区间[i,j]中的所有气球能得到的最多金币。题目中说明了边界情况,当气球周围没有气球的时候,旁边的数字按1算,这样我们可以在原数组两边各填充一个1,这样方便于计算。这道题的最难点就是找递归式,如下所示:
dp[i][j] = max(dp[i][j], nums[i - 1]*nums[k]*nums[j + 1] + dp[i][k - 1] + dp[k + 1][j]) i∈[1,n],j∈[1,n-i+1] k∈[j,j+i)
class Solution { public: int maxCoins(vector<int>& nums) { int n=nums.size(); nums.insert(nums.begin(),1); nums.insert(nums.end(),1); vector<vector<int>>dp(n+2,vector<int>(n+2,0)); //dp[i][j]表示i到j求得的最大coin值 for(int len=1;len<=n;len++){//计算的气球下标范围长度 for(int start=1;start<=n-len+1;start++){//气球下标开始的位置范围 int end=start+len-1;//气球下标结束的位置 for(int x=start;x<=end;x++){ dp[start][end]=max(dp[start][end],dp[start][x-1]+nums[start-1]*nums[x]*nums[end+1]+dp[x+1][end]); } } } return dp[1][n]; } };