PTA团体程序设计天梯赛 L3-004 肿瘤诊断 (Java)(满分不超时)
·
在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环。给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积。
输入格式:
输入第一行给出4个正整数:M、N、L、T,其中M和N是每张切片的尺寸(即每张切片是一个M×N的像素矩阵。最大分辨率是1286×128);L(≤60)是切片的张数;T是一个整数阈值(若疑似肿瘤的连通体体积小于T,则该小块忽略不计)。
最后给出L张切片。每张用一个由0和1组成的M×N的矩阵表示,其中1表示疑似肿瘤的像素,0表示正常像素。由于切片厚度可以认为是一个常数,于是我们只要数连通体中1的个数就可以得到体积了。麻烦的是,可能存在多个肿瘤,这时我们只统计那些体积不小于T的。两个像素被认为是“连通的”,如果它们有一个共同的切面,如下图所示,所有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
代码长度限制
16 KB
时间限制
600 ms
内存限制
64 MB
栈限制
8192 KB
Java实现:
/**
* 【题目核心思路】
* 1. 问题转化:
* - 题目给的是 L 张 M*N 的切片,其实就是一个 M*N*L 的三维空间。
* - “连通体”体积 = 三维空间中 6-连通(上下、左右、前后)的“1”的个数。
* - 目标:找出所有体积 >= T 的连通块,求它们的体积总和。
* * 2. 算法选型:
* - 选用 BFS 广搜:三维空间像素多达百万级,DFS 递归太深会导致栈溢出。
*/
import java.util.*;
import java.io.*;
public class Main {
static int M, N, L, T;
static byte[] matrix; // 扁平化存储:matrix[l * M * N + m * N + n]
static int MN; // 缓存切片面积,减少重复乘法
public static void main(String[] args) throws Exception {
Reader sc = new Reader();
M = sc.nextInt();
N = sc.nextInt();
L = sc.nextInt();
T = sc.nextInt();
MN = M * N;
int totalSize = L * MN;
matrix = new byte[totalSize];
// 字节流高速灌入数据
for (int i = 0; i < totalSize; i++) {
matrix[i] = (byte) sc.nextInt();
}
int totalVolume = 0;
int[] queue = new int[totalSize]; // 整个程序共用一个静态队列,避免反复分配内存
for (int i = 0; i < totalSize; i++) {
// 发现疑似肿瘤起点
if (matrix[i] == 1) {
int volume = bfs(i, queue);
if (volume >= T) totalVolume += volume;
}
}
System.out.println(totalVolume);
}
/**
* BFS 核心:像水流一样扩散搜寻连通的 1
*/
private static int bfs(int start, int[] queue) {
int head = 0, tail = 0;
queue[tail++] = start; // 起点入队
matrix[start] = 0; // 标记已处理
while (head < tail) {
int curr = queue[head++];
// 将一维索引还原为三维坐标,用于边界检查
int curL = curr / MN;
int curM = (curr % MN) / N;
int curN = curr % N;
// 检查 6 个连通方向(上下前后左右)
// 每次入队前直接改 matrix 状态,防止同一个点被重复入队
// 1. L 轴上下
if (curL + 1 < L) { check(curr + MN, queue, tail); if (found) tail++; }
if (curL - 1 >= 0) { check(curr - MN, queue, tail); if (found) tail++; }
// 2. M 轴前后
if (curM + 1 < M) { check(curr + N, queue, tail); if (found) tail++; }
if (curM - 1 >= 0) { check(curr - N, queue, tail); if (found) tail++; }
// 3. N 轴左右
if (curN + 1 < N) { check(curr + 1, queue, tail); if (found) tail++; }
if (curN - 1 >= 0) { check(curr - 1, queue, tail); if (found) tail++; }
}
return tail; // tail 即为该连通块的总体积
}
static boolean found;
/**
* 辅助判定:合法则入队并标记
*/
private static void check(int nIdx, int[] queue, int tail) {
found = false;
if (matrix[nIdx] == 1) {
matrix[nIdx] = 0;
queue[tail] = nIdx;
found = true;
}
}
static class Reader {
BufferedInputStream in = new BufferedInputStream(System.in);
int nextInt() throws Exception {
int res = 0;
int b = in.read();
while (b != -1 && (b < '0' || b > '9')) b = in.read();
if (b == -1) return -1;
while (b != -1 && b >= '0' && b <= '9') {
res = res * 10 + (b - '0');
b = in.read();
}
return res;
}
}
}

更多推荐




所有评论(0)