Leetcode 1691. 堆疊長方體的最大高度(拓撲排序 + DP)
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;
}
};
相關文章
- 拓撲排序排序
- 【Tarjan 拓撲排序 dp】P3387 【模板】縮點排序
- 洛谷P3953 逛公園(dp 拓撲排序)排序
- 拓撲排序,YYDS排序
- 圖論——拓撲排序圖論排序
- 筆記:拓撲排序筆記排序
- 拓撲排序小結排序
- Reward (圖論+拓撲排序)圖論排序
- AOV網與拓撲排序排序
- 【筆記/模板】拓撲排序筆記排序
- DFS實現拓撲排序排序
- 有向圖的拓撲排序——DFS排序
- 拓撲排序就這麼回事排序
- 演算法-圖論-拓撲排序演算法圖論排序
- 圖的拓撲排序詳解與實現排序
- (set+拓撲排序) CF1572A Book排序
- 圖解拓撲排序+程式碼實現圖解排序
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- VOL.2 拓撲排序與關鍵路徑排序
- 拓撲排序詳解(梅開二度之dfs版按字典序輸出拓撲路徑+dfs版輸出全部拓撲路徑排序
- Noc拓撲
- 牛客 51011 可達性統計(拓撲排序,bitset)排序
- StratoVirt 的 vCPU 拓撲(SMP)
- 【BZOJ-1565】植物大戰殭屍 拓撲排序 + 最小割排序
- JS中堆疊記憶體的練習JS記憶體
- javascript堆疊記憶體分配的區別JavaScript記憶體
- QT分局管理:堆疊窗體(三)QT
- JS 堆疊JS
- 平衡堆疊
- 堆疊圖
- Android程式設計師會遇到的演算法(part 7 拓撲排序)Android程式設計師演算法排序
- Day2 尤拉路,拓撲排序和差分約束排序
- 拓撲序的三種功能
- 樹的拓撲序計數
- 堆疊和記憶體的關係 細說記憶體
- Thrift的網路堆疊
- 商企網路拓撲的搭建
- 2020.12.21-2020.12.27 leetcode刷題總結(拓撲排序&蓄水池抽樣&二叉搜尋樹&線段樹)LeetCode排序