堆箱子

堆箱子。给你一堆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;
    }
};
posted @ 2023-07-07 16:41  失控D大白兔  阅读(53)  评论(0编辑  收藏  举报