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.
Figure 1
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 参见《算法笔记》BFS例一:书p276-p278)
脑子由薄片组成,MxN是一片薄片的长与宽,L是片数,T是单个中风核心的体积的阈值。
//若三维矩阵中有若干个邻接的像素1,则这些像素1构成了1块中风核心。
可能出现多个中风核心区域,必须满足条件:单个体积>=T,求中风核心的总体积之和。
-
注意矩阵数据的输入是按层按行按列的
-
三维数组matrix记录输入的0、1数据;三维数组v记录对应像素是否被访问;
遍历每一个像素1,查看其是否被访问,查看和它邻接的6个像素是否为1且是否被访问过,继续查看与邻接像素们邻接的像素是否被访问过。。直到找不到与他们邻接的像素,确定了一个“块”。
继续遍历每一个像素1,重复以上步骤,直到遍历完所有像素1,得出总块数。
-
judge函数判断该像素是否需要访问:是否出界(边界像素的邻接像素不到6个),像素是否为1,是否已被访问。
-
确定一个“块”时运用队列:
-
遍历每一个像素1,查看其是否被访问,若没有则进入队列;
-
取队头元素,查看和它邻接的6个像素是否为1且是否被访问过,没有则进入队列并设置为被访问。
-
重复步骤2,直到队列为空。(这一步做的是:查找该点和邻接像素、邻接像素的邻接像素等,尽可能扩大搜索像素1的范围)
-
-
设置三个增量数组,方便查找6个邻接像素
-
注意:队列中的元素只是复制的副本,某个元素入队后更改该元素的值,不会影响队列内该元素原本的值。
代码
#include<iostream>
#include<queue>
using namespace std;
int M,N,L,T;
const int maxM=1286,maxN=128,maxL=60;
int matrix[maxM][maxN][maxL];
bool v[maxM][maxN][maxL]= {false};
//三个增量数组
int X[]= {0,0,1, 0, 0,-1};
int Y[]= {0,1,0, 0,-1, 0};
int Z[]= {1,0,0,-1, 0, 0};
struct Node {
int x,y,z;
} node;
/*判断该像素是否需要访问*/
bool judge(int x,int y,int z) {
if(x<0||x>=M||y<0||y>=N||z<0||z>=L) return false;
if(matrix[x][y][z]==0||v[x][y][z]==true) return false;
return true;
}
/*一个像素出发bfs*/
int bfs(int x,int y,int z) {
int count=0;//一个块内的像素
queue<Node> que;
node.x=x,node.y=y,node.z=z;
que.push(node);
v[x][y][z]=true;
while(!que.empty()) {
Node top=que.front();
que.pop();
count++;
for(int i=0; i<6; i++) {
int newX=top.x+X[i];
int newY=top.y+Y[i];
int newZ=top.z+Z[i];
if(judge(newX,newY,newZ)) {
v[newX][newY][newZ]=true;
node.x=newX,node.y=newY,node.z=newZ;
que.push(node);
}
}
}
if(count>=T)
return count;
else
return 0;
}
int main() {
//设置01矩阵
scanf("%d %d %d %d
",&M,&N,&L,&T);
for(int k=0; k<L; k++)
for(int i=0; i<M; i++)
for (int j=0; j<N; j++) {
scanf("%d",&matrix[i][j][k]);
}
//遍历每一个像素
int ans=0;//总体积
for(int i=0; i<M; i++)
for(int j=0; j<N; j++)
for (int k=0; k<L; k++)
if(matrix[i][j][k]==1&&v[i][j][k]==false) {
ans+=bfs(i,j,k);
}
cout<<ans<<endl;
return 0;
}
注意
-
如果已经加了头文件,但出现报错信息
std::xxx
,可能是没声明命名空间语句using namespace std;
-
出现报错
Id returned 1 exit status
,可能是开了多个运行窗口,关了就行。
BUG
- 注意矩阵数据的输入是按层按行按列的。
正确:
//设置01矩阵
scanf("%d %d %d %d
",&M,&N,&L,&T);
for(int k=0; k<L; k++)
for(int i=0; i<M; i++)
for (int j=0; j<N; j++) {
scanf("%d",&matrix[i][j][k]);
错误:
//设置01矩阵
scanf("%d %d %d %d
",&M,&N,&L,&T);
for(int i=0; i<M; i++)
for(int j=0; j<N; j++)
for (int k=0; k<L; k++) {
scanf("%d",&matrix[i][j][k]);
}
单词
-
volume:体积,容量
Since the thickness of a slice is a constant, we only have to count the number of 1's to obtain the volume.
-
the maximum resolution is
1286 by 128
:1286x128 -
share a common side
:共用同一条边