题目背景
在一个神秘的二维世界中,小可和小达是一对好朋友。他们在探索这个世界时,发现了一个由陆地和水组成的二维网格。陆地是他们可以行走的区域,而水则是他们无法通过的区域。
题目描述
小可和小达的好奇心驱使他们开始探索这个网格。他们发现,如果两个陆地单元格在水平或垂直方向上相邻,那么它们就属于同一个连通块。也就是说,如果小可和小达可以从一个陆地单元格到达另一个陆地单元格,那么他们就属于同一个连通块。 于是小可和小达开始了他们的探索,他们希望能够找到这个网格的所有陆地连通块,并计算出它们的个数。
输入格式
输入的第一行包含两个整数 nn 和 mm ,表示网格的行数和列数。
接下来的 nn 行,每行包含 mm 个整数,表示网格的每个单元格的状态。11 表示陆地,00 表示水。
输出格式
输出一个整数,表示陆地的连通块个数。
样例
输入数据 1
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
Copy
输出数据 1
3
Copy
提示
样例1解释
样例1 很显然有左上角、中间部分、右下角一共三个陆地连通块。
非常简单 基础连通块问题
#include<bits/stdc++.h>
using namespace std;
int n,m;
int dx[4]={0,0,1,-1};//次处为上下左右方向移动
int dy[4]={1,-1,0,0};
int vis[1001][1001];//此为标记数组
int a[1001][1001];//这是要输入的数组
int cnt=0;
void dfs(int x,int y){//使用dfs深度优先搜索 非常适用于连通块问题
vis[x][y]=1;//每次标记不走重复
for(int i = 0 ; i < 4 ; i++){//四个方向遍历
int xx=x+dx[i],yy=y+dy[i];//每次更新坐标
if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||a[xx][yy]==0) continue;//这里用于判断是否越界是否不是1如果符合其中一项就跳过这一次
dfs(xx,yy);//符合要求往下一个点的上下左右方向移动这就是dfs的精髓(一条路走到黑)
}
}
int main(){
cin >> n >> m;//输入
for(int i = 1; i <= n ; i++){
for(int j = 1 ; j <= m ;j++){
cin >> a[i][j];//这里不多解释
}
}
for(int i = 1; i <= n ; i++){
for(int j = 1; j <= m ; j++){
if(a[i][j]==1&&vis[i][j]==0){//这里后面一句很关键如果这个位置的数是1 and 这个位置没被标记过(什么意思呢就是没被搜过 不属于其他的连通块)
cnt++;//符合以上条件就代表发现一个新连通块
dfs(i,j);//搜索 主要目的是找出何当前a[i][j]属于同一连通块的格子进行标记 以免重复搜索造成错误
}
}
}
cout << cnt;//最后输出答案即可
}
总结:本题主要考察dfs的基础变化 核心心在于如何找到并标记属于同一个连通块的格子
代码核心在于dfs以及标记数组 此题较为简单适合dfs新手练习
dfs核心:一条路走到底 就是找到一个点就往这个点往下搜直到不能搜为止 在回溯到上一个点 非常符合递归的特点