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 by 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 by 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
结题思路:
题意要求我们统计大块中风区域的总体积。
要求1:题目其实不复杂,但由于部分数据量较大,在用递归的方式计算时,可能会暴栈;
要求2:三维数据的链接表示为二维图中的“4联通”的方式,对于斜对角的连接性不做考虑。
程序步骤:
第一步、读入三维数组;
第二步、对于值为1的元素,开始遍历周围的点,将遍历到的连接部分的点标记为0,并统计标记的数量;
第三步、对于统计的标记数量大于阈值的判定为中风区。
第四步、累加中风区的体积,输出即可。
具体程序(递归,最后两个case暴栈)如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#define M 1300
#define N 130
#define S 65
using namespace std;
int width,height,sli,threshold;
int pics[S][M][N];
int floodfill(int k,int i,int j)//深度优先,最后的两个大case会无法通过,程序暴栈
{
int area=1;
pics[k][i][j]=2;
if(k>0&&pics[k-1][i][j]==1)
area+=floodfill(k-1,i,j);
if(k+1<sli&&pics[k+1][i][j]==1)
area+=floodfill(k+1,i,j);
if(i>0&&pics[k][i-1][j]==1)
area+=floodfill(k,i-1,j);
if(i+1<height&&pics[k][i+1][j]==1)
area+=floodfill(k,i+1,j);
if(j>0&&pics[k][i][j-1]==1)
area+=floodfill(k,i,j-1);
if(j+1<width&&pics[k][i][j+1]==1)
area+=floodfill(k,i,j+1);
return area;
}
int main() {
// your code goes here
cin>>height>>width>>sli>>threshold;
int i,j,k;
memset(pics,0,sizeof(pics));
for(k=0;k<sli;++k)
for(i=0;i<height;++i)
for(j=0;j<width;++j)
cin>>pics[k][i][j];
int count=0;
int area;
for(k=0;k<sli;++k)
for(i=0;i<height;++i)
for(j=0;j<width;++j)
if(pics[k][i][j]==1)
{
area=floodfill(k,i,j);
if(area>=threshold)
count+=area;
}
cout<<count<<endl;
return 0;
}
具体程序(AC,迭代的形式)如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <queue>
#define M 1300
#define N 130
#define S 65
using namespace std;
int width,height,sli,threshold;
struct pixel{
int k;
int i;
int j;
pixel(int k,int i, int j):k(k),i(i),j(j){}
};
int roundK[6]={-1,1,0,0,0,0};
int roundI[6]={0,0,-1,1,0,0};
int roundJ[6]={0,0,0,0,-1,1};
queue<pixel> vec;
int pics[S][M][N];
bool range(int k,int i,int j)
{
if(k>=0&&k<sli)
if(i>=0&&i<height)
if(j>=0&&j<width)
return true;
return false;
}
int floodfill(int k,int i,int j)//深度优先,最后的两个大case会无法通过,程序暴栈
{
int area=1;
pics[k][i][j]=0;
vec.push(pixel(k,i,j));
while(!vec.empty())
{
pixel tmp=vec.front();
vec.pop();
for(int i=0;i<6;++i)
{
int tk=tmp.k+roundK[i];
int ti=tmp.i+roundI[i];
int tj=tmp.j+roundJ[i];
if(range(tk,ti,tj)&&pics[tk][ti][tj])
{
vec.push(pixel(tk,ti,tj));
pics[tk][ti][tj]=0;
++area;
}
}
}
return area;
}
int main() {
// your code goes here
cin>>height>>width>>sli>>threshold;
int i,j,k;
while(!vec.empty())
vec.pop()
memset(pics,0,sizeof(pics));
for(k=0;k<sli;++k)
for(i=0;i<height;++i)
for(j=0;j<width;++j)
cin>>pics[k][i][j];
int count=0;
int area;
for(k=0;k<sli;++k)
for(i=0;i<height;++i)
for(j=0;j<width;++j)
if(pics[k][i][j]==1)
{
area=floodfill(k,i,j);
if(area>=threshold)
count+=area;
}
cout<<count<<endl;
return 0;
}