【动态规划】LeetCode 312. 戳气球 --区间DP问题

简介: 因为一些事,最近状态不是很好,加上今天的每日一题有点难,看的烦躁(就是菜 ,就来更新一下今天与每日一题相关的区间Dp问题(戳气球),这篇也是关于区间Dp的问题 uu可以看看

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法......感兴趣就关注我吧!你定不会失望。


🌈个人主页:主页链接


🌈算法专栏:专栏链接


    我会一直往里填充内容哒!


🌈LeetCode专栏:专栏链接


目前在刷初级算法的LeetBook 。若每日一题当中有力所能及的题目,也会当天做完发出


🌈代码仓库:Gitee链接


🌈点击关注=收获更多优质内容🌈


06ac5f86561e4df6a13877f8b195804a.jpg


因为一些事,最近状态不是很好,加上今天的每日一题有点难,看的烦躁(就是菜 ,就来更新一下今天与每日一题相关的区间Dp问题(戳气球),这篇也是关于区间Dp的问题 uu可以看看

话不多说,开始!


题目:戳气球


65b532e902e446e7af26f70a892059a8.png


题解:


这道题虽然被标为了Hard但依据Dp的特点,知道其中缘由之后也没有很难了.先来看看问题


有这样几个气球.我们要求出戳出他之后他掉落的最大金币数


4b5db2faaa8941b1a89dc55f6ef20541.jpg


例如,在戳掉1,则掉落的金币数为周围两个金币数相乘,再乘上被戳掉的气球的金币数


在思考dp问题的时候,我们需要将每一个子问题划分为不受周围影响的独立的子问题,所以观察我们刚刚的计算过程.我们发现,掉落的金币数与i j是有关系的

题目提到:如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。


为了避免越界问题,那我们可以设定两个虚拟气球,他们得分都为1,这样可以将dp的子问题划分为

dp[i][j]的含义为:在i-1到j-1当中,戳破气球获得的最高分.

根据区间dp倒着推问题的特点:我们可以想想在i j当中,最后一个被戳爆的气球是哪一个.

其实每一个气球都能成为最后被戳破的那个,所以我们要做的就是在一定区间内去寻找,戳破这个气球,能获得最大收益的k值

d5eb1d744bba436ca7a13c9abf095a1f.jpg


若想要最后一个戳破k,则需要先将i-k的气球戳破,再将k-j的气球戳破,之后再将结果加上戳破k区间的值即可(注意k是最后一个戳爆的!!他的周围是没有球的,所以这就是为什么是独立的子问题的原因)


dp[i][j]=dp[i][k]+dp[k][j]+val[i]*val[j]*val[k]

观察发现,这是从小范围去推大范围,所以在计算大范围的时候,小范围一定是被准备好了.

所以从只有三个气球的区间开始计算,慢慢拓展到大的区间.存储每个区间可以获得的最大金币,留给之后计算


先看看Base Case是什么,当i j重合的时候,没有东西可以戳,此时得分为0


84b34bb4f6f0475fab5d5e7126c1f608.jpg


当我们计算任何一个Dp[i][j]的时候,我们希望dp[i][k] 与dp[k][j]都已经被计算出来了

2652f29104f44831850903b8b156c0c3.jpg

所以我们一般采用,自底向上的遍历方法.

相关模板:


for(int i=n;i>=0;i--)
    {
        for(int j=i+1;j<n;j++)
        {
            for(int k=i+1;k<j;k++)
            {
                ..........
            }
        }
    }


也就是i从n开始到0结束,j从i+1开始小于n(这里的n是指不能取到额外给的那两个气球),而k介于这二者之间 ,为了避免越界问题,我们一般采用n+2的方法


代码实现:


#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution {
public:
    int maxCoins(vector<int>& nums) {
        vector<int>val(nums.size()+2);
        val[0]=val[val.size()-1]=1;
        for(int i=1;i<=nums.size();i++)
        {
            val[i]=nums[i-1];
        }
        vector<vector<int>>dp(val.size(),vector<int>(val.size()));
        for(int i=val.size();i>=0;i--)
        {
            for(int j=i+1;j<val.size();j++)
            {
                for(int k=i+1;k<j;k++)
                {
                    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]+val[i]*val[j]*val[k]);
                }
            }
        }
        return dp[0][val.size()-1];
    }
};


完结撒花:


🌈本篇博客的内容【LeetCode 312. 戳气球 --区间DP问题】已经结束。

🌈若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。


🌈若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询问。


🌈诸君,山顶见!

目录
相关文章
|
2天前
leetcode代码记录(动态规划基础题(斐波那契数列)
leetcode代码记录(动态规划基础题(斐波那契数列)
8 0
|
2天前
[leetcode~数位动态规划] 2719. 统计整数数目 hard
[leetcode~数位动态规划] 2719. 统计整数数目 hard
|
2天前
|
算法
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
代码随想录算法训练营第五十六天 | LeetCode 647. 回文子串、516. 最长回文子序列、动态规划总结
34 1
|
2天前
|
JavaScript
【leetcode】221--最大正方形-动态规划法
【leetcode】221--最大正方形-动态规划法
10 0
|
2天前
|
JavaScript
【leetcode】221. 最大正方形 动态规划法
【leetcode】221. 最大正方形 动态规划法
12 0
|
2天前
|
Go C++
【力扣】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)
【2月更文挑战第17天】2645. 构造有效字符串的最小插入数(动态规划 贪心 滚动数组优化 C++ Go)
32 8
|
2天前
动态规划之解码方法【LeetCode】
动态规划之解码方法【LeetCode】
|
2天前
动态规划之使用最小花费爬楼梯【LeetCode】
动态规划之使用最小花费爬楼梯【LeetCode】
|
2天前
|
算法
动态规划之第 N 个泰波那契数/三步问题【leetCode】【算法】
动态规划之第 N 个泰波那契数/三步问题【leetCode】【算法】
|
2天前
|
机器学习/深度学习 人工智能 测试技术
【动态规划】【矩阵快速幂】LeetCode2851. 字符串转换
【动态规划】【矩阵快速幂】LeetCode2851. 字符串转换