PAT A1091 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

实现思路:

这是一道以迷宫问题为基础的拓展题,完全可以采用迷宫bfs的求解法来进行解答,只不过迷宫问题中只涉及到上下左右四个方向,而本题有6个方向,因为大脑切片不止一片,可以看作是一个空间体,下面给出一个图片便于理解,

对于本题就是直接采用bfs遍历,是一个判断连通图中1个数的一种题目,但是连通块不止一个所以需要使用访问数组vist来进行判断,本题中的访问数组和之前的bfs不同需要在入队的时候就将访问位设置为true,每一个连通块遍历后都要进行统计1的个数判断是否大于门槛数值T,大于才计入最终结果中输出。

AC代码:

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int n,m,l,t,slice[1290][130][70];
bool  vist[1290][130][70];//设置方向左前右后上下
int X[6]= {-1,0,1,0,0,0};
int Y[6]= {0,1,0,-1,0,0};
int Z[6]= {0,0,0,0,1,-1};

struct node {
	int x,y,z;
};

int bfs(int x,int y,int z) {
	int cnt=0;
	queue<node> q;
	q.push(node {x,y,z});
	vist[x][y][z]=true;
	while(!q.empty()) {
		node now=q.front();
		q.pop();
		cnt++;//计算当前连通块内1的个数
		for(int i=0; i<6; i++) {
			int _x=now.x+X[i],_y=now.y+Y[i],_z=now.z+Z[i];
			if(_x>=0&&_x<n&&_y>=0&&_y<m&&_z>=0&&_z<l&&!vist[_x][_y][_z]&&slice[_x][_y][_z]) {//当坐标在范围内且未访问过为1的块
				vist[_x][_y][_z]=true;//必须要在这里进行置访问位为1 否则会死循环因为存在重复入队的问题
				q.push(node {_x,_y,_z});
			}
		}
	}
	return cnt;
}

int main() {
	memset(vist,false,sizeof(vist));
	cin>>n>>m>>l>>t;
	for(int z=0; z<l; z++) {
		for(int x=0; x<n; x++) {
			for(int y=0; y<m; y++) {
				scanf("%d",&slice[x][y][z]);
			}
		}
	}
	int ans=0;
	for(int z=0; z<l; z++) {
		for(int x=0; x<n; x++) {
			for(int y=0; y<m; y++) {
				if(!vist[x][y][z]&&slice[x][y][z]) {
					int val=bfs(x,y,z);
					if(val>=t) ans+=val;//当前连通区域内1的个数大于门槛值的时候则进行统计
				}
			}
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2021-02-25 18:45  coderJ_ONE  阅读(67)  评论(0)    收藏  举报