​LeetCode刷题实战546:移除盒子

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 移除盒子,我们先来看题面:

https://leetcode-cn.com/problems/remove-boxes/

You are given several boxes with different colors represented by different positive numbers.

You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous boxes with the same color (i.e., composed of k boxes, k >= 1), remove them and get k * k points.

Return the maximum points you can get.

给出一些不同颜色的盒子 boxes ,盒子的颜色由不同的正数表示。

你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k * k 个积分。

返回 你能获得的最大积分和 。

示例                         

示例 1:

输入:boxes = [1,3,2,2,2,3,4,3,1]
输出:23
解释:
[1, 3, 2, 2, 2, 3, 4, 3, 1] 
----> [1, 3, 3, 4, 3, 1] (3*3=9 分) 
----> [1, 3, 3, 3, 1] (1*1=1 分) 
----> [1, 1] (3*3=9 分) 
----> [] (2*2=4 分)

示例 2:

输入:boxes = [1,1,1]
输出:9

示例 3:

输入:boxes = [1]
输出:1

解题

https://blog.csdn.net/weixin_44171872/article/details/106891504

方法1:动态规划

主要思路:

(1)三维动态数组dp[ i ][ j ][ k ]表示子元素组从 i到j 的右侧有 k 个连续的和boxes[ j ]相同的颜色;

(2)对于每一个dp[ i ][ j ],先从最右端找连续的相同的颜色,为k个,既dp[ i ][ j ][ k ],此时计算初值 dp[l][r][k]=dfs(boxes,l,r-1,0)+(k+1)*(k+1);既将最右侧的k+1个消去后,加上前面的可能的处理结果;

(3)然后从左端开始逐个找与右侧连续的箱子相同的颜色,既若boxes[i]==boxes[r],则相当于可以将原来的数组分成两组,既先将中间的从 i+1到r-1 的子数组作为一组先消去, 既 dfs(boxes,i+1,r-1,0),再将剩下的作为一个整体处理,既dfs(boxes,l,i,k+1),故此时dp[ i ][ j ][ k ]的值可以为dp[l][r][k]=dfs(boxes,l,i,k+1)+dfs(boxes,i+1,r-1,0);从l 到 l遍历重复 (3)中的过程,并和(2)中的结果结合,找出最大值;

class Solution {
public:
    //题意中最大100
    int dp[101][101][101];
    
    int dfs(vector<int>&boxes,int l,int r,int k){
      //终止条件
        if(l>r)
            return 0;
        //先找出当前的最右边的连续相同的箱子
        while(r>l&&boxes[r]==boxes[r-1]){
            --r;
            ++k;
        }
        //若之前计算过,直接返回
        if(dp[l][r][k]>0)
            return dp[l][r][k];
        //先计算(2)中的情况,既直接将最右边的相同的箱子消去
        dp[l][r][k]=dfs(boxes,l,r-1,0)+(k+1)*(k+1);
        
        //计算(3)中的情况,既在左边的数组中找出可以和右侧连续的箱子结合的情形
        for(int i=l;i<r;++i){
            if(boxes[i]==boxes[r]){
                dp[l][r][k]=max(dp[l][r][k],dfs(boxes,l,i,k+1)+dfs(boxes,i+1,r-1,0));
            }
        }
        //返回当前情形
        return dp[l][r][k];
    }
    
    int removeBoxes(vector<int>& boxes) {
        return dfs(boxes,0,boxes.size()-1,0);
    }
};

好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-540题汇总,希望对你有点帮助!

LeetCode刷题实战541:反转字符串 II

LeetCode刷题实战542:01 矩阵

LeetCode刷题实战543:二叉树的直径

LeetCode刷题实战544:输出比赛匹配对

LeetCode刷题实战545:二叉树的边界

6fa160c34fe9974e148520e134bd32b4.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值