Leetcode 546 - Remove Boxes(区间dp)

66 篇文章 0 订阅

题意

有一行方块,每个方块有颜色,现在可以把相邻的k个并且颜色相同的方块消除,得分为 kk ,求最大得分。

思路

首先,做一步预处理优化时间:将相邻并且颜色相同的方块合并成段,用 c[i] len[i] 分别记录这个段的颜色和里面的方块数目。于是以下的操作都是针对段进行。

状态表示 d[i,j,k] ,区间 [i,j] 内,并且 j 段之后还有k个颜色和第 j 段相同的方块,能得到的最大得分。

转移方程

j段直接和后面的 k 个合并:

d[i,j,k]=d[i,j1,0]+(len[j]+k)2

继续积累第 j 段(将j段和 k 积累到前面某一段),之后再合并(即在[i,j]之间找颜色和 j 段相同的):

d[i,j,k]=d[i,pos,len[j]+k]+d[pos+1,j1,0]c[pos]==c[j]ipos<j

时间复杂度 O(n4)

代码

const int maxn = 105;
int d[maxn][maxn][maxn];

class Solution {
private:
    int c[maxn], len[maxn];
public:
    int dfs(int i, int j, int k) {
        if (d[i][j][k] != -1) return d[i][j][k];
        if (i > j) return 0;
        d[i][j][k] = dfs(i, j - 1, 0) + (len[j] + k) * (len[j] + k);
        for (int pos = i; pos < j; pos++) {
            if (c[pos] == c[j]) d[i][j][k] = max(d[i][j][k], dfs(i, pos, len[j] + k) + dfs(pos + 1, j - 1, 0));
        }
        return d[i][j][k];
    }

    int removeBoxes(vector<int>& boxes) {
        int n = 0;
        memset(c, 0, sizeof(c));
        memset(len, 0, sizeof(len));
        memset(d, -1, sizeof(d));
        for (int i = 0; i < boxes.size(); i++) {
            if (i == 0 || boxes[i] != boxes[i - 1]) c[++n] = boxes[i], len[n] = 1;
            else len[n]++;
        }
        return dfs(1, n, 0);
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值