PAT甲级1091
原题:
1091 Acute Stroke (30 分)
One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core.
Input Specification:
Each input file contains one test case. For each case, the first line contains 4 positive integers: M, N, L and T, where M and N are the sizes of each slice (i.e. pixels of a slice are in an M×N matrix, and the maximum resolution is 1286 by 128); L (≤60) is the number of slices of a brain; and T is the integer threshold (i.e. if the volume of a connected core is less than T, then that core must not be counted).
Then L slices are given. Each slice is represented by an M×N matrix of 0’s and 1’s, where 1 represents a pixel of stroke, and 0 means normal. Since the thickness of a slice is a constant, we only have to count the number of 1’s to obtain the volume. However, there might be several separated core regions in a brain, and only those with their volumes no less than T are counted. Two pixels are connected and hence belong to the same region if they share a common side, as shown by Figure 1 where all the 6 red pixels are connected to the blue one.
Output Specification:
For each case, output in a line the total volume of the stroke core.
Sample Input:
3 4 5 2
1 1 1 1
1 1 1 1
1 1 1 1
0 0 1 1
0 0 1 1
0 0 1 1
1 0 1 1
0 1 0 0
0 0 0 0
1 0 1 1
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 1
1 0 0 0
Sample Output:
26
注意点:
1、题目主要考的是BFS,每次进队节点时候要记录该节点已经进过队
2、三维坐标要设三个偏移量数组
3、楼主花的时间大多在主函数里的BFS,这里用的是三重循环判断是否访问过的方法不断往外圈扩散,一开始比较担心会超时,用过一些别的方法,但都不能全部遍历完,像是一些除了上下两层是1中间全是0的极端情况就不太好考虑了(希望有大佬能给出更优化的算法)
4、由于偏移量数组有负数,所以有效性函数里要加上<0的判断
#include <iostream>
#include <queue>
using namespace std;
const int MAXL=70,MAXM=1300,MAXN=130;
struct Node{
int x,y,z; //每个像素点的坐标
int data; //每个像素点保存的数据
}Start,End;
int X[6]={1,-1,0,0,0,0},Y[6]={0,0,1,-1,0,0},Z[6]={0,0,0,0,1,-1}; //偏移量
int M,N,L,T,t=0,sum=0; //每个切片M*N像素矩阵,L切片的数量,T每个核心区至少含有的1数量,sum记录总1数,t记录是否满足核心区的条件数量,total记录访问的总数
bool flag[MAXL][MAXM][MAXN]={false}; //记录每个像素点是否已经访问过,初始全为false
int slice[MAXL][MAXM][MAXN]={0}; //存放每个像素点的数据
bool valid(Node a){ //判断给出的点坐标是否有效
if(a.x<0||a.x>=L||a.y<0||a.y>=M||a.z<0||a.z>=N||a.data==0||flag[a.x][a.y][a.z]==true) return false;
return true;
}
int BFS(int x,int y,int z){
int cnt=0; //cnt记录每个区块1的个数
queue<Node> q;
Node s;
s.x=x,s.y=y,s.z=z;
q.push(s);
flag[s.x][s.y][s.z]=true;
while(!q.empty()){
Node a=q.front();
q.pop();
cnt++;
for(int i=0;i<6;i++){
Node b=a;
b.x+=X[i],b.y+=Y[i],b.z+=Z[i];
b.data=slice[b.x][b.y][b.z];
if(valid(b)) //若b是有效像素点
q.push(b),flag[b.x][b.y][b.z]=true; //记录是否访问过
}
}
if(cnt>=T) return cnt;
else return 0;
}
int main(){
int cnt=0; //记录总共的像素点数
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",&slice[i][j][k]);
Start.x=0,Start.y=0,Start.z=0,Start.data=slice[0][0][0];
End.x=L-1,End.y=M-1,End.z=N-1,End.data=slice[L-1][M-1][N-1];
for(int i=0;i<L;i++)
for(int j=0;j<M;j++)
for(int k=0;k<N;k++)
if(slice[i][j][k]==1&&flag[i][j][k]==false)
sum+=BFS(i,j,k);
printf("%d\n",sum);
system("pause");
return 0;
}