例题 1.洛谷 P1451 求细胞数量
题目描述
一矩形阵列由数字 0 0 0 到 9 9 9 组成,数字 1 1 1 到 9 9 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
输入格式
第一行两个整数代表矩阵大小 n n n 和 m m m。
接下来
n
n
n 行,每行一个长度为
m
m
m 的只含字符 0
到 9
的字符串,代表这个
n
×
m
n \times m
n×m 的矩阵。
输出格式
一行一个整数代表细胞个数。
样例 #1
样例输入 #1
4 10
0234500067
1034560500
2045600671
0000000089
样例输出 #1
4
提示
数据规模与约定
对于 100 % 100\% 100% 的数据,保证 1 ≤ n , m ≤ 100 1 \le n,m \le 100 1≤n,m≤100。
题目分析
对于此题,很显然我们可以先遍历所有细胞,从每一个非零的位置开始搜索(DFS,BFS都行),我在如下给出一共三种实现方式。
数组模拟队列 BFS
/*
传统数组模拟队列 BFS
平均内存: 686.8 kb
平均运行时间: 3 ms
*/
struct Point
{
int x,y;
}q[N*N];
int head,tail; //数组模拟队列
void bfs(int x,int y)
{
head = tail = 0;
a[x][y] = '0';
q[tail].x = x;
q[tail].y = y;
tail++;
while(tail>head)
{
for(int i=0;i<4;i++)
{
int dx = q[head].x + dir[i][0];
int dy = q[head].y + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
q[tail].x = dx;
q[tail].y = dy;
tail++;
}
}
head++;
}
}
STL BFS
/*
STL队列 BFS
平均内存: 708.8 kb
平均运行时间: 3 ms
*/
typedef pair<int,int> PII;
queue<PII> sq; //STL队列
void stl_bfs(int x,int y)
{
a[x][y] = '0';
sq.push({x,y});
while(sq.size())
{
for(int i=0;i<4;i++)
{
int dx = sq.front().first + dir[i][0];
int dy = sq.front().second + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
sq.push({dx,dy});
}
}
sq.pop();
}
}
DFS
/*
传统DFS
平均内存: 637.2 kb
平均运行时间: 3.1 ms
*/
void dfs(int x,int y)
{
for(int i=0;i<4;i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
dfs(dx,dy);
}
}
return;
}
总代码
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
char a[N][N];
int ans,n,m;
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
/*
传统数组模拟队列 BFS
平均内存: 686.8 kb
平均运行时间: 3 ms
*/
struct Point
{
int x,y;
}q[N*N];
int head,tail; //数组模拟队列
void bfs(int x,int y)
{
head = tail = 0;
a[x][y] = '0';
q[tail].x = x;
q[tail].y = y;
tail++;
while(tail>head)
{
for(int i=0;i<4;i++)
{
int dx = q[head].x + dir[i][0];
int dy = q[head].y + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
q[tail].x = dx;
q[tail].y = dy;
tail++;
}
}
head++;
}
}
/*
STL队列 BFS
平均内存: 708.8 kb
平均运行时间: 3 ms
*/
typedef pair<int,int> PII;
queue<PII> sq; //STL队列
void stl_bfs(int x,int y)
{
a[x][y] = '0';
sq.push({x,y});
while(sq.size())
{
for(int i=0;i<4;i++)
{
int dx = sq.front().first + dir[i][0];
int dy = sq.front().second + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
sq.push({dx,dy});
}
}
sq.pop();
}
}
/*
传统DFS
平均内存: 637.2 kb
平均运行时间: 3.1 ms
*/
void dfs(int x,int y)
{
for(int i=0;i<4;i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!='0')
{
a[dx][dy] = '0';
dfs(dx,dy);
}
}
return;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
/*for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]!='0') bfs(i,j),ans++;*/ //BFS
/*for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]!='0') dfs(i,j),ans++;*/ //DFS
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]!='0') stl_bfs(i,j),ans++; //STL BFS
cout<<ans<<endl;
return 0;
}
例题 2.Acwing 1097. 池塘计数
此题思路遇上题一致,在此不再赘述。
总代码 (DFS)
DFS写法相对与其他两种代码较短,更容易书写。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
char a[N][N];
int n,m,ans;
void dfs(int x,int y)
{
a[x][y] = '.';
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
{
int dx = x + i;
int dy = y + j;
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]=='W')
{
a[dx][dy] = '.';
dfs(dx,dy);
}
}
return;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]=='W') dfs(i,j),ans++;
cout<<ans<<endl;
return 0;
}