目录

​1,题目描述​

​题目大意​

​输入​

​补充​

​2,思路​

​数据结构​

​算法​

​3,AC代码​

​4,解题过程​

​第一搏​

​第二搏​

​第三搏​


1,题目描述

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_三维BFS 连通分量

Sample Input:

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

 

Sample Output:

26

题目大意

求出图片中每块(连通分量)1的个数,当个数超过阈(( ﹁ ﹁ ) ~→yu)值时,算作肿瘤,加入ans中;

  • Two pixels areconnectedand hence belong to the same region if they share a common side :注意这里的pixel是像素点不是slice,而是题目中的0/1

输入

  1. 第一行:M,N,L(长宽高),T判断阈值 ;
  2. 剩余:给出L片中,每片(M* N个像素点)的像素点值;

补充

2,思路

参考大佬​​@日沉云起【pat甲级1091. Acute Stroke (30 point(s))】​

(三维M*N*L图形,BFS搜索。由于DFS是递归进行,深度过大时,可能出现溢出,BFS则是利用队列,不会出现这种情况)

数据结构

  • int direction[6][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}}:方向矩阵,分别代表6个方向;
  • bool graph[130][130][80]:存放三维图片;
  • struct node{
    int x, y, z;
    node(int xx, int yy, int zz) : x(xx), y(yy), z(zz) {}   // !!!构造函数 学到了
    };像素点位置;

算法

  1. BFS算法:常规算法,注意向六个方向扩展时,要先判断是否越界,再判断是否可以入队:
  2. PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_PAT_04

  3. 遍历每个连通分量只取num大于阈值T的:
  4. PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_PAT_05

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;

int M, N, L, T, ans = 0;//M与N每片的规格(长和宽) L大脑中切片数目(高) T判断的阈值 ans结果
int direction[6][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
bool graph[130][130][80]; // !!!边界要尽可能大一点
struct node{
int x, y, z;
node(int xx, int yy, int zz) : x(xx), y(yy), z(zz) {} // !!!构造函数 学到了
};
int BFS(node p){
queue<node> q;
q.push(p);
graph[p.x][p.y][p.z] = false; // !!!这样可以巧妙地避免此方块再次被访问
int num = 1;
while(!q.empty()){
p = q.front();
q.pop();
for(int i = 0; i < 6; i++){
int x = p.x + direction[i][0], y = p.y + direction[i][1], z = p.z + direction[i][2];
if(x >= 0 && x < M && y >= 0 && y < N && z >= 0 && z < L && graph[x][y][z]){ // !!!先讨论边界 再判断graph
num++;
q.push(node(x, y, z)); //构造函数真香!
graph[x][y][z] = false; // 入队的时候就设置已访问
}
}
}
return num;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d %d %d %d", &M, &N, &L, &T);
for(int k = 0; k < L; k++)//L片
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
scanf("%d", &graph[i][j][k]);
for(int i = 0; i < M; i++) //for循环还可以这样写 又学了一手
for(int j = 0; j < N; j++)
for(int k = 0; k < L; k++)
if(graph[i][j][k]){
int tem = BFS(node(i, j, k)); //构造函数真香!
if(tem >= T)
ans += tem;
}
cout<<ans;
return 0;
}

 

4,解题过程

第一搏

实在没法理解题意(太菜了(;´༎ຶД༎ຶ`)),求助大神@日沉云起,终于弄明白了题意:三维BFS(由于DFS是递归进行,深度过大时,可能出现溢出,BFS则是利用队列,不会出现这种情况)

段错误。。。什么鬼

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_三维BFS 连通分量_06

 

第二搏

判断条件一定要分清先后顺序。。。

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_C++_07

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_PAT_08

第三搏

(我跟着大佬的代码,一步一步敲出来的,怎么会出错(╯‵□′)╯︵┻━┻。。。)

但,唯独漏了这一点

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_C++_09

;虽然题目上说L是≤60的,也就是0-59,但还是取大一点为好。。。

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_1091_10

PAT_甲级_1091 Acute Stroke (30point(s)) (C++)【三维BFS/连通分量】_1091_11