Leetcode546. Remove Boxes(Hard)

题目

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
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)

Note: The number of boxes n would not exceed 100.

分析

题目的意思大概是:
给定一个数组表示一列箱子,不同的值表示箱子不同的颜色,移除箱子可以获得相应的分数,每次都可以选择连续的具有相同颜色的箱子,假设移除了k个连续的相同颜色的箱子,可以获得k * k的分数,k大于等于1。
最后求可以获得的最大分数。

通过用 dp[i][j][k] 来表示通过移除boxes[i, j]中的箱子,且此时在boxes[i]前有k个箱子的颜色与boxes[i]的颜色相同时,可以获得的最大分数。
此时,可以假设boxes数组的长度是n,可以将结果表示为:

dp[0][n - 1][0]

而且此时有如下的一些初始状态:

dp[i][i][k] = (k + 1) * (k + 1)

dp[i][j][k] = 0;    //i < j

考虑一般的情况,对于 dp[i][j][k] 而言,考虑如何将其分解成子问题,以通过递推来求解。
上面说到,dp[i][j][k] 表示的是通过移除boxes[i, j]中的箱子,且此时在boxes[i]前面有k个与boxes[i]颜色相同的箱子。因此,对于第i个箱子,如果将其和前面的k个箱子一起移除,那么此时可以获得的分数,可以表示为:

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

同时对于第i个箱子,还有其他的方案来移除,即可以将boxes[i, j]中的某一个箱子一起移除,这个箱子可以表示为boxes[m],此时boxes[m] == boxes[i]。此时可以获得的分数,可以表示为:

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

而此时的 dp[i][j][k] 就是这些情况下可以取得的最大值。
因此可以写出状态转移方程如下:

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

temp2 = max(dp[i + 1][m - 1][0] + dp[m][j][k + 1])  //i <= m <= j && boxes[m] == boxes[i]

dp[i][j][k] = max(temp1, temp2)

代码:

通过递归和记忆化(搜索)来实现

class Solution {
public:
    int removeBoxes(vector<int>& boxes) {
        int n = boxes.size();
        vector<int> temp1(n, 0);
        vector<vector<int>> temp2(n, temp1);
        vector<vector<vector<int>>> dp(n, temp2);
        return removeBoxesHelp(boxes, 0, n - 1, 0, dp);
    }

    int removeBoxesHelp(vector<int>& boxes, int i, int j, int k, vector<vector<vector<int>>>& dp) {
        if (i > j) return 0;
        if (dp[i][j][k] > 0) return dp[i][j][k];

        int result = (k + 1) * (k + 1) + removeBoxesHelp(boxes, i + 1, j, 0, dp);

        for (int t = i + 1; t <= j; t++) {
            if (boxes[i] == boxes[t]) {
                result = max(result, removeBoxesHelp(boxes, i + 1, t - 1, 0, dp) + removeBoxesHelp(boxes, t, j, k + 1, dp));
            }
        }

        dp[i][j][k] = result;
        return result;
    }
};

运行结果:

Leetcode546. Remove Boxes(Hard)_第1张图片

你可能感兴趣的:(Leetcode)