leetcode 546 Remove Boxes

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 (composed of k boxes, k >= 1), remove them and get k*k points.
Find the maximum points you can get.

Example 1:
Input:

[1, 3, 2, 2, 2, 3, 4, 3, 1]

Output:

23

Explanation:

[1, 3, 2, 2, 2, 3, 4, 3, 1] 
----> [1, 3, 3, 4, 3, 1] (3*3=9 points) 
----> [1, 3, 3, 3, 1] (1*1=1 points) 
----> [1, 1] (3*3=9 points) 
----> [] (2*2=4 points)

解题思路:

这道题我一开始看着就觉得跟祖玛游戏这道题非常类似,所以并没有想他们之间的区别,直接上手写了递归。遍历所有相邻的数字,删除后继续递归。然后就TLE了 。

while(iti != boxes.end())
        {
            auto itj = iti ;
            while(itj != boxes.end() && *iti == *itj) itj++ ;
            
            vector<int> newbox = boxes ;
            int len = itj - iti ;
            auto newi = newbox.begin() + (iti - boxes.begin()) ;
            auto newj = newbox.begin() + (itj - boxes.begin()) ;
            newbox.erase(newi , newj) ;
            
            maxintg = max(maxintg , len * len + DFS(newbox)) ;
            
            iti = itj ;
        }

所以只能用动态规划的方法做,但是动态规划跟递归又不一样,比如[ i , j ]之间中的 [ p m ] 是相邻子串,但是删除这个子串后原有的下标失效 , 无法将[ i p) 和 (m j ]合并起来继续求解 。 所以在后面添一维的做法非常巧妙。比如[ i ][ j ][ k ] 中的 k 代表的是boxes[ j ] 后k个等于 boxes[ j ] 的元素 。

所以递推公式是:

case 1 :

         dp[ i ][ j ][ k ] = dp[ i ][ j - 1][ 0 ] + ( k + 1) * ( k + 1) ;

case 2 :

         对于[ i j ]中任一个等于boxes[j] 的元素 m

        dp[ i ][ j ][ k ] = dp[ i ][ m ][k + 1] + dp[m + 1 ][ j - 1][ 0 ] ;

 

优化: [i  j ]中并没有说 j 之前的元素和 boxes[j]是否相等 , 可以先将j之前与j相邻且等于boxes[j]的元素先加到k上,避免无谓的递归 。

class Solution {
public:
    int removeBoxes(vector<int>& boxes) 
    {
        int len = boxes.size() ;
        if(len == 0) return 0 ;
        
        dp = vector<vector<vector<int>>>(len , vector<vector<int>>(len , vector<int>(len , 0))) ;
        
        return DFS(boxes , 0 , len - 1 , 0) ;
    }
    
    int DFS(vector<int>& boxes , int l , int r , int k)
    {
        if(l > r) return 0 ;
        
        while(l < r && boxes[r - 1] == boxes[r]) 
        {
            r-- ;
            k++ ;
        }
        
        if(dp[l][r][k] > 0) return dp[l][r][k] ;
        
        dp[l][r][k] = (k + 1) * (k + 1) + DFS(boxes , l , r - 1 , 0) ;
        
        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] ;
    }
    
private :
    vector<vector<vector<int>>> dp ;
};

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值