You are 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 (i.e., composed of k boxes, k >= 1), remove them and get k * k points.
This approach tries every possible way to remove boxes, always choosing the best option at each step. At each recursive call, we can remove a contiguous group of boxes of the same color, or skip and try other possibilities. The recursion explores all possible removal orders, which leads to a recursion tree.
If there are no boxes left, return 0. If only one box remains, return 1.
See the diagram below for more understanding:
---
title: boxes=[1,2,1]
---
graph TD
A([1,2,1])
A -.->|"max(3,5,3) = 5"| Z("Ans")
A -->|remove 1| B([2,1]):::remove1
A -->|remove 2| C([1,1]):::remove2
A -->|remove 1| D([1,2]):::remove1
B -->|remove 2| E([1]):::remove2
B -->|remove 1| F([2]):::remove1
D -->|remove 1| G([2]):::remove1
D -->|remove 2| H([1]):::remove2
E -->|remove 1| N1("null"):::remove1
N1 -.->|⏎ 1| E
E -.->|⏎ 1+1| B
B -.->|"⏎ max(2,2) + 1 = 3"| A
F -->|remove 2| N2("null"):::remove2
N2 -.->|⏎ 1| F
F -.->|⏎ 1+1| B
C -->|remove 1| N3("null"):::remove1
N3 -.->|⏎ 4| C
C -.->|⏎ 4 + 1| A
G -->|remove 2| N4("null"):::remove2
N4 -.->|⏎ 1| G
G -.->|⏎ 1+1| D
D -.->|"⏎ max(2,2) + 1 = 3"| A
H -->|remove 1| N5("null"):::remove1
N5 -.->|⏎ 1| H
H -.->|⏎ 1+1| D
classDef remove1 fill:#f9f,stroke:#333,stroke-width:2px;
classDef remove2 fill:#bbf,stroke:#333,stroke-width:2px;
classDef green fill:#44ff44,stroke:#333,stroke-width:2px;
classSolution {
publicintremoveBoxes(int[] boxes) {
return dfs(boxes);
}
privateintdfs(int[] boxes) {
if (boxes.length== 0) return 0;
int maxScore = 0, n = boxes.length;
for (int i = 0; i < n;) {
int j = i;
while (j < n && boxes[j]== boxes[i]) ++j;
int k = j - i;
int[] next =newint[i + n - j];
System.arraycopy(boxes, 0, next, 0, i);
System.arraycopy(boxes, j, next, i, n - j);
maxScore = Math.max(maxScore, dfs(next) + k * k);
i = j;
}
return maxScore;
}
}
classSolution {
funremoveBoxes(boxes: IntArray): Int {
fundfs(boxes: IntArray): Int {
if (boxes.isEmpty()) return0var maxScore = 0var i = 0val n = boxes.size
while (i < n) {
var j = i
while (j < n && boxes[j] == boxes[i]) j++val k = j - i
val next = boxes.sliceArray(0 until i) + boxes.sliceArray(j until n)
maxScore = maxOf(maxScore, dfs(next) + k * k)
i = j
}
return maxScore
}
return dfs(boxes)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defremoveBoxes(self, boxes: List[int]) -> int:
defdfs(boxes):
ifnot boxes:
return0 maxScore =0 n = len(boxes)
i =0while i < n:
j = i
while j < n and boxes[j] == boxes[i]:
j +=1 k = j - i
next_boxes = boxes[:i] + boxes[j:]
maxScore = max(maxScore, dfs(next_boxes) + k * k)
i = j
return maxScore
return dfs(boxes)
The naive recursion repeats many subproblems. By using memoization, we can cache results for each subarray and avoid redundant computation. The key is to define the DP state so that it captures all necessary information to solve the problem optimally.
classSolution {
funremoveBoxes(boxes: IntArray): Int {
val n = boxes.size
val dp = Array(n) { Array(n) { IntArray(n) } }
fundfs(l: Int, r: Int, k: Int): Int {
if (l > r) return0if (dp[l][r][k] !=0) return dp[l][r][k]
var rr = r
var kk = k
while (rr > l && boxes[rr] == boxes[rr - 1]) {
rr-- kk++ }
dp[l][rr][kk] = dfs(l, rr - 1, 0) + (kk + 1) * (kk + 1)
for (m in l until rr) {
if (boxes[m] == boxes[rr]) {
dp[l][rr][kk] = maxOf(dp[l][rr][kk], dfs(l, m, kk + 1) + dfs(m + 1, rr - 1, 0))
}
}
return dp[l][rr][kk]
}
return dfs(0, n - 1, 0)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution:
defremoveBoxes(self, boxes: List[int]) -> int:
from functools import lru_cache
@lru_cache(maxsize=None)
defdfs(l, r, k):
if l > r:
return0 orig_r, orig_k = r, k
while r > l and boxes[r] == boxes[r-1]:
r -=1 k +=1 res = dfs(l, r-1, 0) + (k+1)*(k+1)
for m in range(l, r):
if boxes[m] == boxes[r]:
res = max(res, dfs(l, m, k+1) + dfs(m+1, r-1, 0))
return res
return dfs(0, len(boxes)-1, 0)