BZOJ 3234: [Ahoi2013]立方体
BZOJ 3234: [Ahoi2013]立方体
标签(空格分隔): OI-BZOJ OI-计算几何
Time Limit: 10 Sec
Memory Limit: 64 MB
Description
在一个三维空间中有N个立方体,第i个立方体占据x_i1,y_i1, z_i1 --- x_i2, y_i2, z_i2的位置。这N个立方体可能有相交,也可能重叠。这N个立方体构成一个大的几何图形。现在求这个几何图形的外表面积
Input
第一行,一个整数N,表示立方体的个数。
第二行至第N+1行,每行6个用空格隔开的整数,分别表示x1,y1,z1,x2,y2,z2.
Output
一行,一个整数,表示外表面积的大小。
Sample Input
input 1
1
0 0 0 1 1 1
input 2
2
0 1 0 3 2 1
1 0 0 2 3 1
Sample Output
output 1
6
output 2
22
HINT
对于第一个样例
对于第二个样例
1<=N<=200,0<=x_i1,y_i1,z_i1,x_i2,y_i2,z_i2<=200,x_i1<x_i2,y_i1<y_i2,z _i1<z_i2
Source
鸣谢zhonghaoxi提供数据,原数据似有误
Solution####
开始的时候稍微纠结了一下空心内部空间的面积算不算。。并不算,都说了是外表面积。
开始想到的是扫描线,直接开个200*200的数组暴力修改,加到1或减到0就记录答案\(O(n^3)\)。
后来想了想统计表面积的时候可以bfs外面的空间的小立方体,如果进入被
覆盖的小立方体就记录答案,每块外表面的2边一定是:一个被覆盖的小立方
体和未被覆盖的小立方体。
至于判断是否被覆盖,只要在立方体8个顶点打+-标记,做前缀和。
具体来说,在(x1,y1,z1)标记+1则{(x,y,z)|x>=x1&&y>=y1&&z>=x1}被覆盖
在(x1,y1,z2)标记-1则{(x,y,z)|x>=x1&&y>=y1&&z>=z1}被删除
容斥即可
Code####
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
int read()
{
int s=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*f;
}
//smile please
int n,f[205][205][205],ans,mx,my,mz;
bool vis[205][205][205];
int dx[6]={-1,1,0,0,0,0},dy[6]={0,0,-1,1,0,0},dz[6]={0,0,0,0,-1,1};
struct pai;
queue<pai>q;int kk;
struct pai
{
int x,y,z;
void dfs()
{
if(vis[x][y][z])return;
if(f[x][y][z])ans++;
else
{vis[x][y][z]=1;
for(int i=0;i<6;i++)
q.push((pai){x+dx[i],y+dy[i],z+dz[i]});
}
kk++;
}
};
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int x1,x2,y1,y2,z1,z2;
n=read();
for(int i=1;i<=n;i++)
{x1=read()+2,y1=read()+2,z1=read()+2,
x2=read()+2,y2=read()+2,z2=read()+2;
f[x1][y1][z1]++;
f[x1][y1][z2]--;
f[x1][y2][z1]--;
f[x2][y1][z1]--;
f[x2][y2][z1]++;
f[x2][y1][z2]++;
f[x1][y2][z2]++;
f[x2][y2][z2]--;
mx=max(mx,x2);
my=max(my,y2);
mz=max(mz,z2);
}
for(int i=1;i<=mx+1;i++)
for(int j=1;j<=my+1;j++)
for(int k=1;k<=mz+1;k++)
f[i][j][k]=f[i][j][k]+f[i-1][j][k]+f[i][j-1][k]+f[i][j][k-1]-f[i-1][j-1][k]-f[i-1][j][k-1]-f[i][j-1][k-1]+f[i-1][j-1][k-1];
for(int i=0;i<=mx+2;i++)
for(int j=0;j<=my+2;j++)
for(int k=0;k<=mz+2;k++)
if(i==0||j==0||k==0||i==mx+2||j==my+2||k==mz+2)
vis[i][j][k]=1;
for(q.push((pai){1,1,1});!q.empty();)
{pai x=q.front();q.pop();
x.dfs();
}
printf("%d\n",ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}