给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。
你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k*k 个积分。
当你将所有盒子都去掉之后,求你能获得的最大积分和。
示例:
输入:boxes = [1,3,2,2,2,3,4,3,1]
输出:23
解释:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
----> [1, 3, 3, 4, 3, 1] (3*3=9 分)
----> [1, 3, 3, 3, 1] (1*1=1 分)
----> [1, 1] (3*3=9 分)
----> [] (2*2=4 分)
提示:
- 1 <= boxes.length <= 100
- 1 <= boxes[i] <= 100
解答
参考官方题解,使用动态规划,假设索引r
之后有k
个与boxes[r]
相同的颜色,则dp[l][r][k]
记录从索引l
到索引r
消除颜色,加上右侧k
个相同颜色带来的收益。
具体思路参考官方题解
class Solution {
public:
int dp[100][100][100];
int removeBoxes(vector<int>& boxes) {
memset(dp, 0, sizeof(dp));
return helper(boxes, 0, boxes.size()-1, 0);
}
int helper(vector<int>& boxes, int left, int right, int k){
if(left>right) return 0;
if(dp[left][right][k]!=0) return dp[left][right][k];
//连着的颜色肯定一起消除带来的收益高
while(left<right && boxes[right-1]==boxes[right]){
right--;
k++;
}
// l到r之间不先消除其他颜色以创造更长的连续块
dp[left][right][k] = helper(boxes, left, right-1, 0) + (k+1)*(k+1);
for(int i=left;i<right;i++){
if(boxes[i]==boxes[right]){
// l到r之间还有和r相同的颜色块,将两相同颜色块之间的先消除,创造更长颜色块
dp[left][right][k] = max(dp[left][right][k], helper(boxes, left, i, k+1) + helper(boxes, i+1, right-1, 0));
}
}
return dp[left][right][k];
}
};