leetcode 546. 移除盒子 区间dp
Posted goto_1600
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 546. 移除盒子 区间dp相关的知识,希望对你有一定的参考价值。
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][n−1][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][u−1]+k∗k−(k−1)∗(k−1)+g[u][j][k−1]
这里的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];
}
};
以上是关于leetcode 546. 移除盒子 区间dp的主要内容,如果未能解决你的问题,请参考以下文章