Description:
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.
Solution:
这类问题给我的第一感觉就是区间DP(因为很容易有区间的状态),所以就往这方面想了。
DP[i][j] 表示如果区间[i,j]中间的所有元素都去掉,那么最大值是多少,很容易得到状态转移方程:
DP[i][j] = max( DP[i][k-1] + DP[k+1][j] + nums[i-1] * nums[k] * nums[j+1] )
同时注意一下边界值的表示,即出现 [-1] 和 [n] 的时候如何处理。
nums[-1] = 1
nums[n] = 1
DP[i][i-1] = 0
DP[j+1][j] = 0
public class Solution {
public int maxCoins(int[] nums) {
int n = nums.length;
if (n == 0)
return 0;
int dp[][] = new int[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = nums[i] * (i - 1 >= 0 ? nums[i - 1] : 1)
* (i + 1 < n ? nums[i + 1] : 1);
}
int i, j;
int num_left, num_right;
for (int len = 2; len <= n; len++) {
for (i = 0; (j = i + len - 1) < n; i++) {
num_left = i > 0 ? nums[i - 1] : 1;
num_right = j < n - 1 ? nums[j + 1] : 1;
for (int k = i + 1; k + 1 <= j; k++) {
dp[i][j] = Math.max(dp[i][j], num_left * num_right
* nums[k] + dp[i][k - 1] + dp[k + 1][j]);
}
dp[i][j] = Math.max(dp[i][j], num_left * num_right * nums[i]
+ dp[i + 1][j]);
dp[i][j] = Math.max(dp[i][j], num_left * num_right * nums[j]
+ dp[i][j - 1]);
}
}
return dp[0][n - 1];
}
}