题目
有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。
求所能获得硬币的最大数量。
代码
class Solution {
public int maxCoins(int[] nums) {
int[] points= new int[nums.length+2];
points[0] = points[points.length-1] = 1;
int[][] dp= new int[nums.length+2][nums.length+2];// base case 已经都被初始化为 0
for (int i = 0; i <nums.length ; i++) {
points[i+1]=nums[i];
}
// 开始状态转移,从右下角开始遍历
for (int i = nums.length+1; i >=0 ; i--) {
for (int j = i+1; j < nums.length+2; j++) {
for (int k = i+1; k < j; k++) {
dp[i][j]=Math.max(dp[i][j],dp[k][j]+dp[i][k]+points[i]*points[j]*points[k]);
}
}
}
return dp[0][nums.length+1];
}
}
要点
- dp定义:dp[i][j] = x表示,戳破气球i和气球j之间(开区间,不包括i和j)的所有气球,可以获得的最高分数为x。
- 如何做选择:气球i和气球j之间最后一个被戳破的气球可能是哪一个?
- 寻找i到j的最大值,我们需要对原数组头和尾添加一个数1