堆箱子
堆箱子。给你一堆n个箱子,箱子宽 wi、深 di、高 hi。箱子不能翻转,将箱子堆起来时,下面箱子的宽度、高度和深度必须大于上面的箱子。
实现一种方法,搭出最高的一堆箱子。箱堆的高度为每个箱子高度的总和。
1. 排序 + 动态规划
随便按一个维度排序,然后二重循环加判断进行动态规划转移
如果从小到大排序,dp[i]表示以i为底座的最大高度
从大到小排序,dp[i]表示以i为顶的最大高度
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
sort(box.begin(),box.end(),[&](vector<int> &a,vector<int> &b){
if(a[0]==b[0]) return a[1]>b[1];
return a[0]>b[0];
});
int n = box.size();
vector<int> dp(n);//dp[i]存储以i为顶的最大高度
for(int i=0;i<n;i++)
dp[i] = box[i][2];//用自身高度初始化
int res = INT_MIN;
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(box[j][0]>box[i][0]&&box[j][1]>box[i][1]&&box[j][2]>box[i][2])
dp[i] = max(dp[i],dp[j]+box[i][2]);
}
res =max(res,dp[i]);
}
return res;
}
};
2. 排序 + 二维树状数组
这里按高度进行排序,根据长宽更小的长方体,对以当前查询点为底座的最大高度进行更新
using tiii = tuple<int,int,int>;
class BIT{
public:
vector<vector<int>> tree;
int nw, nd;
BIT(int nw, int nd){//初始化二维树状数组
this->nw = nw;
this->nd = nd;
tree.resize(nw+1);
for (int i = 0; i <= nw; i++)
tree[i].assign(nd+1,0);
}
int query(int w, int d){ //二维树状数组查询最大值,往左查询
int res = 0;
for (int i = w; i > 0; i -= i&(-i)){
for (int j = d; j > 0; j -= j&(-j)){
res = max(res, tree[i][j]);
}
}
return res;
}
void update(int w, int d, int v){ //二维树状数组更新最大值,往右更新
for (int i = w; i <= nw; i += i&(-i)){
for (int j = d; j <= nd; j += j&(-j)){
tree[i][j] = max(tree[i][j], v);
}
}
}
};
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
set<int> ws, ds;
unordered_map<int,int> w2id, d2id; //使用哈希表离散化
vector<tiii> arr;
for (auto &b : box){
ws.insert(b[0]);
ds.insert(b[1]);
arr.push_back({b[2],-b[0],-b[1]});//高度按从小到大排序,高度相同时,宽度和长度按从大到小,避免相同值用作叠加
}
sort(arr.begin(), arr.end());//按高度从小到大排列
int nw = 0;//宽度下标
for (auto w : ws) w2id[w] = ++nw;//离散化宽度,相同点只保留一个
int nd = 0;
for (auto d : ds) d2id[d] = ++nd;//离散化深度
int res = 0;//长度下标
BIT T(nw,nd); //初始化二维树状数组
for (auto &[h,w,d] : arr){ //由高度从小到大遍历点
w = -w; d = -d;
int ph = T.query(w2id[w]-1,d2id[d]-1); //查询长宽更小值的最大高度
res = max(res, ph+h);
T.update(w2id[w],d2id[d],ph+h); //更新点
}
return res;
}
};
class BIT{
public:
vector<vector<int>> tree;
int nw, nd;
BIT(int nw, int nd){//初始化二维树状数组
this->nw = nw;
this->nd = nd;
tree.resize(nw+1);
for (int i = 0; i <= nw; i++)
tree[i].assign(nd+1,0);
}
int query(int w, int d){ //二维树状数组查询最大值,往左查询
int res = 0;
for (int i = w; i > 0; i -= i&(-i)){
for (int j = d; j > 0; j -= j&(-j)){
res = max(res, tree[i][j]);
}
}
return res;
}
void update(int w, int d, int v){ //二维树状数组更新最大值,往右更新
for (int i = w; i <= nw; i += i&(-i)){
for (int j = d; j <= nd; j += j&(-j)){
tree[i][j] = max(tree[i][j], v);
}
}
}
};
class Solution {
public:
int pileBox(vector<vector<int>>& box) {
set<int> ws, ds;
unordered_map<int,int> w2id, d2id; //使用哈希表离散化
vector<tiii> arr;
for (auto &b : box){
ws.insert(b[0]);
ds.insert(b[1]);
arr.push_back({b[2],-b[0],-b[1]});//高度按从小到大排序,高度相同时,宽度和长度按从大到小,避免相同值用作叠加
}
sort(arr.begin(), arr.end());//按高度从小到大排列
int nw = 0;//宽度下标
for (auto w : ws) w2id[w] = ++nw;//离散化宽度,相同点只保留一个
int nd = 0;
for (auto d : ds) d2id[d] = ++nd;//离散化深度
int res = 0;//长度下标
BIT T(nw,nd); //初始化二维树状数组
for (auto &[h,w,d] : arr){ //由高度从小到大遍历点
w = -w; d = -d;
int ph = T.query(w2id[w]-1,d2id[d]-1); //查询长宽更小值的最大高度
res = max(res, ph+h);
T.update(w2id[w],d2id[d],ph+h); //更新点
}
return res;
}
};