题目思路
先预处理不同的边长作为高的立方体,共 \(3*n\) 种情况。
Q: 为什么不是 \(6*n\) 种情况呢?
A: 貌似也可以这么做,但是再判断块的放置时,长和宽互换没有影响,所以没有必要打 \(6\) 种。
再建图。如果块 \(A\) 可以放在块 \(B\) 上,就建一条 \(A\) 指向 \(B\) 的边,边权为 \(B\) 的高。
最后建一个超级源点,指向其他所有点上。
问题就转化成如何选择可以使边权最大。由于 \(n\le3\),可以把边权取负,跑一次 Floyd 即可。输出答案时不要忘记再取负一次。
AC Code
cpp
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=50;
struct node{
int x,y,z;
}a[N*3];
int n,g[N*3][N*3];
void solve(){
memset(g,0x3f,sizeof(g));
int ans=g[0][0];
for(int i=1,u,v,w;i<=n;i++){
cin>>u>>v>>w;
a[i]={u,v,w};
a[i+n]={u,w,v};
a[i+n*2]={v,w,u};
}
for(int i=1;i<=3*n;i++){
for(int j=1;j<=3*n;j++){
if(a[i].x<a[j].x&&a[i].y<a[j].y) g[i][j]=-a[j].z;
else if(a[i].x<a[j].y&&a[i].y<a[j].x) g[i][j]=-a[j].z;
}
}
for(int i=1;i<=3*n;i++){
g[3*n+1][i]=-a[i].z;
}
for(int k=1;k<=3*n+1;k++){
for(int i=1;i<=3*n+1;i++){
for(int j=1;j<=3*n+1;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
for(int i=1;i<=3*n+1;i++)
for(int j=1;j<=3*n+1;j++)
ans=min(ans,g[i][j]);
cout<<-ans<<"\n";
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
while(1){
cin>>n;
if(n==0) break;
solve();
}
return 0;
}