SP100 BABTWR - Tower of Babylon

传送门

题目思路

先预处理不同的边长作为高的立方体,共 \(3*n\) 种情况。

Q: 为什么不是 \(6*n\) 种情况呢?
A: 貌似也可以这么做,但是再判断块的放置时,长和宽互换没有影响,所以没有必要打 \(6\) 种。

再建图。如果块 \(A\) 可以放在块 \(B\) 上,就建一条 \(A\) 指向 \(B\) 的边,边权为 \(B\) 的高。

最后建一个超级源点,指向其他所有点上。

问题就转化成如何选择可以使边权最大。由于 \(n\le3\),可以把边权取负,跑一次 Floyd 即可。输出答案时不要忘记再取负一次。

AC Code

#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;
}

posted @ 2025-12-27 16:22  深申  阅读(19)  评论(0)    收藏  举报