【leetcode】546 移除盒子(动态规划)

题目链接:https://leetcode-cn.com/problems/remove-boxes/

题目描述

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

提示:盒子的总数 n 不会超过 100。

思路

// 记忆化
class Solution {
public:
    int removeBoxes(vector<int>& boxes) {
        int n=boxes.size();
        int memo[100][100][100] = {0};
        return dfs(boxes,memo,0,n-1,0);
    }
    // memo[l][r][k]表示在序列l~r部分后接k长度的r值序列最大得分
    // memo[l][r][3]代表[b_l, ..., b_r, A,A,A]其中b_r == A
    int dfs(vector<int>& boxes,int memo[100][100][100], int l,int r,int k){
        if (l>r) return 0;
        if (memo[l][r][k]!=0) return memo[l][r][k];

        while (r>l && boxes[r]==boxes[r-1]) {r--;k++;}
        memo[l][r][k] = dfs(boxes,memo,l,r-1,0) + (k+1)*(k+1);
        for (int i=l; i<r; i++){
            if (boxes[i]==boxes[r]){
                // 将分成两部分[b_l, ..., b_i, b_r, A, ..., A]和[b_{i+1}, ..., b_{r-1}],相当于先计算后者,然后计算整体
                memo[l][r][k] = max(memo[l][r][k], dfs(boxes,memo,l,i,k+1) + dfs(boxes,memo,i+1,r-1,0));
            }
        }
        return memo[l][r][k];
    }
};

你可能感兴趣的:(LeetCode)