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

运行结果:

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值