【C++/DFS连通块】踏青

265 阅读2分钟

题目描述

小白和他的朋友周末相约去召唤师峡谷踏青。他们发现召唤师峡谷的地图是由一块一块格子组成的,有的格子上是草丛,有的是空地。草丛通过上下左右 4 个方向扩展其他草丛形成一片草地,任何一片草地中的格子都是草丛,并且所有格子之间都能通过上下左右连通。如果用'#'代表草丛,'.'代表空地,下面的峡谷中有 2 片草地。

##..

..##

处在同一个草地的 2 个人可以相互看到,空地看不到草地里面的人。他们发现有一个朋友不见了,现在需要分头去找,每个人负责一片草地,想知道他们至少需要多少人。

Input

第一行输入 n, m (1 ≤ n,m ≤ 100) 表示峡谷大小。

接下来输入 n 行字符串表示峡谷的地形。

Output

输出至少需要多少人。

Sample Input 1

5 6
.#....
..#...
..#..#
...##.
.#....

Sample Output 1

5

思路

先从每个‘#’开始搜索,搜索四周四个方向的符号,如果是‘#’就继续搜索这个‘#’的四周。搜到结束则是一个连通块。

AC代码

#include<bits/stdc++.h>
#define ts ios::sync_with_stdio (false);cin.tie(0);
using namespace std;

int ct=0; //连通块数量
int n,m;
int vis[1000][1000]; //标记某处是否已经被搜索过
vector<string> mp(1000);
int dir[][2]={
        {0,1},{0,-1},{1,0},{-1,0}  //方向,可根据题目改变
};

void dfs(int x,int y) //搜索
{
    if(x<0||x>n-1||y<0||y>m-1) //判断点是否出界
        return;
    if(mp[x][y]!='#'||vis[x][y]) //判断点是否为‘#’以及该点是否以及搜索过
        return;
    vis[x][y]=1; //如果执行到这里,说明条件满足,可搜索,将标记为1
    for(int i=0;i<4;i++)  //遍历四个方向,开搜!
        dfs(x+dir[i][0],y+dir[i][1]);
}

int main()
{
    ts;

    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cin>>mp[i][j]; //输出地图
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(vis[i][j]==0&&mp[i][j]=='#') //vis==0 说明此点没被搜索过,说明是新的一个连通块
            {
                ct++;
                dfs(i,j);

            }

        }
    }
    if(ct>0)
        cout<<ct;
    else
        cout<<"Null";
    return 0;
}

//2022.5.23