您的位置:首页 > 编程语言

UVA - 12171 Sculpture

2017-10-06 15:54 323 查看
/*
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
, y0
, z0
, x1
, y1
, z1
;

// 离散化后的坐标
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息