求一个雕塑的表面积和体积。
雕塑最多由50个立方体组成,总长宽高小于500 * 500 * 500。
立方体可能相互嵌套,或围成密闭空间,因此无法直接计算。
floodfill : 将雕塑放入一个500 * 500 * 500的空间内,求空气的联通块,该联通块的内表面积即为雕塑的表面积,500 * 500 * 500 - 联通块的体积即雕塑的体积。
问题1:500 * 500 * 500大于1e8,超内存,需要离散化。而最多50个立方体,一个坐标轴方向最多2个坐标,最多100个坐标。
问题2:空气的联通块可能较大,用dfs会溢出,应用bfs。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 50 + 5;
const int maxc = 1000 + 1;
//original data
int n,x0[maxn],y0[maxn],z0[maxn],x1[maxn],y1[maxn],z1[maxn];
//discretization data
int nx,ny,nz;
int xs[maxn * 2],ys[maxn * 2],zs[maxn * 2];
const int dx[] = {1,-1,0,0,0,0};
const int dy[] = {0,0,1,-1,0,0};
const int dz[] = {0,0,0,0,1,-1};
int mp[maxn * 2][maxn * 2][maxn * 2];
struct Cell{
int x,y,z;
Cell(int x = 0,int y = 0,int z = 0) : x(x),y(y),z(z) {}
void setVis() const {
mp[x][y][z] = 2;
}
int Volume() const {
return (xs[x + 1] - xs[x]) * (ys[y + 1] - ys[y]) * (zs[z + 1] - zs[z]);
}
Cell neighbor(int dir) const {
return Cell(x + dx[dir],y + dy[dir],z + dz[dir]);
}
bool valid() const {
return x >= 0 && x < nx - 1 && y >= 0 && y < ny - 1 && z >= 0 && z < nz - 1;
}
bool solid() const {
return mp[x][y][z] == 1;
}
int area(int dir) const {
if(dx[dir] != 0) return (ys[y + 1] - ys[y]) * (zs[z + 1] - zs[z]);
else if(dy[dir] != 0) return (xs[x + 1] - xs[x]) * (zs[z + 1] - zs[z]);
else return (xs[x + 1] - xs[x]) * (ys[y + 1] - ys[y]);
}
bool getVis() const {
return mp[x][y][z] == 2;
}
};
void discretization(int xs[],int &nx)
{
sort(xs,xs + nx);
nx = unique(xs,xs + nx) - xs;
}
int ID(int x[],int sz,int x0)
{
return lower_bound(x, x + sz, x0) - x;
}
void floodfill(int &v,int &s)
{
v = 0,s = 0;
Cell c;
c.setVis();
queue<Cell> q;
q.push(c);
while(!q.empty())
{
Cell c = q.front();q.pop();
v += c.Volume();
for (int i = 0; i < 6; i ++) {
Cell c2 = c.neighbor(i);
if (c2.valid()) {
if (c2.solid() ) s += c.area(i);
else if(!c2.getVis())
{
c2.setVis();
q.push(c2);
}
}
}
}
v = maxc * maxc * maxc - v;
}
int main()
{
int T;
scanf("%d",&T);
while(T --)
{
nx = ny = nz = 2;
xs[0] = ys[0] = zs[0] = 0;
xs[1] = ys[1] = zs[1] = maxc;
scanf("%d",&n);
for (int i = 0; i < n; i ++) {
scanf("%d%d%d%d%d%d",&x0[i],&y0[i],&z0[i],&x1[i],&y1[i],&z1[i]);
x1[i] += x0[i];y1[i] += y0[i];z1[i] += z0[i];
xs[nx ++] = x0[i];xs[nx ++] = x1[i];
ys[ny ++] = y0[i];ys[ny ++] = y1[i];
zs[nz ++] = z0[i];zs[nz ++] = z1[i];
}
discretization(xs, nx);
discretization(ys, ny);
discretization(zs, nz);
memset(mp, 0, sizeof(mp));
for (int i = 0; i < n; i ++) {
int X1 = ID(xs,nx,x0[i]),X2 = ID(xs,nx,x1[i]);
int Y1 = ID(ys,ny,y0[i]),Y2 = ID(ys,ny,y1[i]);
int Z1 = ID(zs,nz,z0[i]),Z2 = ID(zs,nz,z1[i]);
for (int X = X1; X < X2; X ++) {
for (int Y = Y1; Y < Y2; Y ++) {
for (int Z = Z1; Z < Z2; Z ++) {
mp[X][Y][Z] = 1;
}
}
}
}
int v,s;
floodfill(v,s);
printf("%d %d\n",s,v);
}
return 0;
}