leetcode546. Remove box/dynamic programming

Subject: 546. Remove the box

Given some boxes of different colors, the colors of the boxes are represented by numbers, that is, different numbers represent different colors.
You will go through several rounds of operations to remove the boxes until all the boxes are removed. In each round you can remove k consecutive boxes with the same color (k >= 1), so you will get k*k points after one round.
After you remove all the boxes, find the maximum sum of points you can get.

Example:

输入: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)

prompt:

  • 1 <= boxes.length <= 100
  • 1 <= boxes[i] <= 100

Source: LeetCode
Link: https://leetcode-cn.com/problems/remove-boxes
Copyright is owned by LeetCode . For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Basic idea 1: Dynamic programming

  • dp[l][r][k]: Represents the maximum result obtained when removing the interval [l, r] plus k elements that are equal to the right and right endpoints of the interval (ie boxes[r])
  • Traverse every combination of elements with the right endpoint, and take the maximum value
  • The final result is stored in dp[0][boxes.size()-1][0]

To say a little more:
The idea of ​​this dynamic programming is different from the idea of ​​dfs below. DFS is the maximum value of the final result obtained by traversing all the situations, while dynamic programming is to find the elements that can be connected with the current interval and the right endpoint to delete together .

class Solution {
    
    
public:
    int dp[100][100][100];
    int removeBoxes(vector<int>& boxes) {
    
    
        memset(dp, 0, sizeof dp);
        return fun(boxes, 0, boxes.size() - 1, 0);
    }
    int fun(vector<int>& boxes, int l, int r, int k){
    
    
        if(l > r)
            return 0;
        if(dp[l][r][k])
            return dp[l][r][k];
        while(l < r && boxes[r] == boxes[r - 1]){
    
    //当右端点左面的元素和右端点相等时,尽可能的将右端点左移,使得相同元素的长度最长
            --r;
            ++k;
        }
        dp[l][r][k] = fun(boxes, l, r - 1, 0) + (k + 1) * (k + 1);
        //右端点左面和右端点相等组成连续序列的情况
        for(int i = l; i < r; ++i){
    
    
            if(boxes[i] == boxes[r]){
    
    
                dp[l][r][k] = max(dp[l][r][k], fun(boxes, l, i, k + 1) + fun(boxes, i + 1, r - 1, 0));
            }
        }
        return dp[l][r][k];
    }
};

Basic idea 2: dfs (timed out)

Traverse every possibility, the result timed out

class Solution {
    
    
public:
    struct Node{
    
    
        int val, cnt;
        Node(int a, int b): val(a), cnt(b){
    
    }
    };
    int removeBoxes(vector<int>& boxes) {
    
    
        if(boxes.size() == 0)
            return 0;
        vector<Node> nums;
        nums.push_back(Node(boxes[0], 1));
        for(int i = 1; i < boxes.size(); ++i){
    
    
            if(boxes[i] == nums.back().val)
                nums.back().cnt++;
            else
                nums.push_back(Node(boxes[i], 1));
        }
        int res = 0;
        dfs(nums, res, 0);
        return res;
    }
    void dfs(vector<Node> &nums, int &res, int cur){
    
    
        //cout << cur << endl;
        if(nums.size() == 0){
    
    
            res = max(res, cur);
            
            return;
        }
        for(int i = 0; i < nums.size(); ++i){
    
    
            auto nums_copy = nums;
            int c = nums[i].cnt;
            
            if(i > 0 && i + 1 < nums.size() && nums[i - 1].val == nums[i + 1].val){
    
    
                nums[i - 1].cnt += nums[i + 1].cnt;
                nums.erase(nums.begin() + i, nums.begin() + i + 2);
            }
            else
                nums.erase(nums.begin() + i);
            
            dfs(nums, res, cur + c * c);
            
            nums = nums_copy;
        }
    }
};

Guess you like

Origin blog.csdn.net/qq_31672701/article/details/108023256