这道题的难点的思路紫书上说的很清楚了,floodfill就是一个bfs填色算法
但我觉得这道题难点在对离散化的理解,从区间到点的理解,如填色时为什么不包括右边界,bfs判断边界时为什么右边没到最后一个元素。这里参考一个大佬的博客:https://blog.csdn.net/weixin_33834910/article/details/94053469
结合代码去理解吧
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 110;
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 n;
int xx[N],yy[N],zz[N],x0[N],x1[N],y0[N],y1[N],z0[N],z1[N];
int lenx,leny,lenz;
int vis[N][N][N]; //0代表未访问 1表示有长方体 2表示访问过
int v,s;
struct point
{
int x,y,z;
point(int x = 0,int y = 0 ,int z = 0):x(x),y(y),z(z){};
};
void lsh()
{
sort(xx,xx+n*2+2);
sort(yy,yy+n*2+2);
sort(zz,zz+n*2+2);
lenx = unique(xx,xx+n*2+2) - xx;
leny = unique(yy,yy+n*2+2) - yy;
lenz = unique(zz,zz+n*2+2) - zz;
}
int find(int *a,int len,int x)
{
return lower_bound(a,a+len,x) - a;
}
bool check(int x,int y,int z)
{
return (x >= 0 && x < lenx - 1 && y >=0 && y < leny - 1 && z>=0 && z< lenz -1); //注意右边界不包括最后一个元素
}
int get_v(point a)
{
int v = (xx[a.x+1] - xx[a.x]) * (yy[a.y+1] - yy[a.y]) * (zz[a.z+1] - zz[a.z]);
return v;
}
//根据点的移动求和平行的面的面积
int area(point a,int flag)
{
if(dx[flag]) return (yy[a.y+1] - yy[a.y]) *(zz[a.z+1] - zz[a.z]);
else if(dy[flag]) return (xx[a.x+1] - xx[a.x]) *(zz[a.z+1] - zz[a.z]);
return (yy[a.y+1] - yy[a.y]) *(xx[a.x+1] - xx[a.x]);
}
void floodfill()
{
s = v = 0;
queue<point> q;
point a,b;
q.push(a);
vis[0][0][0] = 2;
while(!q.empty()){
a = q.front();
q.pop();
v += get_v(a);
for(int i = 0 ; i < 6 ; i++){
b.x = a.x+dx[i],b.y = a.y + dy[i],b.z = a.z + dz[i];
if(!check(b.x,b.y,b.z)) continue;
if(vis[b.x][b.y][b.z] == 1) s += area(b,i);
else if(vis[b.x][b.y][b.z] == 0){
q.push(b);
vis[b.x][b.y][b.z] = 2;
}
}
}
v = 1001 * 1001 * 1001 - v;
}
int main()
{
int t;
cin >> t;
while(t--){
cin >> n;
xx[0] = yy[0] = zz[0] = 0;
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];
xx[i*2+1] = x0[i];
xx[i*2+2] = x1[i];
yy[i*2+1] = y0[i];
yy[i*2+2] = y1[i];
zz[i*2+1] = z0[i];
zz[i*2+2] = z1[i];
}
xx[n*2+1] = yy[n*2+1] = zz[n*2+1] = 1001;
//离散化
lsh();
//染色
memset(vis,0,sizeof vis);
for(int i = 0 ; i < n ; i++){
int X = find(xx,lenx,x0[i]);
int X1 = find(xx,lenx,x1[i]);
int Y = find(yy,leny,y0[i]);
int Y1 = find(yy,leny,y1[i]);
int Z = find(zz,lenz,z0[i]);
int Z1 = find(zz,lenz,z1[i]);
//为什么不包括右边界,和离散化区间和点的关系有关
for(int j = X ; j < X1;j++){
for(int k = Y;k < Y1 ; k++){
for(int q = Z;q < Z1;q++){
vis[j][k][q] = 1;
}
}
}
}
floodfill();
printf("%d %d\n",s,v);
}
return 0;
}