05 August 2008
Given
balloons, indexed from 1
n
to 1
0
. Each balloon is painted with a number on it represented by array 1
n-1
. You are asked to burst all the balloons. If the you burst balloon 1
nums
you will get 1
i
coins. Here 1
nums[left] * nums[i] * nums[right]
and 1
left
are adjacent indices of 1
right
. After the burst, the 1
i
and 1
left
then becomes adjacent.1
right
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
1
nums[-1] = nums[n] = 1
. They are not real therefore you can not burst them.1
n
≤ 500, 0 ≤ 1
nums[i]
≤ 100Example:
1
2
3
4
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
一个气球对应一个数字,每次打爆一个气球,得到的金币数是被打爆的气球的数字和两边的气球上的数字相乘,如果旁边没有气球了,则按1算,以此类推,求能得到的最多金币数。又是求极值,那自然用DP,维护一个二维动态数组dp,其中dp[i][j]表示区间[i,j]中的打爆所有气球能得到的最多金币。题目中说明了边界情况,当气球周围没有气球的时候,旁边的数字按1算,这样可以在区间[i,j]两边各填充一个1,递归式:
1
2
dp[i][j] = max(dp[i][j], nums[i - 1]*nums[k]*nums[j + 1] + dp[i][k - 1] + dp[k + 1][j])
其中i ≤ k ≤ j
因为每次气球打爆后就不计算了,所以只是更新了dp这个二维数组的右上三角区域(左下三角区域为空),我们最终要返回的值存在dp[0][n-1]中,其中n是两端添加1之前数组nums的个数。
更加详细的解释 https://leetcode.com/problems/burst-balloons/discuss/76228/Share-some-analysis-and-explanations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int maxCoins(int[] nums) {
int[] newNums = new int[nums.length + 2];
int n = 1;
for (int x : nums) {
if (x > 0) {
newNums[n] = x;
n++;
}
}
newNums[0] = newNums[n++] = 1;//两边各加一个1,注意这里末尾的元素赋值为1后再自增一下
int[][] dp = new int[n][n];
for (int k = 2; k < n; k++) {
for (int left = 0; left < n - k; left++) {
int right = left + k;
for (int i = left + 1; i < right; i++) {
dp[left][right] = Math.max(dp[left][right],
newNums[left]*newNums[i]*newNums[right] + dp[left][i] + dp[i][right]);
}
}
}
return dp[0][n-1];
}
}