概述
1. 问题描述:
有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。求所能获得硬币的最大数量。
示例 1:
输入:nums = [3,1,5,8]
输出:167
解释:
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
示例 2:
输入:nums = [1,5]
输出:10
提示:
n == nums.length
1 <= n <= 500
0 <= nums[i] <= 100
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/burst-balloons
2. 思路分析:
这道题目属于经典的区间dp的问题,对于区间dp的问题我们其实是可以尝试枚举所有长度的区间,为了避免数组越界的问题我们在nums数组左右两边各增加一个值为1的数字,然后枚举起点为i的长度为j的区间,然后尝试在当前长度为j的区间中枚举当前戳掉的气球为第k个气球(第一个气球与最后气球是不能够戳掉的),从较短的区间进行递推一直到最长的那个区间即可。其中我们可以声明长度为n + 2的二维列表,f[i][j]的含义其实是很好想出来的,因为表示的是区间所以含义为区间[i, j]的最大得分,其实本质上是由小的区间范围递推到更大的区间范围,所以最终的结果肯定是最优的(可以看成是暴力枚举的优化,其实也是在尝试所有可能的方案,只是这里的dp是有选择性的记录结果)。
3. 代码如下:
from typing import List
class Solution:
def maxCoins(self, nums: List[int]) -> int:
n = len(nums)
# 往左右两边各插入一个值为1的气球这样而且这两只气球是不能够被戳掉的, 是边界情况
# dp[i][j]表示的区间[i, j]中第i, j只气球是没有被戳掉的
nums.insert(0, 1)
nums.append(1)
# 多声明几个长度防止越界
dp = [[0] * (n + 10) for i in range(n + 10)]
# 区间长度为l
for l in range(3, n + 3):
# 枚举所有的区间
i = 0
# 枚举所有起点为i长度为l的区间
while i + l - 1 <= n + 1:
j = i + l - 1
# 爆掉的是第k个气球
for k in range(i + 1, j):
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[i] * nums[j] * nums[k])
i += 1
return dp[0][n + 1]
最后
以上就是开放康乃馨为你收集整理的312 戳气球(区间dp)的全部内容,希望文章能够帮你解决312 戳气球(区间dp)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复