题意
某雕塑有 n 个边长平行于坐标轴的长方体组成。用每个长方体左上角的坐标,以及长方体的长宽高表示每个长方体。要求统计这个长方体的体积和表面积。其中,体积包含封闭在内部的空间,但表面积不包含在外面看不到的面。
思路
假想是从一个大的立方体中抠出这个雕塑,通过BFS计算多余体积,再从立方体中抠掉即可。同时,表面积也可以计算出来。
题目坐标系比较大,需要离散化。一开始有一点没想明白,怎么处理相邻两个长方体是否连接起来。实际上,只需要在描述长方体的长宽高区间时,采用左开右闭的方法处理即可。
链接
https://vjudge.net/problem/UVA-12171
代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxx = 1010;
const int maxn = 100+10;
struct node{
int x, y, z;
node(){}
node(int x,int y, int z):x(x), y(y), z(z){}
void read(){scanf("%d %d %d", &x, &y, &z);}
node operator +(node a){
return node(x + a.x, y + a.y, z + a.z);
}
void show(){
printf("%d %d %d\n", x, y, z);
}
};
node mov[6];
int T, n;
node P[maxn];
vector<int> X, Y, Z;
bool G[maxn][maxn][maxn];
bool vis[maxn][maxn][maxn];
void push_in(node &a){
X.push_back(a.x);
Y.push_back(a.y);
Z.push_back(a.z);
}
void compress(vector<int> &a){
a.push_back(0);
a.push_back(maxx);
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
}
int get_id(int d, vector<int> &D){
return lower_bound(D.begin(), D.end(), d) - D.begin();
}
int get_area(node &d, int dir){
if(mov[dir].z != 0)
return (X[d.x+1] - X[d.x]) * (Y[d.y+1] - Y[d.y]);
else if(mov[dir].y != 0)
return (X[d.x+1] - X[d.x]) * (Z[d.z+1] - Z[d.z]);
return (Y[d.y+1] - Y[d.y]) * (Z[d.z+1] - Z[d.z]);
}
int main(){
mov[0] = node(1, 0, 0);
mov[1] = node(-1, 0, 0);
mov[2] = node(0, 1, 0);
mov[3] = node(0, -1, 0);
mov[4] = node(0, 0, 1);
mov[5] = node(0, 0, -1);
scanf("%d", &T);
while(T--){
int v = 0, s = 0;
X.clear();Y.clear();Z.clear();
memset(vis, false, sizeof vis);
memset(G, false, sizeof G);
scanf("%d", &n);
for(int i = 0; i < (n<<1); i+=2){
P[i].read();
P[i+1].read();
P[i+1] = P[i] + P[i+1];
push_in(P[i]);
push_in(P[i+1]);
}
compress(X);
compress(Y);
compress(Z);
//构造离散化的小图
for(int i = 0; i < (n<<1); i += 2){
int x0 = get_id(P[i].x, X), x1 = get_id(P[i+1].x, X);
int y0 = get_id(P[i].y, Y), y1 = get_id(P[i+1].y, Y);
int z0 = get_id(P[i].z, Z), z1 = get_id(P[i+1].z, Z);
for(int x = x0; x < x1; ++x){
for(int y = y0; y < y1; ++y){
for(int z = z0; z < z1; ++z){
G[x][y][z] = true;
}
}
}
}
queue<node> qu;
qu.push(node(0, 0, 0));
vis[0][0][0] = true;
while(!qu.empty()){
node t = qu.front();
qu.pop();
if(!G[t.x][t.y][t.z]){
v += (X[t.x+1] - X[t.x]) * (Y[t.y+1] - Y[t.y]) * (Z[t.z+1] - Z[t.z]);
}
for(int i = 0; i < 6; ++i){
node mt = t + mov[i];
if(mt.x < 0 || mt.x >= X.size()-1 || mt.y < 0 || mt.y >= Y.size()-1 || mt.z < 0 || mt.z >= Z.size()-1)
continue;
if(G[mt.x][mt.y][mt.z]){
s += get_area(mt, i);
}else if(!vis[mt.x][mt.y][mt.z]){
qu.push(mt);
vis[mt.x][mt.y][mt.z] = true;
}
}
}
printf("%d %d\n", s, maxx * maxx * maxx - v);
}
return 0;
}