312戳气球

Posted xxswkl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了312戳气球相关的知识,希望对你有一定的参考价值。

题目:有 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

来源:https://leetcode-cn.com/problems/burst-balloons/

法一:自己的代码  动态规划

思路:这是一道区间dp题,与1000合并石头的最低成本方法类似,都是由内到外进行数据记录,关键是写出动态规划方程,注意使用动态方程的时候一定不要拘泥于只用一维dp,要根据题意进行选择,本题要求的是数组从0到n的最大值,而0和n就是决定最后结果的两个变量,故用它们定义二维动态数组,从i到j的最大值是由未戳破的k加上其余已经戳破的数组的和决定的,由此写出如下的状态转移方程.

dp[i][j] = max(nums[i-1] * nums[k] * nums[j+1] + dp[i][k-1] + dp[k+1][j] for k in range(i,j+1))

要学会斜变量dp矩阵的方法.

技术图片
from typing import List
class Solution:
    def maxCoins(self, nums: List[int]) -> int:
        ans = 0
        # 为了方便后续写状态转移方程,添加边界条件
        nums = [1] + nums + [1]
        size = len(nums)
        dp  = [[0] * size for i in range(size)]
        # 这里提供了一个斜遍历矩阵的方法,start用于控制起始位置,引入变量i进行控制行索引
        for start in range(1,size):
            i = 1
            print(- * 20)
            for j in range(start,size-1):
                print(i,j)
                # 最开始的这个状态转移方程是错的,只考虑了i,j数据两边未戳破的情况,事实上中间也有可能未戳破,与两边已经戳破的进行合并.
                # dp[i][j] = max(nums[i-1] * nums[i] * nums[j+1] + dp[i+1][j],
                #                nums[i-1] * nums[j] * nums[j+1] + dp[i][j-1])
                dp[i][j] = max(nums[i-1] * nums[k] * nums[j+1] + dp[i][k-1] + dp[k+1][j]
                               for k in range(i,j+1))
                i += 1
        print(dp)
        return (dp[1][size-2])
if __name__ == __main__:
    duixiang = Solution()
    # a = duixiang.maxCoins([3,1,5,8])
    a = duixiang.maxCoins([35, 16, 83, 87, 84, 59, 48, 41])
    print(a)
View Code

ttt

 

以上是关于312戳气球的主要内容,如果未能解决你的问题,请参考以下文章

312. 戳气球. dp

312. 戳气球

312. 戳气球

312. 戳气球

312 Burst Balloons 戳气球

312. 戳气球困难区间DP