Solution 讲解: leetcode 546. Remove Boxes
很巧妙的分析思路:T(i, j, k) 来表示 k个相同前缀,i-j 之间的最大值
自己写的 自底向上的 Bottom-Top
public class Solution {
public int removeBoxes(int[] boxes) {
int len = boxes.length;
if(len==0) return 0;
int[][][] dp = new int[len][len][len+1];
for(int inter=0;inter<len;inter++){
for(int i=0;i+inter<len;i++){
for(int k=0;k<len;k++){
int j = i+inter; //j>=i
// if j<i => 0
dp[i][j][k] = 0;
if(i==j) {
dp[i][j][k]=(k+1)*(k+1);
continue;
}
if(dp[i+1][j][0]+(k+1)*(k+1)>dp[i][j][k]){
dp[i][j][k] = dp[i+1][j][0]+(k+1)*(k+1);
}
for(int h=i+1;h<=j;h++){
if(boxes[h]==boxes[i]){
if(dp[i+1][h-1][0] + dp[h][j][k+1]>dp[i][j][k]){
dp[i][j][k] = dp[i+1][h-1][0] + dp[h][j][k+1];
}
}
}
}
}
}
return dp[0][len-1][0];
}
}
这一题很经典的dp题目,Solution给出如下的写法,也是dp常见的套路:
Top-Bottom:
public int removeBoxes(int[] boxes) {
int n = boxes.length;
int[][][] dp = new int[n][n][n];
return removeBoxesSub(boxes, 0, n - 1, 0, dp);
}
private int removeBoxesSub(int[] boxes, int i, int j, int k, int[][][] dp) {
if (i > j) return 0;
if (dp[i][j][k] > 0) return dp[i][j][k];
int res = (k + 1) * (k + 1) + removeBoxesSub(boxes, i + 1, j, 0, dp);
for (int m = i + 1; m <= j; m++) {
if (boxes[i] == boxes[m]) {
res = Math.max(res, removeBoxesSub(boxes, i + 1, m - 1, 0, dp) + removeBoxesSub(boxes, m, j, k + 1, dp));
}
}
dp[i][j][k] = res;
return res;
}
Bottom-Top:
public int removeBoxes(int[] boxes) {
int n = boxes.length;
int[][][] dp = new int[n][n][n];
for (int j = 0; j < n; j++) {
for (int k = 0; k <= j; k++) {
dp[j][j][k] = (k + 1) * (k + 1);
}
}
for (int l = 1; l < n; l++) {
for (int j = l; j < n; j++) {
int i = j - l;
for (int k = 0; k <= i; k++) {
int res = (k + 1) * (k + 1) + dp[i + 1][j][0];
for (int m = i + 1; m <= j; m++) {
if (boxes[m] == boxes[i]) {
res = Math.max(res, dp[i + 1][m - 1][0] + dp[m][j][k + 1]);
}
}
dp[i][j][k] = res;
}
}
}
return (n == 0 ? 0 : dp[0][n - 1][0]);
}