leetcode546. 移除盒子/动态规划

文章目录

    • 题目:546. 移除盒子
    • 基本思想1:动态规划
    • 基本思想2:dfs(超时了)

题目:546. 移除盒子

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-boxes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

基本思想1:动态规划

  • dp[l][r][k]:表示移除区间[l, r]加上区间右边和右端点(即boxes[r])相等的k个元素时,得到的最大结果
  • 遍历每一种和右端点元素合并的情况,取其中的最大值
  • 最终结果保存在dp[0][boxes.size() - 1][0]中

多说一点:
这个动态规划的思想和下面的dfs的思想不同,dfs是遍历所有的情况得到最终结果的最大值,而动态规划是寻找能和当前区间以及和右端点连成一片的元素一起删除。

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];
    }
};

基本思想2:dfs(超时了)

遍历每一种可能,结果超时了

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;
        }
    }
};

你可能感兴趣的:(#,算法)