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 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& boxes) 
    {
        int len = boxes.size() ;
        if(len == 0) return 0 ;
        
        dp = vector>>(len , vector>(len , vector(len , 0))) ;
        
        return DFS(boxes , 0 , len - 1 , 0) ;
    }
    
    int DFS(vector& 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>> dp ;
};

 

 

你可能感兴趣的:(leetcode,动态规划,深度优先搜索)