我是靠谱客的博主 开放康乃馨,最近开发中收集的这篇文章主要介绍312 戳气球(区间dp),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部