PAT-ADVANCED1091——Acute Stroke

我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED

原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805375457411072

题目描述:

题目翻译:

1091 急性中风

确定急性脑卒中的一个重要依据是脑卒中核心的体积。给定图像分析的结果,其中在每个MRI切片中识别核心区域,你的工作是计算中风核心的体积。

输入格式:

每个输入文件包含一个测试用例。在每个测试用例中,第一行给出4个正整数:M、N、L和T,其中M和N是每个切片的尺寸(切片的像素在M×N矩阵中,最大分辨率为1286 × 128);L(<= 60)是一个大脑的切片总数;T是判定界限(如果连接核心的容量小于T,则不得计算该核心)。

接下来给出L个脑切片。每个切片由0和1组成的M × N矩阵表示,其中1表示中风区域,0表示正常区域。 由于切片的厚度是常数,我们只需计算1的数量即可获得体积。 然而,大脑中可能存在几个分离的核心区域,并且仅计算其体积不小于T的核心区域。 如果它们共享公共侧,则连接两个像素并因此属于相同区域,如图1所示,其中所有6个红色像素连接到蓝色像素。

输出格式:

对每个测试用例,在一行中输出中风区域的总体积。

输入样例:

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

输出样例:

26

知识点:深度优先遍历、广度优先遍历

思路一:深度优先遍历(测试点4和5会爆系统栈引发段错误)

三维深度优先遍历,用一个二维数组int directions[3][6]来定义6个方向。

时间复杂度极高,可能达到O(6 ^ (M * N * L))。空间复杂度是O(M * N * L)。

C++代码:

#include<iostream>

using namespace std;

int M, N, L, T;
int brain[1286][128][60];
bool visited[1286][128][60] = {false};
int directions[3][6] = {0, 0, 1, 0, 0, -1, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0};
int count = 0;
int totalCount = 0;

bool valid(int i, int j, int k);
void dfs(int i, int j, int k);

int main(){
	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", &brain[i][j][k]);
			}
		}
	}
	for(int k = 0; k < L; k++){
		for(int i = 0; i < M; i++){
			for(int j = 0; j < N; j++){
				if(!visited[i][j][k] && brain[i][j][k] == 1){
					count = 0;
					dfs(i, j, k);
					if(count >= T){
						totalCount += count;
					}
				}
			}
		}
	}
	printf("%d\n", totalCount);
	return 0;
}

bool valid(int i, int j, int k){
	if(i >= 0 && i < M && j >= 0 && j < N && k >= 0 && k < L){
		return true;
	}else{
		return false;
	}
}

void dfs(int i, int j, int k){
	visited[i][j][k] = true;
	count++;
	for(int t = 0; t < 6; t++){
		int newI = directions[0][t] + i;
		int newJ = directions[1][t] + j;
		int newK = directions[2][t] + k;
		if(valid(newI, newJ, newK) && !visited[newI][newJ][newK] && brain[newI][newJ][newK] == 1){
			dfs(newI, newJ, newK);
		}
	}
}

C++解题报告:

思路二:广度优先遍历

三维广度优先遍历,和二维情况一样,只不过多了几个方向。用结构体node来存储入队元素的3个坐标值。

C++代码:

#include<iostream>
#include<queue>

using namespace std;

struct node {
	int i;
	int j;
	int k;
	node(int _i, int _j, int _k) : i(_i), j(_j), k(_k) {};
};

int M, N, L, T;
int brain[1286][128][60];
bool inq[1286][128][60] = {false};
int directions[3][6] = {0, 0, 1, 0, 0, -1, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0};
int count = 0;
int totalCount = 0;

bool valid(int i, int j, int k);
void bfs(int i, int j, int k);

int main() {
	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", &brain[i][j][k]);
			}
		}
	}
	for(int k = 0; k < L; k++) {
		for(int i = 0; i < M; i++) {
			for(int j = 0; j < N; j++) {
				if(!inq[i][j][k] && brain[i][j][k] == 1) {
					count = 0;
					bfs(i, j, k);
					if(count >= T) {
						totalCount += count;
					}
				}
			}
		}
	}
	printf("%d\n", totalCount);
	return 0;
}

bool valid(int i, int j, int k) {
	if(i >= 0 && i < M && j >= 0 && j < N && k >= 0 && k < L) {
		return true;
	} else {
		return false;
	}
}

void bfs(int i, int j, int k) {
	queue<node> q;
	q.push(node(i, j, k));
	inq[i][j][k] = true;
	while(!q.empty()) {
		node now = q.front();
		q.pop();
		count++;
		for(int t = 0; t < 6; t++) {
			int newI = directions[0][t] + now.i;
			int newJ = directions[1][t] + now.j;
			int newK = directions[2][t] + now.k;
			if(valid(newI, newJ, newK) && !inq[newI][newJ][newK] && brain[newI][newJ][newK] == 1) {
				q.push(node(newI, newJ, newK));
				inq[newI][newJ][newK] = true;
			}
		}
	}
}

C++解题报告:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值