PAT Acute Stroke (30)

来源:互联网 发布:驾驶证制作软件生成器 编辑:程序博客网 时间:2024/04/29 06:15

题目描述

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.

输入描述:

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(感觉这句话表述的不清楚,我看了解释才知道先是M*N个数组表示一层的切片图,然后接下来继续,总共有L层,把每层叠加在一起就是一个三维的图像了).  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.(这句话也是有点醉,主要是图与点不一样,直接说点的上下左右就是“connected”及相邻的不就行了吗,画个2.5维图,真的想骂人)
Figure 1

输出描述:

For each case, output in a line the total volume of the stroke core.

输入例子:

3 4 5 2 //m=3,n=4,l=5,t=2
//第一层(因为每层3*4个点)1 1 1 11 1 1 11 1 1 1
//第二层(下面类似,就不继续标记了)0 0 1 10 0 1 10 0 1 11 0 1 10 1 0 00 0 0 01 0 1 10 0 0 00 0 0 00 0 0 10 0 0 11 0 0 0

输出例子:

26



一:题目解释。
  看了我上面的标注,应该能大体了解题目的意思了。反正我当时是看了好久才明白什么意思,有点小郁闷,所以写下来解释下。
  总共l*m*n个点,这些点有些事1,有些点为0,题目的目的就是找出为1并连着的点,何为相连呢?即三维图中上下左右前后的点,如果也为1,则可以继续往外扩展,即相连,我们要找到所有的相连的块,然后只要大于T就计入总数并输出总数。
二:解题思路
 看上去没有思路,大概有点想法,类似图的搜索是不是?但是这是三维的瞬间就虚了是不是,没关系,淡定,一步一步来。
 1.总体就是先找到一个未访问的点(此题还可以直接找未中风的未访问的点对不对?),然后向周围搜,如果是邻居并满足条件就把邻居加进来并标记为搜过了,然后继续向邻居的邻居扩展,直到这个连接块被找完。
 2.循环对未访问的中风的点来搜索。
 难点:无非就是bfs的时候,找邻居麻烦了一点对不对,但是三维的总共也只有6个邻居,所以虚什么,就是干!
 3.如果对bfs不熟悉,建议先看我的这篇专门讲bfs的博客http://blog.csdn.net/qq_16949707/article/details/51490764
三:自己的代码
#include<iostream>#include<queue>using namespace std;struct Node{int x, y, z;Node(){}Node(int _x, int _y, int _z) :x(_x), y(_y), z(_z){}};vector<vector<vector<int> > >brain;    //脑切片图vector<vector<vector<bool> > >visited; //标记访问图int m, n, l, t,s=1,S=0;      //s为单个联通图的为1的个数,S是总个数queue<Node> que;            //bfs算法中用到的先进先出堆void search(int i, int j, int k); //bfsbool isBrain(Node node);    //判断是否点node是在 脑切片图 brain里面bool isStroke(Node node);  //判断点node是否中分Node adjNode(Node node, int i);  //点node的邻居上下左右前后int main(){cin >> m >> n >> l >> t;//brain 和visited 置为 l m n 大小并赋初值brain.resize(l, vector<vector<int> >(m,vector<int> (n)));   visited.resize(l, vector<vector<bool> >(m, vector<bool>(n,false)));//输入图for (int i = 0; i < l; i++){for (int j = 0; j < m; j++){for (int k = 0; k < n; k++){cin >> brain[i][j][k];}}}//对于每个没有访问过的点都找一下for (int i = 0; i < l; i++){for (int j = 0; j < m; j++){for (int k = 0; k < n; k++){Node aa = Node(i, j, k);//如果改点没有访问if (!visited[i][j][k]&&brain[i][j][k]==1){//标记为访问visited[i][j][k] = true;//如果改点为中风,继续往下访问(search),如果集合点s大于t,则计入综合Sif (isStroke(aa)){s = 1;search(i, j, k);if (s>=t){S += s;}}}}}}//输出总和Scout << S << endl;return 0;}void search(int i, int j, int k){//将改点压入堆que.push(Node(i, j, k));//下面是找到符合条件的邻居,并把邻居压入堆while (!que.empty()){//取堆顶的元素Node top = que.front();//cout << "top: " << top.x << " " << top.y << " " << top.z << endl;visited[top.x][top.y][top.z] = true;que.pop();//找到堆顶元素的邻居Node adjTop;for (int i = 0; i < 6; i++){adjTop = adjNode(top, i);//cout << "adjTop: " << adjTop.x << " " << adjTop.y << " " << adjTop.z << endl;if (isBrain(adjTop) && !visited[adjTop.x][adjTop.y][adjTop.z]){if (isStroke(adjTop)){//将符合条件的邻居依次压入堆,并标记为访问!(已经计入总数了就可以标记为访问了)visited[adjTop.x][adjTop.y][adjTop.z] = true;//重要!!!que.push(adjTop);s++;}}}}}//判断是否在边界内的函数bool isBrain(Node node){if (node.x >= 0 && node.x < l&&node.y >= 0 && node.y < m&&node.z >= 0 && node.z < n)return true;elsereturn false;}//判断该点是否中风,及brain该点是否为1bool isStroke(Node node){if (brain[node.x][node.y][node.z]==1){return true;}else{return false;}}//点node的邻居Node adjNode(Node node,int i){Node a=node;if (i==0)a.z = node.z + 1;if (i==1)a.z = node.z - 1;if (i == 2)a.y = node.y + 1;if (i == 3)a.y = node.y - 1;if (i == 4)a.x = node.x + 1;if (i == 5)a.x = node.x - 1;return a;}
四:自己代码有待改进的地方
      1.不需要设个visited,因为brian[i][j][k]为1,即访问即可,访问完直接将其置为0代表访问过了。这样简便很多。
      2.vector感觉用的有点乱,判断是否为邻居点的时候感觉还可以写的简单点等等。


0 0
原创粉丝点击