数据结构-04-移除盒子

给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k*k 个积分。当你将所有盒子都去掉之后,求你能获得的最大积分和。                              

例如:

输入: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 分)                                     // 来源:力扣(LeetCode)/546

解决思路:

  1. 以官方解答例子为例,例如[6,3,6,5,6,7,6,6,8,6],盒子从最右侧看,第一种方法就是消除从最右侧开始,也就是从红色的6开始,消除和它相连的同类型盒子,第一轮后你会得到[6,3,6,5,6,7,6,6,8],第二轮后得到     [6,3,6,5,6,7,6,6],以此类推。
  2. 第二种方法还是从最右侧开始,,要消除阻碍它和同颜色盒子相连的盒子,也就是为了要让6盒子相连,需要除掉8盒子。

最后方法一和方法二对比,最大的就是题目所求的。

class Solution {
    public int removeBoxes(int[] boxes) {
        // 用于存储之前计算过的状态,避免重复计算
        int[][][] dp = new int[100][100][100];
        return cal(boxes, dp, 0, boxes.length - 1, 0);
    }
    
    public int cal(int[] boxes, int[][][] dp, int l, int r, int k) {
        if (l > r) {
            return 0;
        }
        if (dp[l][r][k] != 0) {
            return dp[l][r][k];
        }
        // 计算右边有几个跟最右边一个(boxes[r])相等, 如果相等则把右边界左移到不相同的元素之后一个为止,移动过程中同步改动k
        while (r > l && boxes[r] == boxes[r-1]) {
            r--;
            k++;
        }
        // 计算把右边k+1个消除时的得分
        dp[l][r][k] = cal(boxes, dp, l, r-1, 0) + (k+1)*(k+1);
        // 从右边界开始向左寻找跟外部k个元素相等的元素,如果相等则剔除掉这些不相等的,让后面一段连起来。
        // 此时得分就是中间消除中间一段不连续部分的得分和剩下来部分的得分
        // 比较这个得分和原来计算过其他方案的得分,去最大值覆盖到状态数组dp中
        for (int i = r-1; i >= l; --i) {
            if (boxes[i] == boxes[r]) {

//第一个cal计算剩下左面盒子的值,第二个计算已被除掉盒子的值
                dp[l][r][k] = Math.max(dp[l][r][k], cal(boxes, dp, l, i, k+1) + cal(boxes, dp, i+1, r-1, 0));

            }
        }
        return dp[l][r][k];
        
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值