/* A. 这题用到了之前做过的一些题的一些思想: 例如: 1. 之前做过的 UVA - 1103 Ancient Messages ( http://blog.csdn.net/mofushaohua_ln/article/details/78162277 ) 两题十分相似之处在于,都是连通块问题,且都要在最外围,加上一圈“空气”,以使得所有空气格子得以连通 2. 之前做过的 UVA - 221 Urban Elevations ( http://blog.csdn.net/mofushaohua_ln/article/details/77799245 ) 两题都用到了坐标离散化的思想,来减少所需单元格的数目 不过需要注意的是,floodfill时,运用离散化后的坐标来处理连通块,是没有问题的。但是,在统计表面积和体积时,一定要用原始坐标,否则必定WA B. 该题主要思路见小白书 P172 不考虑雕塑本身,而考虑“空气”,在网格周围加一圈“空气”(目的时为了让所有空气格子连通),然后做一次 floodfill,即可得到空气的 “内表面积” 和体积,这个表面积就是雕塑的外表面积,雕塑体积等于总体积减去空气体积 floodfill 时直接使用离散化后的新坐标,但在统计表面积和体积时则需要使用原始坐标 */
#include <iostream> #include <algorithm> #include <queue> #include <cstring> #define rep(i, n) for ( int i = 0; i < (n); i++ ) using namespace std; const int N = 50 + 5; const int C = 1e3 + 1; int n, x0[N], y0[N], z0[N], x1[N], y1[N], z1[N]; // 离散化后的坐标 int nx, ny, nz; int xs[N * 2], ys[N * 2], zs[N * 2]; // 种子填充 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 color[N * 2][N * 2][N * 2]; struct Cell { int x, y, z; Cell (int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) { } bool valid() const { return x >= 0 && x < nx - 1 && y >= 0 && y < ny - 1 && z >= 0 && z < nz - 1; } bool solid() const { return color[x][y][z] == 1; // solid } bool getVis() const { return color[x][y][z] == 2; // visited } void setVis() const { color[x][y][z] = 2; } Cell neighbour (int dir) const { return Cell( x + dx[dir], y + dy[dir], z + dz[dir] ); } int getVolume() const { return ( xs[x + 1] - xs[x] ) * ( ys[y + 1] - ys[y] ) * ( zs[z + 1] - zs[z] ); } int getArea(int dir) const { if (dx[dir]) return ( ys[y + 1] - ys[y] ) * ( zs[z + 1] - zs[z] ); if (dy[dir]) return ( xs[x + 1] - xs[x] ) * ( zs[z + 1] - zs[z] ); return ( xs[x + 1] - xs[x] ) * ( ys[y + 1] - ys[y] ); } }; void discretize (int* x, int& n) // 坐标离散化 { sort(x, x + n); n = unique(x, x + n) - x; } int ID (int *x, int n, int x0) { return lower_bound(x, x + n, x0) - x; } void FloodFill(int &v, int &s) { v = s = 0; Cell c; c.setVis(); queue<Cell> q; q.push(c); while (!q.empty()) { Cell c = q.front(); q.pop(); v += c.getVolume(); rep(i, 6) { Cell c2 = c.neighbour(i); if (!c2.valid()) continue; if (c2.solid()) s += c.getArea(i); else if (!c2.getVis()) { c2.setVis(); q.push(c2); } } } v = C * C * C- v; } int main() { int t; cin >> t; while (t--) { nx = ny = nz = 2; xs[0] = ys[0] = zs[0] = 0; xs[1] = ys[1] = zs[1] = C; cin >> n; rep(i, n) { cin >> x0[i] >> y0[i] >> z0[i] >> x1[i] >> y1[i] >> z1[i]; x1[i] += x0[i]; y1[i] += y0[i]; z1[i] += z0[i]; xs[nx++] = x0[i]; xs[nx++] = x1[i]; ys[ny++] = y0[i]; ys[ny++] = y1[i]; zs[nz++] = z0[i]; zs[nz++] = z1[i]; } discretize(xs, nx); discretize(ys, ny); discretize(zs, nz); // paint memset( color, 0, sizeof(color) ); rep(i, n) { int X1 = ID ( xs, nx, x0[i] ), X2 = ID ( xs, nx, x1[i] ); int Y1 = ID ( ys, ny, y0[i] ), Y2 = ID ( ys, ny, y1[i] ); int Z1 = ID ( zs, nz, z0[i] ), Z2 = ID ( zs, nz, z1[i] ); for (int X = X1; X < X2; X++) for (int Y = Y1; Y < Y2; Y++) for (int Z = Z1; Z < Z2; Z++) { color[X][Y][Z] = 1; } } int v, s; FloodFill(v, s); cout << s << " " << v << endl; } }