题目链接
题目分析
以两个数作为左右端点,找出最优解中它们中间那个戳破的气球,中间这个气球把整个队列分为了2部分,要想让中间这个气球和2个端点靠在一起,就需要先把分开的2部分的气球戳破。 dp[i][j]表示i~j最大值,i,j不戳破。 比如k气球在i,j之间时(i,k,j)被戳破,那么要先戳破i,k、k,j之间的气球,所以dp[i][j]=dp[i][k]+dp[k][j]+nums[i]nums[k]nums[j]
上面是引述评论区大佬的,其实总而言之就是利用一个二维的dp数组,记录从(i,j)之间戳破气球可以获得的最大硬币数(这里i,j都是开区间),然后我们在这个区间内一个一个气球戳破去看看哪一个气球在这轮中能够使得这个区间内获得最大值。也就是转移方程。转移方程的意思是我们已经把(i,k)和(k,j)之间的气球都戳破了,现在只剩下i, k, j三个气球,那么我们戳破就是把这三者相乘。
代码实现
class Solution {
public int maxCoins(int[] nums) {
int[] cur = new int[nums.length + 2];
//补齐左右边界的气球。
cur[0] = 1;
cur[cur.length - 1] = 1;
for(int i = 1; i <= nums.length; i++){
cur[i] = nums[i - 1];
}
//在i,j区间内戳破气球可以获得的最大值。
int[][] dp = new int[nums.length + 2][nums.length + 2];
//因为我们最终答案是取右上角的数值,所以我们第一个状态应该倒叙
for(int i = nums.length + 1; i >= 0; i--){
//第二个状态从左到右正序
for(int j = i + 1; j < cur.length; j++){
for(int k = i + 1; k < j; k++){
dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[k][j] + cur[i]*cur[j]*cur[k]);
}
}
}
return dp[0][cur.length - 1];
}
}