题意(from紫书):某雕塑由 n (n<=50) 个边平行于坐标轴的长方体组成。每个长方体用 6 个整数 x0, y0, z0, x, y, z 表示(1<= x0, y0, z0, x, y, z <= 500)。 x0 为长方体顶点中,x 坐标的最小值,x 表示长方体在 x 方向的长度。其他 4 个值类似定义。统计这个雕像的体积和表面积。注意,雕像内部可能会有密闭的空间,其体积应该算在总体积中。
分析:可以把长方体对应到一个三维坐标系中,这样就可以抛开长方体只对网格进行统计,观察题目中x,y,z的范围都是0~500,这样开三维需要500^3=1.25e8,对每个长方体的网格进行操作时,无论是时间和空间复杂度都比较高,而n只有50,那么对x,y,z坐标进行离散化之后,只有100个点,100^3=1e6
然后考虑如何计算体积,我们把每个离散化后的网格都染色进行统计,但是在雕像内部有密闭空间,这部分空间也要算在总体积中,而染色的网格把这一块密闭空间都包围了,这时就要用紫书中所说的在所有网格的最外围加一层空气,使得空气网格都连通
此时就可以用floodfill,将坐标系中所有的空气网格都标记,统计标记网格的体积,用坐标系的总体积-标记网格的体积即为所求得体积,然后floodfill过程中访问到的已经染过色的网格,即为表面积
实现中还有一些细节问题,具体看代码
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=55;
const int M=1001;
struct node
{
int x,y,z,lx,ly,lz;
}e[55];
struct p
{
p(){}
p(int _x,int _y,int _z)
{
x=_x,y=_y,z=_z;
}
int x,y,z;
};
int nx,ny,nz,a[N<<1],b[N<<1],c[N<<1];
int vis[N<<1][N<<1][N<<1];
int dx[]={-1,1,0,0,0,0};
int dy[]={0,0,-1,1,0,0};
int dz[]={0,0,0,0,-1,1};
int area(int x,int y,int z,int dir)
{
if(dx[dir]!=0)
return (b[y+1]-b[y])*(c[z+1]-c[z]);
else if(dy[dir]!=0)
return (a[x+1]-a[x])*(c[z+1]-c[z]);
else if(dz[dir]!=0)
return (a[x+1]-a[x])*(b[y+1]-b[y]);
}
void add(int x,int y,int z)
{
a[nx++]=x;
b[ny++]=y;
c[nz++]=z;
}
void bfs()
{
queue<p>q;
vis[0][0][0]=2;
q.push(p(0,0,0));
int v=0,s=0;
while(!q.empty())
{
p u=q.front();
q.pop();
v+=(a[u.x+1]-a[u.x])*(b[u.y+1]-b[u.y])*(c[u.z+1]-c[u.z]);
for(int i=0;i<6;i++)
{
int tx=u.x+dx[i];
int ty=u.y+dy[i];
int tz=u.z+dz[i];
if(tx>=0&&tx<nx-1&&ty>=0&&ty<ny-1&&tz>=0&&tz<nz-1)
{
if(vis[tx][ty][tz]==0)
{
vis[tx][ty][tz]=2;
q.push(p(tx,ty,tz));
}
if(vis[tx][ty][tz]==1)
s+=area(tx,ty,tz,i);
}
}
}
v=M*M*M-v;
printf("%d %d\n",s,v);
}
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n;
nx=0,ny=0,nz=0;
//加入坐标系的起点和终点,相当于在所有整体的最外边加了一层空气,使得所有空气格子连通
a[nx++]=b[ny++]=c[nz++]=0;
a[nx++]=b[ny++]=c[nz++]=M;
mem(vis,0);
for(int i=1;i<=n;i++)
{
cin>>e[i].x>>e[i].y>>e[i].z>>e[i].lx>>e[i].ly>>e[i].lz;
add(e[i].x,e[i].y,e[i].z);
add(e[i].x+e[i].lx,e[i].y+e[i].ly,e[i].z+e[i].lz);
}
sort(a,a+nx);
sort(b,b+ny);
sort(c,c+nz);
nx=unique(a,a+nx)-a;
ny=unique(b,b+ny)-b;
nz=unique(c,c+nz)-c;
for(int k=1;k<=n;k++)
{
int x=lower_bound(a,a+nx,e[k].x)-a;
int tx=lower_bound(a,a+nx,e[k].x+e[k].lx)-a;
int y=lower_bound(b,b+ny,e[k].y)-b;
int ty=lower_bound(b,b+ny,e[k].y+e[k].ly)-b;
int z=lower_bound(c,c+nz,e[k].z)-c;
int tz=lower_bound(c,c+nz,e[k].z+e[k].lz)-c;
//将长方体所在的网格染色为1
for(int i=x;i<tx;i++)
for(int j=y;j<ty;j++)
for(int o=z;o<tz;o++)
vis[i][j][o]=1;
}
bfs();
}
return 0;
}