#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
using namespace std;
const int Dirs[6][3] = { {1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1} };
const int MPOINT = 50 + 3,MLEN = 1001;
int plen ,xStart[MPOINT], xEnd[MPOINT], yStart[MPOINT], yEnd[MPOINT], zStart[MPOINT], zEnd[MPOINT];
int matrix[MPOINT*2][MPOINT*2][MPOINT*2];
int xlen, ylen, zlen, xPoint[MPOINT * 2], yPoint[MPOINT * 2], zPoint[MPOINT * 2];
struct Cell {
Cell(int _x = 0, int _y = 0, int _z = 0) :x(_x), y(_y), z(_z) {}
Cell GetNext(int dir) {
return Cell(x + Dirs[dir][0], y + Dirs[dir][1], z + Dirs[dir][2]);
}
//是否是合法的下标
int IsValid() {
return x >= 0 && x < xlen-1&& y >= 0 && y < ylen-1&& z >= 0 && z < zlen-1;
}
//是否是实心块
int IsFilled() {
return matrix[x][y][z] == 1;
}
//是否访问过
int GetVis() {
return matrix[x][y][z] == 2;
}
//标记访问
void SetVis() {
matrix[x][y][z] = 2;
}
//体积
int GetV() {
return (xPoint[x + 1] - xPoint[x]) * (yPoint[y + 1] - yPoint[y]) * (zPoint[z + 1] - zPoint[z]);
}
//表面积
int GetArea(int dir) {
if (Dirs[dir][0] != 0) { return (yPoint[y + 1] - yPoint[y])* (zPoint[z + 1] - zPoint[z]); }
else if (Dirs[dir][1] != 0) { return (xPoint[x+1] - xPoint[x])*(zPoint[z + 1] - zPoint[z]); }
return (xPoint[x + 1] - xPoint[x]) * (yPoint[y + 1] - yPoint[y]);
}
int x, y, z;
};
void GetUseful(int* a, int& len) {
sort(a, a + len);
len = unique(a, a + len) - a;
}
//实际坐标 对应的 有用下标
int GetID(int *a,int len, int value) {
return lower_bound(a, a + len, value) - a;
}
void FloodFill() {
int s = 0,v = 0;
Cell c,c2;
c.SetVis();
queue<Cell> q;
q.push(c);
//找空块
while (!q.empty()) {
c = q.front(); q.pop();
v += c.GetV();
for (int i = 0; i < 6; ++i) {
c2 = c.GetNext(i);
if(!c2.IsValid()) continue;
//从空块找到了实心的块 当前方向结束 累计表面积
if (c2.IsFilled()) s += c2.GetArea(i);
//当前空块是否已经找过 没找过就加入
else if(!c2.GetVis()){
c2.SetVis();
q.push(c2);
}
}
}
v = MLEN * MLEN * MLEN - v;
cout << s << " " << v << endl;
}
int main()
{
int n;
cin >> n;
while (n--) {
xlen = ylen = zlen = 0;
memset(matrix, 0, sizeof(matrix));
cin >> plen;
xPoint[xlen++] = yPoint[ylen++] = zPoint[zlen++] = 0;
xPoint[xlen++] = yPoint[ylen++] = zPoint[zlen++] = MLEN;
for (int i = 0; i < plen; ++i) {
cin >> xStart[i] >> yStart[i] >> zStart[i] >> xEnd[i] >> yEnd[i] >> zEnd[i];
//保存输入的坐标起点和终点
xEnd[i] += xStart[i];yEnd[i] += yStart[i];zEnd[i] += zStart[i];
//保存有用的坐标
xPoint[xlen++] = xStart[i]; xPoint[xlen++] = xEnd[i];
yPoint[ylen++] = yStart[i]; yPoint[ylen++] = yEnd[i];
zPoint[zlen++] = zStart[i]; zPoint[zlen++] = zEnd[i];
}
//排序并去掉重复的坐标 剩下有用的
GetUseful(xPoint, xlen);
GetUseful(yPoint, ylen);
GetUseful(zPoint, zlen);
for (int i = 0; i < plen; ++i) {
int xs = GetID(xPoint, xlen, xStart[i]),xe = GetID(xPoint, xlen, xEnd[i]);
int ys = GetID(yPoint, ylen, yStart[i]), ye = GetID(yPoint, ylen, yEnd[i]);
int zs = GetID(zPoint, zlen, zStart[i]), ze = GetID(zPoint, zlen, zEnd[i]);
//填充
for (int j = xs; j < xe; ++j) {
for (int k = ys; k < ye; ++k) {
for (int l = zs; l < ze; ++l)
matrix[j][k][l] = 1;
}
}
}
FloodFill();
}
return 0;
}
例题6-18(uva-12171)
最新推荐文章于 2021-07-01 11:41:40 发布