有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。
求所能获得硬币的最大数量。
说明:
你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
示例:
输入: [3,1,5,8]
输出: 167
解释: nums = [3,1,5,8] –> [3,5,8] –> [3,8] –> [8] –> []
coins = 315 + 358 + 138 + 181 = 167
思路:
可以利用区间动态规划,dp[i][j]表示i到j之间的最优解(不包括i,j),那么dp[i][j]就等于max(dp[i][j], dp[i][k] + dp[k][j] + nums[i] * nums[j] * nums[k])。
即我们假设求i到j之间的最优解,k为i和j之间的数,那么当前i到j之间以k为基准将要戳k(也就是k是i到j中最后一个戳的)的最优解就等于k左半部分最优解加k右半部分最优解加k、j、i的乘积,遍历k求出最大的一个就好了。当然dp初始值要为0,这样第一次戳i时dp[i-1][i+1]就理所当然等于0 + nums[i+1] nums[i] nums[i - 1] + 0。
nums首部先插入1,再在末尾补1。
1 | class Solution { |