宽搜手工写队列

 

二维数组区块计数

  • 描述:

输入一个只包含0和1的二维数组,上下左右和对角相邻的1组成一个区块,0不形成区块,求数组中的区块个数。

  • 输入:

第一行输入两个正整数N和M,N表示数组行数,M表示数组列数。

接下来N行,每行表示数组对应的一行,每行包含M个整数,整数之间用空格隔开。

  • 输出:

输出一个整数,表示数组中区块的个数。

  • 数据范围:

$0 \le N,M,N*M \le 10^6$

  • 样例输入:

3 3
0 1 0
1 0 0
1 0 1

  • 样例输出:

2

  • 样例解释:

数组右下角的1单独构成一个区块,其他的3个1对角或上下相邻,构成另一个区块。

  • 解题思路:宽搜/深搜

  • 参考代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    //dfs
    #include<iostream>
    #include<algorithm>

    using namespace std;

    typedef pair<int,int> PII;
    const int N=1000010;
    int n,m;
    int g[N];

    void dfs(int x,int y) {
    g[x*m+y]=0;
    for(int i=-1;i<=1;i++)
    for(int j=-1;j<=1;j++) {
    int a=x+i,b=y+j;
    if(a>=0&&a<n&&b>=0&&b<m&&g[a*m+b])
    dfs(a,b);
    }
    }

    int main() {
    scanf("%d%d",&n,&m);
    for(int i=0,k=0;i<n;i++)
    for(int j=0;j<m;j++,k++)
    scanf("%d",&g[k]);
    int res=0;
    for(int i=0;i<n;i++)
    for(int j=0;j<m;j++) {
    if(g[i*m+j]) {
    res++;
    dfs(i,j);
    }
    }
    printf("%d\n",res);
    return 0;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//bfs,用STL中的queue
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

typedef pair<int,int> PII;
const int N=1000010;

int n,m;
int g[N];

void bfs(int sx,int sy) {
queue<PII> q;
q.push({sx,sy});
g[sx*m+sy]=0;

while(q.size()) {
auto t=q.front();
q.pop();
int x=t.first,y=t.second;

for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++) {
int a=x+i,b=y+j;
if(a>=0&&a<n&&b>=0&&b<m&&g[a*m+b]) {
g[a*m+b]=0;
q.push({a,b});
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=0,k=0;i<n;i++)
for(int j=0;j<m;j++,k++)
scanf("%d",&g[k]);

int res=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(g[i*m+j]) {
res++;
bfs(i,j);
}
printf("%d\n",res);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//bfs,用手工写的队列
#include<iostream>
#include<algorithm>
using namespace std;

typedef pair<int,int> PII;
const int N=1000010;

int n,m;
int g[N];
PII q[N];

void bfs(int sx,int sy) {
int hh=0,tt=0;
q[0]={sx,sy};
g[sx*m+sy]=0;
while(hh<=tt) {
PII t=q[hh++];
int x=t.first,y=t.second;
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++) {
int a=x+i,b=y+j;
if(a>=0&&a<n&&b>=0&&b<m&&g[a*m+b]) {
g[a*m+b]=0;
q[++tt]={a,b};
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=0,k=0;i<n;i++)
for(int j=0;j<m;j++,k++)
scanf("%d",&g[k]);

int res=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(g[i*m+j]) {
res++;
bfs(i,j);
}
printf("%d\n",res);
return 0;
}
  • 运行时间:
    • 用dfs:1003ms
    • 用bfs:
      • 用STL中的queue:1932ms
      • 用手工写的队列:1036ms