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 1:
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)
整体思路类似于分治和记忆化存储
三维dp,直接看下面这种情况:
1 2 3 4 2 2
用dp[i][j][k] 存储可获得的最大分数,其中i是左边界,j是又边界,k是和右边界相等的后缀长度。上面例子如下:
1 2 3 4 2 2
i j 即dp[i][j][1]
对于当前左右边界和相应的k值,可以对右边界后k个元素进行merge操作得分:
dfs(boxes, mem, l, r - 1, 0 ) + (k + 1) * (k + 1);
也可以不merge,从左往右如果找到一个值和box[r]相等则将原数组分为两部分求值:
1 2 2 2 左右两部分合并
i j dp[i][j][2]
3 4 中间的部分
i j dp[i][j][0]
Math.max(mem[l][r][k], dfs(boxes, mem, l, i, k + 1) + dfs(boxes, mem, i + 1, r - 1, 0));
最后代码如下:
public class Solution {
public int removeBoxes(int[] boxes) {
int size = boxes.length;
int[][][] mem = new int[size][size][size];
return dfs(boxes, mem, 0, size - 1, 0);
}
private int dfs(int[] boxes, int[][][] mem, int l, int r, int k) {
if (l > r) return 0;
if (mem[l][r][k] > 0) return mem[l][r][k];
while (r > l && boxes[r] == boxes[r - 1]) {
r--;
k++;
}
mem[l][r][k] = dfs(boxes, mem, l, r - 1, 0 ) + (k + 1) * (k + 1);
for (int i = l; i < r; i++) {
if (boxes[i] == boxes[r]) {
mem[l][r][k] = Math.max(mem[l][r][k], dfs(boxes, mem, l, i, k + 1) + dfs(boxes, mem, i + 1, r - 1, 0));
}
}
return mem[l][r][k];
}
}