LeetCode 546. 移除盒子 Python

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

示例 1:
输入:

[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 分)

思路:

涉及子串的动态规划一般从子串两端进行递推,即(i,j)子串。 
分析如下: 
dp[i][j][k]表示从i到j子串并且右端存在与j相同的k个字符其获得的最大点数。 
有1,3,2,2,2,3,3 
    i                          j                                   dp[i][j][1]        
此时有两种可选操作: 
1、将j以及其后面的连续相同的串消除获得点数:dp[i][j-1][0]+(k+1)*(k+1) 
      1,3,2,2,2,4,3,1  ——>  dp[i][j][0]+2*2 
2、在子串内部寻找与右端相同的字符,将子串划分成两部分,先消除内部,再消除右端:dp[i][p][k+1]+dp[p+1][j-1][0] 
      1,3,3,1  ——>  dp[i][p][k+1] 
      2,2,2,4  ——>  dp[p+1][j-1][0] 
dp[i][j][k]最大值为上面两种情况的最大值,代码如下

Python版:

class Solution:
    def removeBoxes(self, boxes):
        """
        :type boxes: List[int]
        :rtype: int
        """
        #涉及子串动态规划利用(i,j)进行地推   dp[i][j][k]表示从i到j子串并且右端存在与j相同的k个字符其获得的最大点数。
        n = len(boxes)
        dp = [[[0]*n for _ in range(n)]for _ in range(n)]
        return self.robot(boxes,dp,0,n-1,0)
    
    def robot(self,boxes,dp,x,y,k):
        if x > y:
            return 0
        if dp[x][y][k] > 0:
            return dp[x][y][k]
        while x < y and boxes[y] == boxes[y-1]:
            y -= 1
            k += 1
            
        dp[x][y][k] = self.robot(boxes,dp,x,y-1,0) + (k+1)*(k+1)
        for i in range(x,y):
            if boxes[i] == boxes[y]:
                dp[x][y][k] = max(dp[x][y][k],self.robot(boxes,dp,x,i,k+1) + self.robot(boxes,dp,i+1,y-1,0))
        return dp[x][y][k]

 

你可能感兴趣的:(LeetCode 546. 移除盒子 Python)