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

输入描述:

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

输出例子:

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); //bfs
bool 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,则计入综合S
					if (isStroke(aa))
					{
						s = 1;
						search(i, j, k);
						if (s>=t)
						{
							S += s;
						}
					}
				}
			}
		}
	}
	//输出总和S
	cout << 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;
	else
		return false;
}
//判断该点是否中风,及brain该点是否为1
bool 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感觉用的有点乱,判断是否为邻居点的时候感觉还可以写的简单点等等。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值