1091 Acute Stroke (30 分)
题意
给出一个三维图(可以看成是有上下层(不止两层)的迷宫)由0和1构成,定义相邻:
一个块a的上下左右前后的块都算和a相邻。给了一张图表示红色的都和蓝色的相邻。相邻为1的块不少于一个数值(给出)时它们构成一个核心区,求出所有核心区中块为1的块的数量。(诺干个1相邻,如果这些1大于一定数量时这些1的区域就为核心区)
如111110 数量大于3时组成核心区 这五个1就构成一个核心区。块的数量为 5
思路
二位迷宫的升级版,和二维迷宫类似。设1为有效块,以每个有效块为起点进行广搜,广搜一次可以找到与该块相邻的有效块。在判断这些块的数量够不够。够的就加起来,不够的就不计。
广搜:用队列实现,队列先进先出的特性刚好符合广搜从近到远的要求。队头出队,搜索上下左右前后六个方向,遇到没有遍历过的有效块就加入队列,重复直到没有相邻的有效块结束这一次搜索。
注意再搜索周围六个方向时可能会越界,注意限制一下。越界pat测试会报出
代码
#include<stdio.h>
#include<queue>
using namespace std;
typedef struct node{
int x,y,z,p;
}node;
int vis[64][1290][130],mp[64][1290][130],m,n,l,t;
int up[7]={1,-1,0,0,0,0},left[7]={0,0,1,-1,0,0},ahead[7]={0,0,0,0,1,-1};
queue<node>q;
int bfs(int v)
{
// queue<node>q;
node next,pre;
int x,y,z;
while(!q.empty()){
next=q.front();
q.pop();
// x=next.x;
// y=next.y;
// z=next.z;
for(int i=0;i<6;i++){
x=next.x+up[i];
y=next.y+ahead[i];
z=next.z+left[i];
if(x>=0&&x<l&&y>=0&&y<m&&z>=0&&z<n){
if(mp[x][y][z]&&vis[x][y][z]==0){
pre.x=x;
pre.y=y;
pre.z=z;
pre.p=1;
q.push(pre);
vis[x][y][z]=1;
v+=1;
}
}
}
}
return v;
}
int main()
{
int total=0,v;
node nod;
while(!q.empty()){
q.pop();
}
scanf("%d%d%d%d",&m,&n,&l,&t);
for(int i=0;i<l;i++){
for(int j=0;j<m;j++){
for(int k=0;k<n;k++){
scanf("%d",&mp[i][j][k]);
vis[i][j][k]=0;
}
}
}
for(int i=0;i<l;i++){
for(int j=0;j<m;j++){
for(int k=0;k<n;k++){
if(vis[i][j][k]==0&&mp[i][j][k]){
nod.x=i;
nod.y=j;
nod.z=k;
nod.p=1;
q.push(nod);
vis[i][j][k]=1;
v=bfs(1);
if(v>=t){
total+=v;
}
}
}
}
}
printf("%d\n",total);
return 0;
}