You are given a list of cuboids
, where each cuboid is represented by a list of three integers: [width, length, height]
. You can stack cuboids on top of each other to form a tower, but you must follow these rules:
A
on top of cuboid B
only if the width, length, and height of A
are each less than or equal to those of B
(i.e., A
fits on B
).Your task is to return the maximum possible height of a stack that can be formed by stacking some or all of the cuboids.
Key constraints: Each cuboid can be rotated, but can be used only once. You must determine the optimal order (and orientation) to maximize the total height.
At first glance, it seems like a brute-force approach would be to try all possible combinations and rotations of cuboids, checking which ones can be stacked and keeping track of the tallest possible tower. But with up to 100 cuboids and 6 possible rotations for each, this quickly becomes infeasible.
To optimize, we need to:
This shift from brute-force to dynamic programming is the key insight for an efficient solution.
Here’s a step-by-step breakdown of the optimal approach:
width ≤ length ≤ height
. This way, rotation is handled, and we only need to consider one orientation per cuboid.dp[i]
represent the maximum height of a stack ending with cuboid i
at the top.dp[i]
as the height of cuboid i
itself.i
, look at all cuboids j
before it (i.e., j < i
), and if cuboid i
can be placed on j
(all dimensions of i
≤ j
), update dp[i]
as max(dp[i], dp[j] + height of i)
.dp
array.This approach ensures we efficiently consider all valid stacking orders and orientations.
Sample Input:
cuboids = [[50,45,20], [95,37,53], [45,23,12]]
This example shows how the DP array is built up and how the tallest stack is found.
The optimized approach is efficient and feasible for the input constraints.
To solve the "Maximum Height by Stacking Cuboids" problem, we:
The elegance of this solution lies in reducing a seemingly complex 3D stacking problem to a variant of the Longest Increasing Subsequence, making it both efficient and easy to implement.
class Solution:
def maxHeight(self, cuboids):
# Step 1: Normalize all cuboids by sorting their dimensions
for cuboid in cuboids:
cuboid.sort()
# Step 2: Sort cuboids in non-decreasing order
cuboids.sort()
n = len(cuboids)
dp = [0] * n
for i in range(n):
dp[i] = cuboids[i][2] # height after sorting
for j in range(i):
if (cuboids[j][0] <= cuboids[i][0] and
cuboids[j][1] <= cuboids[i][1] and
cuboids[j][2] <= cuboids[i][2]):
dp[i] = max(dp[i], dp[j] + cuboids[i][2])
return max(dp)
class Solution {
public:
int maxHeight(vector<vector<int>>& cuboids) {
for (auto& c : cuboids) sort(c.begin(), c.end());
sort(cuboids.begin(), cuboids.end());
int n = cuboids.size();
vector<int> dp(n, 0);
int res = 0;
for (int i = 0; i < n; ++i) {
dp[i] = cuboids[i][2];
for (int j = 0; j < i; ++j) {
if (cuboids[j][0] <= cuboids[i][0] &&
cuboids[j][1] <= cuboids[i][1] &&
cuboids[j][2] <= cuboids[i][2]) {
dp[i] = max(dp[i], dp[j] + cuboids[i][2]);
}
}
res = max(res, dp[i]);
}
return res;
}
};
class Solution {
public int maxHeight(int[][] cuboids) {
for (int[] c : cuboids) Arrays.sort(c);
Arrays.sort(cuboids, (a, b) -> {
if (a[0] != b[0]) return a[0] - b[0];
if (a[1] != b[1]) return a[1] - b[1];
return a[2] - b[2];
});
int n = cuboids.length;
int[] dp = new int[n];
int res = 0;
for (int i = 0; i < n; ++i) {
dp[i] = cuboids[i][2];
for (int j = 0; j < i; ++j) {
if (cuboids[j][0] <= cuboids[i][0] &&
cuboids[j][1] <= cuboids[i][1] &&
cuboids[j][2] <= cuboids[i][2]) {
dp[i] = Math.max(dp[i], dp[j] + cuboids[i][2]);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
}
var maxHeight = function(cuboids) {
cuboids.forEach(c => c.sort((a, b) => a - b));
cuboids.sort((a, b) => {
if (a[0] !== b[0]) return a[0] - b[0];
if (a[1] !== b[1]) return a[1] - b[1];
return a[2] - b[2];
});
let n = cuboids.length;
let dp = new Array(n).fill(0);
let res = 0;
for (let i = 0; i < n; ++i) {
dp[i] = cuboids[i][2];
for (let j = 0; j < i; ++j) {
if (cuboids[j][0] <= cuboids[i][0] &&
cuboids[j][1] <= cuboids[i][1] &&
cuboids[j][2] <= cuboids[i][2]) {
dp[i] = Math.max(dp[i], dp[j] + cuboids[i][2]);
}
}
res = Math.max(res, dp[i]);
}
return res;
};