BFS(连通分量) - 肿瘤诊断 - 天梯赛L3-004
注意点:
三维矩阵连通分量的统计。
本题点数较多,递归容易爆栈(段错误)。
BFS过程中,一开始少加了一句:
if(st[x][y][z]) continue;
打印出了很多重复的点,才反应过来,我是在循环过程中,在某个点出队时才将其标记,
while(Q.size())
{
node t = Q.front();
Q.pop();
x = t.x, y = t.y, z = t.z;
if(st[x][y][z]) continue;
cnt ++;
st[x][y][z] = true;
for(int i=0;i<6;i++)
{
int u = x + dir[i][0], v = y + dir[i][1], w = z + dir[i][2];
if(u < 1 || u > n || v < 1 || v > m || w < 1 || w > l) continue;
if(a[u][v][w] && !st[u][v][w]) Q.push({u, v, w});
}
}
而分层扩展的过程中,两点间长度相同的路径可能有多条,这就导致了同一个点会被多个结点扩展
所以加上这句话过滤掉相同的点。
事实上,比较清晰的逻辑应该在点入队时就标记已经遍历到这个点了。如下:
void bfs(int x, int y, int z)
{
queue<node> Q;
Q.push({x, y, z});
cnt ++;
st[x][y][z] = true;
while(Q.size())
{
node t = Q.front();
Q.pop();
x = t.x, y = t.y, z = t.z;
for(int i=0;i<6;i++)
{
int u = x + dir[i][0], v = y + dir[i][1], w = z + dir[i][2];
if(u < 1 || u > n || v < 1 || v > m || w < 1 || w > l) continue;
if(a[u][v][w] && !st[u][v][w])
{
st[u][v][w] = true;
cnt ++;
Q.push({u, v, w});
}
}
}
}
代码:
#include<sstream>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1300, M = 130, L = 70;
int n, m, l, T;
bool a[N][M][L], st[N][M][L];
int ans, cnt;
int dir[6][3] = {{0, 0, -1}, {0, 0, 1}, {0, -1, 0}, {0, 1, 0}, {-1, 0, 0}, {1, 0, 0}};
struct node
{
int x, y, z;
}V[N * M * L];
void bfs(int x, int y, int z)
{
queue<node> Q;
Q.push({x, y, z});
while(Q.size())
{
node t = Q.front();
Q.pop();
x = t.x, y = t.y, z = t.z;
if(st[x][y][z]) continue;
cnt ++;
st[x][y][z] = true;
for(int i=0;i<6;i++)
{
int u = x + dir[i][0], v = y + dir[i][1], w = z + dir[i][2];
if(u < 1 || u > n || v < 1 || v > m || w < 1 || w > l) continue;
if(a[u][v][w] && !st[u][v][w]) Q.push({u, v, w});
}
}
}
int main()
{
scanf("%d%d%d%d", &n, &m, &l, &T);
int x;
for(int k=1;k<=l;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d", &x);
a[i][j][k] = x;
}
for(int k=1;k<=l;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j][k] && !st[i][j][k])
{
cnt = 0;
bfs(i, j, k);
if(cnt >= T) ans += cnt;
}
printf("%d\n", ans);
return 0;
}