开头声明
本文由署髫亲自撰写并非转载。
如果代码或文章内容有误,请大佬们及时指出。
部分内容是从网上复制的。
!!链接绝对安全无毒!!
点个赞呗~
基础理论
连通块其实就是求相邻格子的数量、有几块......通常用深度优先搜索来编写。
比如
1 | 0 | 1 | 0 | 0 |
1 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 1 | 0 |
0 | 0 | 1 | 1 | 0 |
“ 1 ”代表不可通行,“ 0 ”代表可以通行,那么图中有几个连通块呢?(只能“上 左 下 右”来搜索)。可以看到图中有4个连通块(单个也算),最大的连通块是由5个块联通的。转化成数据就是:
1 0 1 0 0
1 0 1 1 0
0 1 0 0 0
1 0 1 1 0
0 0 1 1 0
连通块十分简单,所以我们直接上代码。
代码实践
描述
有一块 N×M 的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
输入描述
第一行为 N,M (1≤N,M≤100)。
下面为 N×M的土地示意图。
输出描述
一行,共有的水洼数。
#include<bits/stdc++.h>
using namespace std;
char mp[101][101];
int vis[101][101];
int n,m,cnt;
int dx[8]={0,1,1,1,0,-1,-1,-1},dy[8]={1,1,0,-1,-1,-1,0,1};
void dfs(int x,int y){
for(int i=0;i<8;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=m&&vis[nx][ny]==0&&mp[nx][ny]=='W'){
vis[nx][ny]=1;
dfs(nx,ny);
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='W'&&vis[i][j]==0){
vis[i][j]==1;
dfs(i,j);
cnt++;
}
}
}
cout<<cnt;
return 0;
}
变量定义
char mp[101][101];
int vis[101][101];
int n,m,cnt;
int dx[8]={0,1,1,1,0,-1,-1,-1},dy[8]={1,1,0,-1,-1,-1,0,1};
mp是我们要输入的地图,vis是记录该位置有没有搜索过,n和m是地图(mp)的大小,dx和dy是搜索的4个方向,cnt来统计有几个连通块。
主函数
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
}
}
先输入n和m,用来确定地图大小,再根据地图大小输入每一位。
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(mp[i][j]=='W'&&vis[i][j]==0){
vis[i][j]==1;
dfs(i,j);
cnt++;
}
}
}
先用两个for循环遍历整个地图,看看有没有地图的i和j位是‘W’(水洼)且这个位置没有被搜索过。如果判断成功,那么就标记这一位搜索过了,且从该位开始搜索,搜索这一步是为了防止这块连通块 被再次搜索,最后连通块的数量(cnt)自增。
自定义函数
看过我写的深度优先搜索|c++基础--详细讲解的小伙伴应该熟悉自定义函数部分,连通块的自定义函数其实就是删改了深度优先搜索的的代码。
void dfs(int x,int y){
for(int i=0;i<8;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=m&&vis[nx][ny]==0&&mp[nx][ny]=='W'){
vis[nx][ny]=1;
dfs(nx,ny);
}
}
}
这段代码就不细说了,要注意的是这里的dfs函数是为了标记这个连通块里所有的块,而深度优先搜索的dfs函数是为了判断能不能走到目标位置
视角拓展
我给大家挑了几道简单的小题,大家可以做一做:
都看到这儿了,就点个赞呗~
by~