PAT A1091 Acute Stroke

思路:本题为三维BFS,本质上和二维BFS相同,不过从上下左右4种方向拓展为上下左右前后6种方向。

一个连通空间即为一个核,达到阈值T的核可以算进总体积中。

注意BFS中每次调用BFS相当于走过了一个连通区域,需要设置visit数组防止重复访问已经访问的坐标。

#include<cstdio>
#include<queue>
using namespace std;

int M, N, L, T, ans;

typedef struct {
    int x, y, z;
} Node;

int dx[6] = {0, 0, 0, 0, 1, -1};
int dy[6] = {0, 0, 1, -1, 0, 0};
int dz[6] = {1, -1, 0, 0, 0, 0};

int graph[1290][130][61];
bool visit[1290][130][61];

bool judge(int x, int y, int z) {
    if(x < 0 || x >= M || y < 0 || y >= N || z < 0 || z >= L) {
        return false;
    }
    if(graph[x][y][z] == 0 || visit[x][y][z] == true) {
        return false;
    }
    return true;
}

int BFS(int x, int y, int z) {
    queue<Node> q;
    Node temp;
    temp.x = x;
    temp.y = y;
    temp.z = z;
    q.push(temp);
    visit[x][y][z] = true;
    int res = 0;
    while(!q.empty()) {
        Node node = q.front();
        q.pop();
        res++;
        for(int i = 0; i < 6; i++) {
            int nx = node.x + dx[i];
            int ny = node.y + dy[i];
            int nz = node.z + dz[i];
            if(judge(nx, ny, nz)) {
                temp.x = nx;
                temp.y = ny;
                temp.z = nz;
                q.push(temp);
                visit[nx][ny][nz] = true;
            }
        }
    }
    if(res < T) return 0;
    return res;
}

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", &graph[i][j][k]);
    for(int z = 0; z < L; z++) 
        for(int x = 0; x < M; x++)
            for(int y = 0; y < N; y++)
                if(graph[x][y][z] == 1 && visit[x][y][z] == false)
                    ans += BFS(x, y, z);
    printf("%d", ans);
    return 0;
}