Leetcode 1691. 堆疊長方體的最大高度(拓撲排序 + DP)

chr1st0pher發表於2020-12-24

Description
在這裡插入圖片描述

Solution
一個立方體可以任意翻轉, 我們可以當成多個不同的立方體看待。
問題轉化為:有最多N*6個立方體, 最高能壘多高
考慮DP[i], 第i個立方體放在最上面時的最大高度, 發現當前的狀態是由所有可以壘在其下面的立方體轉移過來的,所以我們考慮一邊拓撲排序一邊DP

Code

class Solution {
public:
    #define N 202
    struct cube{
        int a,b,c;
    };
    vector<cube>num;
    inline void init() {
        num.clear();
    }
    bool vis[N][N][N];
    inline void emp(int a,int b,int c) {
        vis[a][b][c] = vis[a][c][b] = vis[b][a][c] = vis[b][c][a] = vis[c][a][b] = vis[c][b][a] = false;
    }
    int d[N*3], dp[N*3];
    vector<int>edge[N*3];
    int used[N][N][N], val[N*3];
    bool check(int i,int j) {
        if(num[i].a >= num[j].a && num[i].b >= num[j].b && num[i].c >= num[j].c) {
            return true;
        }
        return false;
    }
    inline void add(int i,int j) {
        edge[i].push_back(j);
        ++d[j];
    }
    int solve() {
        int n = num.size();
        for(int i = 0;i < n;++i) edge[i].clear(), d[i] = 0, used[num[i].a][num[i].b][num[i].c] = 0;
        vector<cube>tmp;
        for(int i = 0;i < n;++i) {
            int a = num[i].a, b = num[i].b, c = num[i].c;
            if(!used[a][b][c]) {
                tmp.push_back((cube){a,b,c});
            } else {
            }
            used[a][b][c] += num[i].c;
        }
        num.clear();
        for(auto x : tmp) {
            num.push_back(x);
        } tmp.clear();
        n = num.size();
        for(int i = 0;i < n;++i) {
            dp[i] = val[i] = used[num[i].a][num[i].b][num[i].c];
            for(int j = 0;j < n;++j) {
                if(i == j) continue;
                if(check(i,j)) add(i,j);
            }
        }
        queue<int>q;
        for(int i = 0;i < n;++i) if(!d[i]) {q.push(i);}
        int res = 0;
        while(!q.empty()) {
            int u = q.front();q.pop();
            for(int i = 0;i < edge[u].size();++i) {
                int v = edge[u][i];
                dp[v] = max(dp[v], dp[u] + val[v]);
                if(--d[v] == 0) q.push(v);
            }
        }
        for(int i = 0;i < n;++i) res = max(res, dp[i]);
        return res;
    }
    int maxHeight(vector<vector<int>>& cuboids) {
        init();
        for(int i = 0;i < cuboids.size();++i) {
            int a = cuboids[i][0], b = cuboids[i][1], c = cuboids[i][2];
            num.push_back((cube){a,b,c}), vis[a][b][c] = true;
            if(!vis[a][c][b]) num.push_back((cube){a,c,b}), vis[a][c][b] = true;
            if(!vis[b][a][c]) num.push_back((cube){b,a,c}), vis[b][a][c] = true;
            if(!vis[b][c][a]) num.push_back((cube){b,c,a}), vis[b][c][a] = true;
            if(!vis[c][a][b]) num.push_back((cube){c,a,b}), vis[c][a][b] = true;
            if(!vis[c][b][a]) num.push_back((cube){c,b,a}), vis[c][b][a] = true;
            emp(a,b,c);
        }
        int res = solve();return res;
    }
};

相關文章