天天看点

PAT A1091 Acute Stroke

PAT A1091 Acute Stroke

题目说明:

提供一个三维空间,一个值为1的结点和它上下左右前后值为1的结点构成一个块;要求统计结点数大于等于T的块,合计的结点数。

思路:

1.建立三维数组,保存数据;为方便访问当前结点相邻位置,建立一个结点结构保存(x,y,z)坐标;数组要建立在主函数外面,最后两个测试数据量过大,建立在主函数内会报错;

2.三层循环遍历每一个结点;

1)若结点值为1且未被访问,说明遇到了一个新的块,按广度优先搜索遍历与当前结点相邻且值为1的结点;若块中的1数量>=T,则答案增加相应数量,否则跳过;

AC代码:

#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;

//保存 前后上下左右 6个方位的相对坐标 
int ix[6]={-1,1,0,0,0,0};//左右上下前后 
int iy[6]={0,0,0,0,1,-1};
int iz[6]={0,0,1,-1,0,0};

int M,N,L,T;
struct Node
{
	short data;
	int x,y,z;
	bool inq;//标记是否入队 
};
Node table[60][1286][128];

int main()
{
	freopen("text.txt","r",stdin);
	cin>>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",&table[i][j][k].data);
				table[i][j][k].x=k;
				table[i][j][k].y=j;
				table[i][j][k].z=i;
				table[i][j][k].inq=false;
				
			}
		}
	}
	int ans=0,count;//ans保存答案,count为当前块1的个数 
	Node temp;
	queue<Node> Q;//队列,广度优先遍历 使用 
	int x,y,z;//存放坐标
	//三层循环,遍历数据 
	for(int i=0;i<L;i++)
	{
		for(int j=0;j<M;j++)
		{
			for(int k=0;k<N;k++)
			{
				//当 访问的结点为1 且 未进入过队列 说明访问到一个新块 
				//则 结点进入队列并按广度搜索 
				if(table[i][j][k].inq==false&&table[i][j][k].data==1)
				{
					count=1;//当前有一个 1 
					Q.push(table[i][j][k]);
					table[i][j][k].inq=true;// 标记入队 
					while(!Q.empty())//广度优先搜索 
					{
						temp=Q.front();Q.pop();
						for(int t=0;t<6;t++)
						{
							//更新相邻数据的坐标 
							z=temp.z+iz[t];
							y=temp.y+iy[t];
							x=temp.x+ix[t];
							//判断坐标是否合法 
							if(z<0||z>=L||y<0||y>=M||x<0||x>=N) continue;
							//若相邻位置未被访问 且 数据为1 则入队 
							if(table[z][y][x].inq==false&&table[z][y][x].data==1)
							{
								Q.push(table[z][y][x]);
								table[z][y][x].inq=true;
								count++;//当前 块 计数加1 
							}
						}//t
					}//while
					if(count>=T) ans+=count;//若块的计数大于T 则 修改ans 
				}//if	
			}//k
		}//j
	}//i
	cout<<ans;
}