Stack of Boxes:给定n
个箱子,宽度、高度和深度分别为w[i]
、d[i]
和h[i]
,求将这些箱子摞起来后的最大高度,要求下面箱子的宽深高均大于上面箱子的宽深高。
可以先根据任意的一个维度进行降序排序,然后计算每一个箱子在最底部时的最大高度。如果不进行优化,会出现很多的重复计算,所以需要记录每个箱子在最底部的最大高度,并设定边界条件MaxHeight[0] = Boxes[0].height
。
struct Box
{
int width, depth, height;
public:
Box(int w, int d, int h)
: width(w), depth(d), height(h){}
bool above(const Box &bottom)
{
return width < bottom.width && depth < bottom.depth && height < bottom.height;
}
};
bool operator<(const Box &b1, const Box &b2)
{
return b1.width < b2.width;
}
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
convertBox(box);
sort(Boxes.begin(), Boxes.end());
MaxHeight.assign(Boxes.size(), 0);
MaxHeight[0] = Boxes[0].height;
int maxHeight = 0, height;
for(size_t btm = Boxes.size(); btm > 0; btm--)
{
height = pileBox(btm - 1);
maxHeight = height > maxHeight ? height : maxHeight;
}
return maxHeight;
}
private:
vector<Box> Boxes;
vector<int> MaxHeight;
int pileBox(const size_t btmIdx)
{
if(MaxHeight[btmIdx] != 0) return MaxHeight[btmIdx];
int maxHeight = 0, height;
for(size_t btm = btmIdx; btm > 0; btm--)
{
if(Boxes[btm - 1].above(Boxes[btmIdx])){
height = pileBox(btm - 1);
maxHeight = height > maxHeight ? height : maxHeight;
}
}
maxHeight += Boxes[btmIdx].height;
MaxHeight[btmIdx] = maxHeight;
return maxHeight;
}
void convertBox(const vector<vector<int>> &box)
{
for(size_t i = 0; i < box.size(); i++)
{
Boxes.push_back(Box(box[i][0], box[i][1], box[i][2]));
}
}
};
也可以把摞的过程看做是对每个箱子做一个决策,每个箱子有两种选择,是否出现在结果序列中,如果出现,则考虑下一个箱子时需要使用新的newTop
;否则使用旧的top
。
代码中的curr
为无符号整型,小于0
后会自动回绕,所以0
要单独判断,第0
个箱子可以摞上去时,因为初始化了maxHeight[0]
,所以可以按照正常逻辑进行判断,所以只在计算withoutHeight
时进行了判断。
struct Box
{
int width, depth, height;
public:
Box(int w, int d, int h)
: width(w), depth(d), height(h){}
bool above(const Box &bottom)
{
return width < bottom.width && depth < bottom.depth && height < bottom.height;
}
};
bool operator<(const Box &b1, const Box &b2)
{
return b1.width < b2.width;
}
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
convertBox(box);
sort(Boxes.begin(), Boxes.end());
MaxHeight.assign(Boxes.size(), 0);
MaxHeight[0] = Boxes[0].height;
return pileBox(Boxes.size() - 1, Box(INT_MAX, INT_MAX, INT_MAX));
}
private:
vector<Box> Boxes;
vector<int> MaxHeight;
int pileBox(const size_t curr, const Box &top)
{
Box &newTop = Boxes[curr];
int withHeight = 0, withoutHeight = 0;
if(newTop.above(top)){
if(MaxHeight[curr] == 0){
MaxHeight[curr] = pileBox(curr - 1, newTop);
MaxHeight[curr] += newTop.height;
}
withHeight = MaxHeight[curr];
}
if(curr != 0) withoutHeight = pileBox(curr - 1, top);
return withHeight > withoutHeight ? withHeight : withoutHeight;
}
void convertBox(const vector<vector<int>> &box)
{
for(size_t i = 0; i < box.size(); i++)
{
Boxes.push_back(Box(box[i][0], box[i][1], box[i][2]));
}
}
};
我越看记忆化搜索越觉得乱,所以最终还是用了动态规划。因为一个箱子下面的箱子只和该箱子的尺寸有关系,所以只需要记录以每个箱子作为最底部的箱子时能达到的最大高度即可。
struct Box
{
int width, depth, height;
public:
Box(int w, int d, int h)
: width(w), depth(d), height(h){}
bool above(const Box &bottom)
{
return width < bottom.width && depth < bottom.depth && height < bottom.height;
}
};
bool operator<(const Box &b1, const Box &b2)
{
return b1.width < b2.width;
}
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
convertBox(box);
sort(Boxes.begin(), Boxes.end());
vector<int> Height(Boxes.size(), 0);
Height[0] = Boxes[0].height;
int max = Height[0];
for(size_t i = 1; i < Boxes.size(); i++)
{
Height[i] = Boxes[i].height;
for(size_t j = 0; j < i; j++)
{
if(Boxes[j].above(Boxes[i])){
if(Height[i] < Height[j] + Boxes[i].height){
Height[i] = Height[j] + Boxes[i].height;
}
}
}
if(max < Height[i]) max = Height[i];
}
return max;
}
private:
vector<Box> Boxes;
void convertBox(const vector<vector<int>> &box)
{
for(size_t i = 0; i < box.size(); i++)
{
Boxes.push_back(Box(box[i][0], box[i][1], box[i][2]));
}
}
};