Flood Fill

本文介绍了使用C++编程语言实现FloodFill算法,包括广度优先搜索(BFS)和深度优先搜索(DFS)方法,处理网格图中的连通块问题。在ACWing平台的多个题目中,通过修改字符矩阵g[][]来避免使用boolst[]数组,优化了代码效率。
摘要由CSDN通过智能技术生成

欢迎点赞指点 还有一个月 ✈蓝桥杯✈

Flood Fill (洪水填充) 求解 对于网格图的连通块 问题

提取:

  1. g[ ][ ]字符矩阵的读取技巧

  1. bool st[ ]的作用及应用

  1. g[ ][ ]将走过的格子修改 从而省去 bool st[ ]


ACWing 1113.红与黑

BFS 用 g[ ][ ]标记为 ' # ' 省去bool st[ ]的表示
#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> PII;
const int N = 25;

char g[N][N];
int n,m;
queue<PII> q;

int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int bfs(int sx,int sy)
{
    g[sx][sy] = '#';
    q.push({sx,sy});
    
    int res = 1;
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        int a = t.first,b = t.second;
        
        for(int i = 0;i < 4;i++)
        {
            int x = a + dx[i],y = b + dy[i];
            if(x < 0 || x >= n || y < 0 || y >= m) continue;
            if(g[x][y] == '#') continue;
            g[x][y] = '#'; // 相当于 st[] 数组
            q.push({x,y});
            res++;
        }
    }
    
    return res;
}

int main()
{
    while(cin >> m >> n,n || m) // 注意 题目描述  n m 行列
    {
        for(int i = 0;i < n;i++) scanf("%s",g[i]);
        
        PII start;
        
        for(int i = 0;i < n;i++)
          for(int j = 0;j < m;j++)
            if(g[i][j] == '@') start = {i,j};
              
        cout << bfs(start.first,start.second) << endl;
    }
    
    return 0;
}
DFS (flood fill) 理解过程
#include <bits/stdc++.h>

using namespace std;

const int N = 25;

int n,m;
char g[N][N];

int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

int dfs(int a,int b)
{
    int res = 1;
    
    g[a][b] = '#';
    
    for(int i = 0;i < 4;i++)
    {
        int x = a + dx[i],y = b + dy[i];
        if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] != '#')
          res += dfs(x,y); // 理解 不断向下递归与 回溯 的过程
    }                      // 通过画网格图进行手动模拟 来理解
    
    return res;
}

int main()
{
    while(cin >> m >> n,n || m)
    {
        for(int i = 0;i < n;i++) scanf("%s",g[i]);
        
        int a = 0,b = 0;
        
        for(int i = 0;i < n;i++)
          for(int j = 0;j < m;j++)
            if(g[i][j] == '@') a = i,b = j;
            
        cout << dfs(a,b) << endl;
    }
    
    return 0;
}

' # ' 变为 ' . ' 省去 bool st[ ]


ACWing 1097.池塘计数

#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> PII;
const int N = 1010;

int n,m;
char g[N][N];
bool st[N][N];
queue<PII> q;


void bfs(int sx,int sy)
{
    g[sx][sy] = '.';
    q.push({sx,sy});
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        int a = t.first,b = t.second;
        
        for(int i = a - 1;i <= a + 1;i++) //对于 相邻8个方向的偏移
          for(int j = b - 1;j <= b + 1;j++)
          {
               if(i < 0 || i >= n || j < 0 || j >= m) continue;
             if(st[i][j] || g[i][j] == '.') continue;
             
             g[i][j] = '.';
             st[i][j] = true;
             q.push({i,j});
          }
    }
}

int main()
{
    cin >> n >> m;
    
    for(int i = 0;i < n;i++) scanf("%s",g[i]); // 注:语法的细节  不用 &g[i]  "%d" 用&g[i];
    
    int res = 0;
    for(int i = 0;i < n;i++) // 遍历每个字符  寻找并同时 标记连通块
      for(int j = 0;j < m;j++)
        if(g[i][j] == 'W')
        {
            bfs(i,j);
            res++;
        }
    cout << res << endl;
    
    return 0;
}

' w ' 变为 ' . ' st[ ]数组在 bfs( )中 用于判断是否重复遍历 然后入队


ACWing 1233.全球变暖

#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> PII;
const int N = 1010;

int n;
char g[N][N];
bool st[N][N];
queue<PII> q;

int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};

bool bfs(int sx,int sy)
{
    int total = 0,bound = 0;
    
    st[sx][sy] = true;
    q.push({sx,sy});
    total++;
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        int a = t.first,b = t.second;
        
        int res = 0;
        bool is_bound = false;
        for(int i = 0;i < 4;i++)
        {
            int x = a + dx[i],y = b + dy[i];
            if(x < 0 || x >= n || y < 0 || y >= n) continue;
            if(st[x][y]) continue;
            if(g[x][y] == '.')
            {
                is_bound = true; // 四周只要有水就会被淹没
                continue;
            }
            
            st[x][y] = true;
            q.push({x,y});
            total++;
        }
        if(is_bound) bound++;
    }
    
    return total == bound;
}

int main()
{
    cin >> n;
    
    for(int i = 0;i < n;i++) scanf("%s",g[i]);
    
    int ans = 0;
    for(int i = 0;i < n;i++)
      for(int j = 0;j < n;j++)
        if(!st[i][j] && g[i][j] == '#')
         if(bfs(i,j)) ans++;
    
    cout << ans << endl;
    
    return 0;
}

' # ' 不变为 ' . ' st[ ] 出现在for循环遍历中 且 出现在bfs( )中用于判断 然后入队

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值