看到题目首先想到200^4的乱搞。竟然有70分。。。。
正解是神奇的括号法,对8个角进行处理,然后求一下前缀和。
再从一个没被包住的点开始访问,如果访问到一个点的f值是正数,说明这是一个面。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int f[210][210][210];
bool vis[210][210][210];
int n;
struct node
{
int x,y,z;
};
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 maxx,maxy,maxz,ans;
int minx=222,miny=222,minz=222;
bool judge(int x,int y,int z)
{
if(x>=minx-1&&x<=maxx&&y>=miny-1&&y<=maxy&&z>=minz-1&&z<=maxz)
return true;
return false;
}
void bfs(int x,int y,int z)
{
node now,next;
int xx,yy,zz;
now.x=x;
now.y=y;
now.z=z;
vis[x][y][z]=1;
queue<node>q;
q.push(now);
while(!q.empty())
{
now=q.front();
q.pop();
for(int i=0;i<6;i++)
{
xx=now.x+dx[i];
yy=now.y+dy[i];
zz=now.z+dz[i];
if(!judge(xx,yy,zz)) continue;
if(vis[xx][yy][zz]) continue;
if(f[xx][yy][zz]) ans++;
else
{
vis[xx][yy][zz]=1;
next.x=xx;
next.y=yy;
next.z=zz;
q.push(next);
}
}
}
}
int main()
{
scanf("%d",&n);
int x1,x2,y1,y2,z1,z2;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
x1++;y1++;z1++;
x2++;y2++;z2++;
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]--;
minx=min(minx,x1);
miny=min(miny,y1);
minz=min(minz,z1);
maxx=max(maxx,x2+2);
maxy=max(maxz,y2+2);
maxz=max(maxz,z2+2);
}
for(int i=minx;i<=maxx;i++)
{
for(int j=miny;j<=maxy;j++)
{
for(int k=minz;k<=maxz;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-1];
f[i][j][k]-=f[i-1][j-1][k]+f[i][j-1][k-1]+f[i-1][j][k-1];
}
}
}
bfs(minx,miny,minz);
printf("%d\n",ans);
return 0;
}