leetcode 546. 移除盒子 区间dp

博客探讨了一个利用三维动态规划解决的问题,即在给定数组中删除连续重复元素,每次删除贡献平方值,目标是最大化总贡献。文章介绍了思路、转移方程和代码实现,特别强调了如何通过封锁元素构造最优解。最后,给出了求解全局最大贡献的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

link
题意:
每次可以删除连续的相同的数,删除k个贡献为k*k,问删完的最大贡献。
n<=100
思路:
一开始想到的是区间dp,但是二维不知道怎么转移,看了题解,只能说是太难想到了,三维 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]代表删除i~j并且i是最后一次删除,并且最后一次删了k个元素的最大值。最后答案就是 m a x k d p [ 0 ] [ n − 1 ] [ k ] max_{k}dp[0][n-1][k] maxkdp[0][n1][k],为什么这样一定能求出答案呢,有一个重要的性质是一定能构造出最后的解,因为某次删了k个相同的i,我们可以将它封锁,不去动他,放到最后再删除,也是等价的。因为他是前缀。,然后考虑考虑怎么转移,已经知道了最后一步操作的是i,那么不难想到枚举倒数第二次删除的是啥,dp方程就来了
d p [ i ] [ j ] [ k ] = g [ i + 1 ] [ u − 1 ] + k ∗ k − ( k − 1 ) ∗ ( k − 1 ) + g [ u ] [ j ] [ k − 1 ] dp[i][j][k]=g[i+1][u-1]+k*k-(k-1)*(k-1)+g[u][j][k-1] dp[i][j][k]=g[i+1][u1]+kk(k1)(k1)+g[u][j][k1]
这里的u是枚举在i和j之间的,同时需要满足color[u]==color[i]
g[i][j]代表所有i到j删除所有不同k的最大值。
最后答案就是g[0][n-1]
代码:

class Solution {
public:
    int removeBoxes(vector<int>& boxes) {
            int n=boxes.size();
            int INF=1e9;
            vector<vector<vector<int>>>dp(n,vector<vector<int>>(n,vector<int>(n+1,-INF)));
            vector<vector<int>>g(n*2,vector<int>(n,0));
            for(int len=1;len<=n;len++){
                for(int i=0;i+len-1<n;i++){
                    int j=i+len-1;
                    for(int k=1;k<=j-i+1;k++){
                        if(len==1){
                            dp[i][j][k]=1;
                        }
                        else if(k==1){
                            for(int t=1;t<=j-i;t++)
                            dp[i][j][k]=max(dp[i][j][k],dp[i+1][j][t]+1);
                        }
                        else {
                            for(int u=i+1;u<=j;u++){
                                if(boxes[u]==boxes[i])
                                dp[i][j][k]=max(dp[i][j][k],g[i+1][u-1]+k*k-(k-1)*(k-1)+dp[u][j][k-1]);
                            }
                        }
                        g[i][j]=max(g[i][j],dp[i][j][k]);
                    }
                }
            }

            return g[0][n-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值