算法:搜索 || Flood Fill模型(bfs)

Flood Fill模型,顾名思义就是洪水漫灌,如下图所示,假设绿色区域为山谷(引申为合法区域),棕色区域为山峰(引申为非法区域),如果在某一区域发洪水(以某一点为起点)了,求所能淹到的区域(联通区间)。

outside_default.png

以上图模拟Flood Fill算法:

如图(1),当前选择一不合法区域(1, 1),不能进行bfs;

按照从左到右从上到下的方向,寻找可行区域,直到找到第一个可行区域(1, 2),从(1, 2)进入bfs,图(2)、(3)、(4)为bfs的过程;

继续移动,找到下一个合法区域(1, 5)进行bfs,继续移动,找到最后一个合法区域(4, 5)进行bfs(图6),最后移动至(5, 5),循环结束。

这个算法的时间复杂度是线性于所有节点数目的。

例题1:ACwing1097池塘计数

农夫约翰有一片 N∗M 的矩形土地。

最近,由于降雨的原因,部分土地被水淹没了。

现在用一个字符矩阵来表示他的土地。

每个单元格内,如果包含雨水,则用”W”表示,如果不含雨水,则用”.”表示。

现在,约翰想知道他的土地中形成了多少片池塘。

每组相连的积水单元格集合可以看作是一片池塘。

每个单元格视为与其上、下、左、右、左上、右上、左下、右下八个邻近单元格相连。

请你输出共有多少片池塘,即矩阵中共有多少片相连的”W”块。

输入格式 第一行包含两个整数 N 和 M。

接下来 N 行,每行包含 M 个字符,字符为”W”或”.”,用以表示矩形土地的积水状况,字符之间没有空格。

输出格式 输出一个整数,表示池塘数目。

数据范围 1≤N,M≤1000

输入样例:

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

输出样例:

3

本题直接使用bfs的Flood Fill模型解决。

并在代码中使用到如下优化:

  1.  使数组从(1,1)开始,避免边界判断;

  2.  直接修改原数组g,将访问过的节点修改为不合法区域,不需再保存访问状态。

#include <iostream>
#include <queue>


using namespace std;


const int N = 1010;


int g[N][N];
int m, n;
queue<pair<int, int> > tmp;


void bfs(int x, int y)
{
    g[x][y] = 0;
    tmp.push({x, y});
    while(!tmp.empty())
    {
        for(int i = tmp.front().first - 1; i <= tmp.front().first + 1; i++)
        for(int j = tmp.front().second - 1; j <= tmp.front().second + 1; j++)
            if(g[i][j]){g[i][j] = 0; tmp.push({i, j});}
            //直接修改原数组,将入队过的节点修改为0
        tmp.pop();
    }
    return;
}


int main()
{
    cin >> m >> n;
    for(int i = 1; i <= m; i++)
    {
        string tmp;
        cin >> tmp;
        for(int j = 1; j <= n; j++)//从1,1开始,避免边界判断
        g[i][j] = tmp[j - 1] == 'W';
    }//01 保存
    int cnt = 0;
    for(int i = 1; i <= m; i++)
    for(int j = 1; j <= n; j++)
        if(g[i][j]){cnt ++; bfs(i, j);}


    cout << cnt;
}

点击阅读原文,进入acwing,试试这题吧~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值