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至i-1个气球的最大积分,看可不可以由此推出0至i个气球的最大积分,虽然0至i-1个最大积分求出了,但是加入了i,要求出0至i个气球的最大积分,那么0至i-1整个爆炸序列又会改变,所以不能根据0至i-1个气球的最大积分推出0至i个气球的最大积分。
想着可不可以求出第i个到第j个气球的最大积分,然后根据第i个至第j个最大积分推出第i-1个至j+1个气球的最大积分,同理,好像也不行。
参考网上的做法,换个意义,不管怎么踩气球,那么总有一个气球最后踩吧,对于任意第i个气球 (i在0到n-1之间),求出它的最大积分temp,那么最后的结果就是每一个temp中最大的一个。
抽象化,不只是求0到n-1之间气球的最大积分,求i至j之间气球的最大积分dp[i][j],则:
dp[i][j]=max{d[i][x-1]+nums[i-1]*nums[x]*nums[j+1]+d[x+1][j]} 其中i<=x <=j
当x是最后一个爆炸的时候,d[i][x-1] 和d[x+1][j]肯定全部爆炸完了
那么第x个气球肯定和第i-1和j+1个气球一起爆炸
public class Solution {
public int maxCoins(int[] nums) {
int n=nums.length;
if(n==0) return 0;
int[] arr=new int[n+2];
for(int i=0;i<n;i++)
{
arr[i+1]=nums[i];
}
arr[0]=1; arr[n+1]=1;
int[][] dp=new int[n+2][n+2];
for(int last=1;last<=n;last++)
{
int gap=last-1;
for(int i=1;i<=n-gap;i++)
{
int j=i+gap;
for(int x=i;x<=j;x++)
{
int temp=(dp[i][x-1])+arr[i-1]*arr[x]*arr[j+1]+dp[x+1][j];
if(dp[i][j]<temp)
dp[i][j]=temp;
}
}
}
return dp[1][n];
}
}