poj 2882 Food Cubes
//sicily3 1114. Food Cubes
//一立方体,给出某些填充的三维点,求有多少孔穴
//要注意孔的定义:A hole is a continuous empty space surrounded by food cubes in all six directions.
//如果某区域与边界相临,那么它不能算做是孔.宽搜遍历时会忽略掉这种特殊情况,得到的孔数目比答案要多
//方法是扩大边界, 题意:all between 1 and 100 inclusive,所以可以扩大到 0-101。最后得到的孔的数目减去 1 即为答案
//为什么扩大边界后只要减去 1 就可以了,分两种情况讨论:
//1.如果原边界全部被填充,即原立方体的表面全部被覆盖,这时额外增加的边界将使孔数目增加 1 ,自然要减去 1
//2.如果原边界没有被全部填充,存在空白,那么新立方体内此空白(无论几处)会与新增加的边界空白形成一连续的空白区域,使得孔数目增加 1,但原立方体表面上的空白不能算做孔,所以结果要减去 1
#include<iostream> //BFS
#include<stdio.h>
#include<queue>
#include <cstring>
using namespace std;
bool cube[105][105][105],vis[105][105][105]; //如果是int 则TLE
int move[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
struct node
{
int x,y,z;
};
node pos,temp;
bool blank(int a,int b,int c)
{
return a>=0&&a<=101&&b>=0&&b<=101&&c>=0&&c<=101&&cube[a][b][c]==0;
}
void bfs(int i,int j,int k) //宽搜,从一个空白点搜索出整块连续未被访问过的空白区域: holes
{
queue<node> col;
pos.x=i;pos.y=j;pos.z=k;
col.push(pos);
while (!col.empty())
{
temp=col.front();
col.pop();
for(int l=0;l<6;++l)
{
int i1=temp.x+move[l][0],j1=temp.y+move[l][1],k1=temp.z+move[l][2];
if(blank(i1,j1,k1)&&!vis[i1][j1][k1])
{
vis[i1][j1][k1]=1;
pos.x=i1;pos.y=j1;pos.z=k1;
col.push(pos);
}
}
}
}
int main()
{
int cases,m,a,b,c;
cin>>cases;
while(cases--)
{
scanf("%d",&m);
memset(cube,0,sizeof(cube));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;++i)
{
scanf("%d%d%d",&a,&b,&c);
cube[a][b][c]=1; //表示已被填充
}
int sum=0;
for(int i=0;i<=101;++i)
for(int j=0;j<=101;++j)
for(int k=0;k<=101;++k)
if(vis[i][j][k]==0&&cube[i][j][k]==0)
{
bfs(i,j,k);
sum++;
}
printf("%d\n",sum-1);
}
return 0;
}