DP-LeetCode546. 移除盒子(困难题:消消乐)

1、题目描述

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

给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。 你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 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 分)
  • 1 <= boxes.length <= 100
  • 1 <= boxes[i] <= 100

2、代码详解

定义

dp[i][j][k] 表示在 [i,j]部分能得到的最大得分

k表示boxes[i]左边有k个与之相等的数可以与它结合(可能原本有多余k个数,但是能和它合并一起消失的,只有k个)

举例

如...X DFD X DFDF X SDF [X LSKDFJ X LSJDFLK X DLKFJ...]

dp[i][j][k]表示只考虑[]部分对分数的贡献,那么第一个X可能跟着前面K个X消失,也可能等着后面的X一起消失

1. 跟前面的k个一起消失的话 

  • 得分为 (k+1)**2 + helper(i+1,j,0)

2.1 跟后面的第二个X一起消失的话,[]中的“LSKDFJ” 部分独立拿分,X成为第二个X开头的子序的前导之一 k->1+k

  • 得分为helper(i+1,m-1,0)+helper(m,j,1+k)  ,m此时是第二个X的序号

2.2 跟后面的第三个X一起消失的话,[]中的“LSKDFJ X LSJDFLK” 部分独立拿分,X成为第三个X开头的子序的前导之一 k->1+k

  • 得分还是helper(i+1,m-1,0)+helper(m,j,1+k)  ,m此时是第三个X的序号

2.3 至于“LSKDFJ”与“LSJDFLK”部分分别独立拿分,再合并k+3个X拿分的情况,包含于2.1情况中

    因为helper(m,j,1+k) 可以递归,下一层的2.1情况就是前K个与第一个X第二个X和第三个X合并

    所以只用考虑[]中第一个X与第Y个X直接合并,中间部分作为子区间独立拿分的情况

几种情况取最高得分,并存入dp[i][j][k]

class Solution(object):
    def removeBoxes(self, boxes):
        """
        :type boxes: List[int]
        :rtype: int
        """
        n = len(boxes)
        dp = [[[0] * n for _ in range(n)] for _ in range(n)]

        # dp[i][j][k] 表示在 [i,j]部分能得到的最大得分
        # k表示boxes[i]左边有k个与之相等的数可以与它结合(可能原本有多余k个数,但是能和它合并一起消失的,只有k个)

        def helper(i, j, k):
            if i > j:
                return 0

            if dp[i][j][k] != 0:
                return dp[i][j][k]

            # 大段连续的部分肯定是放一起消失得分高,而不是单个消失
            while i < j and boxes[i] == boxes[i + 1]:
                i += 1
                k += 1

            res = (k + 1) ** 2 + helper(i + 1, j, 0)

            for m in range(i + 1, j + 1):
                if boxes[m] == boxes[i]:
                    res = max(res, helper(i + 1, m - 1, 0) + helper(m, j, 1 + k))

            dp[i][j][k] = res
            return dp[i][j][k]

        return helper(0, n - 1, 0)

 

动画理解

https://leetcode-cn.com/problems/remove-boxes/solution/guan-fang-fang-fa-2ji-yi-hua-sou-suo-dong-hua-tu-j/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值