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.
// Top-Down Dynamic Programming
// int helper(vector<int>& boxes, int i, int j, int k, int dp[100][100][100]) {
int helper(vector<int>& boxes, int i, int j, int k, vector<vector<vector<int> > >& dp) {
if (i > j) return 0;
if (dp[i][j][k] > 0) return dp[i][j][k];
// Optimization: all boxes of the same color counted continuously from the first box should be grouped together
for ( ; i + 1 <= j && boxes[i + 1] == boxes[i]; i++, k++);
int res = (1 + k) * (1 + k) + helper(boxes, i + 1, j, 0, dp); // remove the i-th box
for (int m = i + 1; m <= j; ++m) {
if (boxes[m] == boxes[i]) {
// max(T(i + 1, m - 1, 0) + T(m, j, k + 1)), i < m <= j && boxes[i] == boxes[m]
res = max(res, helper(boxes, i + 1, m - 1, 0, dp) + helper(boxes, m, j, k + 1, dp));
}
}
return dp[i][j][k] = res;
}
int removeBoxes(vector<int>& boxes) { // time: O(n^4); space: O(n^3)
int n = boxes.size();
// int dp[100][100][100] = {0};
vector<vector<vector<int> > > dp(n, vector<vector<int> >(n, vector<int>(n, 0)));
return helper(boxes, 0, n - 1, 0, dp);
}
// Bottom-Up Dynamic Programming
int removeBoxes(vector<int>& boxes) { // time: O(n^4); space: O(n^3)
if (boxes.empty()) return 0;
int n = boxes.size();
// int dp[n][n][n] = {0};
vector<vector<vector<int> > > dp(n, vector<vector<int> >(n, vector<int>(n, 0)));
// Initialization
for (int i = 0; i < n; ++i) {
for (int k = 0; k <= i; ++k) {
dp[i][i][k] = (1 + k) * (1 + k);
}
}
for (int l = 1; l < n; ++l) { // range length
for (int j = l; j < n; ++j) { // right bound
int i = j - l; // left bound
for (int k = 0; k <= i; ++k) {
// start from removal of the i-th box
int res = (1 + k) * (1 + k) + dp[i + 1][j][0];
for (int m = i + 1; m <= j; ++m) {
if (boxes[m] == boxes[i]) {
res = max(res, dp[i + 1][m - 1][0] + dp[m][j][k + 1]);
}
}
dp[i][j][k] = res;
}
}
}
return dp[0][n - 1][0];
}