1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 int a[110][110][110],x_map[110],y_map[110],z_map[110], 8 x1_ori[110],y1_ori[60],z1_ori[60],x2_ori[60],y2_ori[60],z2_ori[60], 9 x_move[6]={1,-1,0,0,0,0},y_move[6]={0,0,1,-1,0,0},z_move[6]={0,0,0,0,1,-1}, 10 x_cnt,y_cnt,z_cnt; 11 long long ans_s,ans_v; 12 map<int,int> x_rev,y_rev,z_rev; 13 struct cond 14 { 15 int x,y,z; 16 }c1,c2; 17 queue<cond> q; 18 int main() 19 { 20 int i,j,k,l,m,n,p,x,y,z,t,xx,yy,zz,temp; 21 scanf("%d",&t); 22 while (t--) 23 { 24 memset(a,0,sizeof(a)); 25 memset(x_map,0,sizeof(x_map)); 26 memset(y_map,0,sizeof(y_map)); 27 memset(z_map,0,sizeof(z_map)); 28 memset(x1_ori,0,sizeof(x1_ori)); 29 memset(y1_ori,0,sizeof(y1_ori)); 30 memset(z1_ori,0,sizeof(z1_ori)); 31 memset(x2_ori,0,sizeof(x2_ori)); 32 memset(y2_ori,0,sizeof(y2_ori)); 33 memset(z2_ori,0,sizeof(z2_ori)); 34 x_rev.clear(); 35 y_rev.clear(); 36 z_rev.clear(); 37 scanf("%d",&n); 38 for (i=1;i<=n;i++) 39 { 40 scanf("%d%d%d%d%d%d",&x1_ori[i],&y1_ori[i],&z1_ori[i],&x,&y,&z); 41 x_map[i]=x1_ori[i]; 42 y_map[i]=y1_ori[i]; 43 z_map[i]=z1_ori[i]; 44 x_map[i+n]=x2_ori[i]=x1_ori[i]+x; 45 y_map[i+n]=y2_ori[i]=y1_ori[i]+y; 46 z_map[i+n]=z2_ori[i]=z1_ori[i]+z; 47 } 48 sort(x_map+1,x_map+2*n+1); 49 sort(y_map+1,y_map+2*n+1); 50 sort(z_map+1,z_map+2*n+1); 51 x_cnt=unique(x_map+1,x_map+2*n+1)-(x_map+1); 52 y_cnt=unique(y_map+1,y_map+2*n+1)-(y_map+1); 53 z_cnt=unique(z_map+1,z_map+2*n+1)-(z_map+1); 54 for (i=1;i<=x_cnt;i++) 55 x_rev[x_map[i]]=i; 56 for (i=1;i<=y_cnt;i++) 57 y_rev[y_map[i]]=i; 58 for (i=1;i<=z_cnt;i++) 59 z_rev[z_map[i]]=i; //以上为离散化 60 x_map[0]=y_map[0]=z_map[0]=0; 61 x_map[x_cnt+1]=y_map[y_cnt+1]=z_map[z_cnt+1]=1005; //边界,要在外面多围一圈空气。 62 for (i=1;i<=n;i++) 63 for (x=x_rev[x1_ori[i]];x<x_rev[x2_ori[i]];x++) 64 for (y=y_rev[y1_ori[i]];y<y_rev[y2_ori[i]];y++) 65 for (z=z_rev[z1_ori[i]];z<z_rev[z2_ori[i]];z++) 66 a[x][y][z]=1; //填充 67 ans_v=1005*1005*1005; 68 ans_s=0; 69 c1.x=c1.y=c1.z=0; 70 q.push(c1); 71 a[0][0][0]=2; //2表示已经入过队 72 while (!q.empty()) 73 { 74 c1=q.front(); 75 q.pop(); 76 xx=c1.x; 77 yy=c1.y; 78 zz=c1.z; 79 ans_v-=(x_map[xx+1]-x_map[xx])*(y_map[yy+1]-y_map[yy])*(z_map[zz+1]-z_map[zz]); 80 for (i=0;i<=5;i++) 81 { 82 x=xx+x_move[i]; 83 y=yy+y_move[i]; 84 z=zz+z_move[i]; 85 if (x>=0&&x<=x_cnt&&y>=0&&y<=y_cnt&&z>=0&&z<=z_cnt) 86 { 87 if (a[x][y][z]==0) 88 { 89 c2.x=x; 90 c2.y=y; 91 c2.z=z; 92 a[x][y][z]=2; //要在入队时标记,不能在取出时。 93 q.push(c2); 94 } 95 if (a[x][y][z]==1) 96 { 97 temp=1; 98 if (x==xx) temp*=(x_map[xx+1]-x_map[xx]); 99 if (y==yy) temp*=(y_map[yy+1]-y_map[yy]); 100 if (z==zz) temp*=(z_map[zz+1]-z_map[zz]); 101 ans_s+=temp; //算面积 102 } 103 } 104 } 105 } 106 printf("%lld %lld\n",ans_s,ans_v); 107 } 108 }
离散化+floodfill。
最开始用的dfs结果RE想到可能是堆栈溢出,改用bfs后AC。
由于体积和面积都是从外面看的,可以从外面一圈“空气”开始floodfill,每次遇到雕塑就加上表面积,因为每一块表面积都会且只会和一块空气接触。体积用总体积减去遇到的空气体积即可。
由于坐标较大,需要离散化。