1091. Acute Stroke

来源:互联网 发布:mac arp 嗅探工具dmg 编辑:程序博客网 时间:2024/05/01 18:24

题目

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

基本思路

考察BFS的基本操作。
本题理解起来相对生涩,借用了几个医学名词来吓唬人。其大意可理解为,给定一个三维数组,元素为0或1,若干个相邻的“1”称为一个块(不必两两相邻,只要与块中的某个“1”相邻,该“1”就归于这一块)。而块中“1”的个数不低于T个,则称其为stroke core。题目要求所有符合条件的stroke core的“1”的个数之和。
延伸
在解决这个问题之前,先从一个较为简单的题目入手,题目如下:
给出一个m*n的矩阵,矩阵中元素为 0或1,称位置(x,y)与其上下左右四个位置是相邻的,如果矩阵中有若干个1是相邻的,则这些1构成了一个块(规定每块中1的个数至少3个)
求给定矩阵的“块”的个数。
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0
上面的矩阵块数为3
分析:显然,这两个题目是一模一样的,区别只在于三维和二维。我们先从二维的入手。
定义数组int X[4] = {0,0,-1,1},int Y[4] = {1,-1,0,0} ,方便表示当前位置(x,y)的上下左右四个相邻的位置。可表示如下:

for(int i=0;i<4;i++){//遍历当前顶点的上下左右四个邻点             int newX = nowX + X[i];            int newY = nowY + Y[i];}

BFS的思想通过队列实现,基本写法如下:

void BFS(int s){//s为起点    queue<int> q;//定义队列    q.push(s);//将起始点入队    while(!q.empty()){//若队列非空        取出队首元素赋给top;        将队首元素pop出队;        访问队首元素;//即根据题意对其进行一些操作        将top的下一层结点中未曾入队的结点入队,同时层号加1,并标记入队。    }}
延伸例题代码
#include<cstdio>#include<queue>using namespace std;const int maxn = 25;struct node{//定义结点结构     int x,y;}Node; int m,n,matrix[maxn][maxn];//01矩阵bool inq[maxn][maxn];//坐标变换的增量数组 int X[4] = {0,0,-1,1};int Y[4] = {1,-1,0,0}; //判断当前点是否需要检查,若需要检查返回truebool isTest(int x,int y){    if(x < 0 || x >= n || y < 0 || y >= m) return false;//判断是否越界    else if(matrix[x][y] == 0 || inq[x][y] == true) return false;//判断是否为1或已经入队    else return true; }int BFS(int x,int y){    int count = 0;//每块中 1 的个数     queue<node> q;//定义node型队列     Node.x = x;    Node.y = y;    q.push(Node);//起点入队     inq[x][y] = true;//标记当前点入队     while(!q.empty()){        node top = q.front();//取出队首元素        count++;         q.pop();//队首元素出队        for(int i=0;i<4;i++){//遍历当前顶点的上下左右四个邻点             int newX = top.x + X[i];            int newY = top.y + Y[i];            if(isTest(newX,newY)){//若当前点的邻点需要检查                Node.x = newX;                Node.y = newY;                q.push(Node);//将新的点入队                inq[Node.x][Node.y] = true;//并标记             }         }     }    return count;//返回块中1的个数} int main(){    scanf("%d%d",&m,&n);    for(int x=0;x<m;x++){//输入“01”矩阵         for(int y=0;y<n;y++){            scanf("%d",&matrix[x][y]);        }    }    int ans = 0;//块数     for(int x=0;x<m;x++){//从(0,0)开始遍历矩阵        for(int y=0;y<n;y++){            if(matrix[x][y] == 1 && inq[x][y] == false){//若当前点为1且尚未入队,则由该点开始BFS遍历                if( BFS(x,y) >= 3) ans++;//满足条件,块数加1            }        }    }    printf("%d",ans);    return 0;}

理解到这里再回到原题,想必问题就迎刃而解了,思路完全相同,只是矩阵多了一维,多个for循环的事。BFS的实现要记住大致的模板,便于解题。

原题代码
#include<cstdio>#include<queue>using namespace std;const int MAXM = 1300;const int MAXN = 150;const int MAXL = 70;struct node{    int x,y,z;}Node;int matrix[MAXM][MAXN][MAXL];//01矩阵bool inq[MAXM][MAXN][MAXL] = {false}; int M,N,L,T;//M,N,L为矩阵的三维,T是最小的阈值 //坐标变化的增量数组int X[6] = {0,0,-1,1,0,0};int Y[6] = {1,-1,0,0,0,0};int Z[6] = {0,0,0,0,1,-1};//判断当前点是否需要检查  bool isTest(int x,int y,int z){    if(x < 0 || x >= M || y < 0 || y >= N ||z < 0 || z >= L) return false;//判断是否越界    else if(matrix[x][y][z] == 0 || inq[x][y][z] == true) return false;//判断是否为1或已经入队    else return true; }int BFS(int x,int y,int z){    int count = 0;//块中 1 的个数     queue<node> q;    Node.x = x;    Node.y = y;    Node.z = z;    q.push(Node);//起始点入队     inq[x][y][z] =  true;//标记入队     while(!q.empty()){        node top = q.front();//取出队首元素         count++;//块中 1 的个数加1         q.pop(); //队首元素出队         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(isTest(newX,newY,newZ)){                Node.x = newX, Node.y = newY, Node.z = newZ;                q.push(Node);                inq[newX][newY][newZ] = true;             }         }    }     return count;//返回块中1的个数 }int main(){    scanf("%d%d%d%d",&M,&N,&L,&T);     for(int z=0;z<L;z++){//输入三维矩阵         for(int x=0;x<M;x++){            for(int y=0;y<N;y++){                scanf("%d",&matrix[x][y][z]);            }        }    }    int ans = 0;//存放结果     for(int z=0;z<L;z++){//遍历矩阵         for(int x=0;x<M;x++){            for(int y=0;y<N;y++){                if(matrix[x][y][z] == 1 && inq[x][y][z] == false){                    int num = BFS(x,y,z);//BFS遍历                     if( num >= T) ans += num;                }            }        }    }    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击