LeetCode (Li button) 312 question: Poke the balloon ---- dynamic programming solution with detailed notes

问题描述

There are n balloons, numbered from 0 to n-1, and each balloon is marked with a number, which exists in the array nums.
You are now asked to pop all the balloons. Pop the i-th balloon, you can get nums[i-1] * nums[i] * nums[i+1] coins. Here i - 1 and i + 1 represent the serial numbers of the two balloons adjacent to i. If i - 1 or i + 1 is outside the bounds of the array, treat it as a balloon with number 1.

Find the maximum number of coins that can be obtained.

示例

输入: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

输入:nums = [1,5]
输出:10

思路分析

For this kind of problem solving the most value problem, the dynamic programming solution is the first choice, dynamic programming yyds, hahahaha. I also mentioned the problem solved by dynamic programming before. To judge whether a problem can be solved by dynamic programming, first check whether the problem has an optimal sub-problem structure . Finding the optimal sub-problem structure is actually equivalent to defining a DP array. In this problem, the subproblem can be defined as the maximum number of coins that can be obtained by the balloons numbered i to j, then the DP array is defined as a two-dimensional array DP[ i ][ j ].
In this problem, if you poke a balloon, you can get coin rewards from adjacent balloons, but with so many balloons, we don’t know which one to poke first to get the most coin rewards, so let’s just assume that the number i to j Among the balloons, the other balloons have been smashed, leaving only one balloon at position k. We assume that the last balloon at
position k gets the most coin rewards. That is, the total number of coin rewards obtained in balloons numbered i to j DP[ i ][ j ] = DP[ i ][ k ] + nums[ i ] * nums[ k ] * nums[ j ] , which is actually similar to the score The idea of ​​governance, the left and right sides of k are calculated separately . We will ask, there are so many balloons between i and j, how do we know which one gets the most coins when we finally pop it? In fact, we list all the cases and take the maximum value.
We start the calculation when there are only three numbers in the (i, j) open interval, store the maximum value of gold coins in each small interval, and then gradually expand to a larger interval, using the already calculated numbers in the small interval It is enough to calculate a larger interval (this is also the advantage of dynamic transfer, the latter result is affected by the former result, and can be calculated through the former result, thereby avoiding repeated calculations)!

代码

class Solution:
    def maxCoins(self, nums: List[int]) -> int:
        # 先给nums数组扩展边界
        nums.insert(0, 1)
        nums.insert(len(nums), 1)
        # 创建DP数组
        DP = [[0] * len(nums) for i in range(len(nums))]

        # 寻找最后戳破哪一个气球得到的硬币奖励最多
        def select_last_ball(i, j):
            # 定义(i, j)区间获得的硬币数
            ij_coin = 0
            # 因为是(i, j)开区间,所以从 i + 1 开始, j - 1结束
            for k in range(i + 1, j):
                # 除K之外, 左右两边获取的硬币奖励
                left = DP[i][k]
                right = DP[k][j]
                # (i, j)区间气球获得硬币奖励为左边区间气球 + 右边区间气球 + 第K个气球(最后扎破), 戳破第K个气球是,就只剩[i, j]区间就只剩第i, j, k 3个气球了
                temp = left + nums[i]*nums[k]*nums[j] + right
                # 比较然后取最大值
                if temp > ij_coin:
                    ij_coin = temp
            DP[i][j] = ij_coin

        #对每一个区间长度进行循环, n为[i, j]区间的长度
        for n in range(2,len(nums)): #因为区间内至少要有三个气球, 所以从最小长度3开始,所以n从2开始
            #开区间长度会从3一直到len(nums)
            #因为这里取的是range,所以最后一个数字是len(nums)-1
            #对于每一个区间长度,循环区间开头的i
            for i in range(0,len(nums)-n): #i+n = len(nums)-1

                #计算这个区间的最多金币
                select_last_ball(i,i+n)
        # 返回编号区间为[0, len(nums)]内的气球, 即题目所给的所有气球
        return DP[0][len(nums)-1]      

运行结果
insert image description here
总结

I personally feel that this question is very difficult. It combines dynamic programming and divide and conquer. Its DP array definition is difficult to find (I personally feel ha), and it is also difficult to consider. Assuming that all the balloons are punctured, only two borders are left. The idea of ​​a balloon and a balloon in the middle is the key to solving this problem. Get in touch~ Welcome everyone to learn and communicate together.

参考

https://leetcode-cn.com/problems/burst-balloons/solution/zhe-ge-cai-pu-zi-ji-zai-jia-ye-neng-zuo-guan-jian-/

Guess you like

Origin blog.csdn.net/Just_do_myself/article/details/118383554