题目:
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 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:
- You may imagine
nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them. - 0 ≤
n
≤ 500, 0 ≤nums[i]
≤ 100
Example:
Input:[3,1,5,8]
Output:167 Explanation:
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个气球的序列,每个气球具有不同的值,有如下规则,假设打破气球i,那么得到的值为气球i-1乘上气球i乘上气球i+1,之后气球i移出序列,题目需要求的是,打破的顺序要如何处理才能是得分总数最大。
解法:
这题可以看成是一个DP问题,我们可以由一小部分的解推到全局解。
举个例子
假设我们求 2到4气球的打破的最大值,那么我们只需要确定最后打破哪个即可
如果最后打破4号,那么这个数值会为 max(num[1~3])+ num[-1]*num[4]*num[5] (假设打破1到3的数值在之前已求出)
如果最后打屁 3号 那么数值为 max(num[1~2])+max(num[4])+num[-1]*num[3]*num[5]
如果最后打破 2 。。。。。。。
依据这个思路,我们可以做一张动态规划的表dp[][] 我们使用dp[i][j] 来表示打破i到j之间的气球所能达到的最大值
对于 3 1 5 8 这个气球序列 我们可以得到下表(括号里为填表的顺序)
代码实现:
代码方面,为了方便处理 我们在气球序列的前后各加了一个数值为1的气球,方便计算题中所说的边界 num【-1】 num【n】为1
class Solution {
public int maxCoins(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int array[] = new int[nums.length + 2];
array[0] = 1;
array[array.length-1] = 1;
for (int i = 0; i < nums.length; i++) {
array[i+1] = nums[i];
}
int[][] dp = new int[array.length][array.length];
for(int i=1;i<array.length-1;i++){
for(int j=i;j>=1;j--){
for (int k=j; k <= i; k++) {
dp[j][i] = Math.max(array[j-1]*array[k]*array[i+1] + dp[j][k-1] + dp[k+1][i], dp[j][i]);
}
}
}
return dp[1][array.length-2];
}
}