Flood Fill algorithm of common algorithm

Posted by DepretioN on Tue, 08 Feb 2022 15:44:16 +0100

Flood Fill algorithm of common algorithm

Algorithm Introduction

  • Basic function: find connected blocks
  • Basic method: BFS search
  • Applicable topics: it is necessary to find out the topics of classification blocks / some clustering problems
  • As the name suggests, Flood Fill algorithm is to find the surrounding qualified areas like flooding. BFS can be used to find the nearest point and then expand gradually.

Code ideas

  1. Set function bfs
  2. Input parameter coordinates, create a queue, and press in the initial position
  3. Change the formal parameter coordinates and mark that they have been accessed (to prevent duplication)
  4. Loop until the queue is empty
  5. Take out the team head element
  6. Judge whether the changed coordinates meet the requirements (range, marking status, belonging to connected blocks, etc.)
  7. If the status is satisfied, press into the queue and reset the status

Examples

  1. Pond count (simple application)

Farmer John has a rectangular land of N * M. Recently, due to rainfall, some land has been flooded. Now use a character matrix to represent his land. In each cell, use "W" if it contains rainwater, and use "." if it does not contain rainwater express. Now John wants to know how many ponds have formed in his land.
Each set of connected ponding cells can be regarded as a pond.
Each cell is considered to be connected to its eight adjacent cells: top, bottom, left, right, top left, top right, bottom left and bottom right.
Please output the total number of ponds, that is, the total number of connected "W" blocks in the matrix.

sample input 
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

sample output 
3

ac Code:

#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 1010;

int n, m;
char g[N][N];
bool st[N][N];
int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[] = {0, 1, 1, 1, 0, -1, -1, -1};//Eight directions

void bfs(int x, int y)
{
    st[x][y] = true;

    queue<PII> q;
    q.push({x, y});

    while(q.size())
    {
        PII tmp = q.front();
        q.pop();

        for(int i = 0; i < 8; i++)
        {
            int nx = tmp.x + dx[i], ny = tmp.y + dy[i];

            if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;

            if(st[nx][ny] || g[nx][ny] == '.') continue;

            st[nx][ny] = true;
            q.push({nx, ny});
        }
    }
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++) cin >> g[i];

    int ans = 0;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(g[i][j] == 'W' && !st[i][j])
            {
                bfs(i, j);
                ans ++;
            }
        }
    }

    cout << ans << endl;

    return 0;
}
  1. castle

Please write a program to calculate the total number of rooms in the castle and the size of the largest room. The castle is divided into m * n square areas, and each square area can have 0 ~ 4 walls.
The castle is described as follows:

    1   2   3   4   5   6   7  
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #
   #---#########---#####---#---#
 4 #   #   |   |   |   |   #   #
   #############################
           (Figure 1)
   #  = Wall   
   |  = No wall
   -  = No wall
   Direction: up north, down south, left West, right east.

Input format

The first line contains two integers m and n,It represents the length of the castle in the north-south direction and the length in the east-west direction respectively.

next m Rows, each containing n An integer, each integer representing the characteristics of the wall of the block at the corresponding position of the plan.

The characteristics of the wall in each block are represented by numbers P To describe, we use 1 to represent the west wall, 2 to represent the north wall, 4 to represent the east wall and 8 to represent the south wall, P Is the sum of the numbers that contain the wall in the box.

For example, if a square P Is 3, then 3 = 1 + 2,The box contains the west wall and the north wall.

The inner wall of the castle is calculated twice, square(1,1)The south wall is also a square(2,1)The north wall of.

The data entered ensures that there are at least two rooms in the castle.

Output format:

There are two lines in total. The first line outputs the total number of rooms, and the second line outputs the area (number of square blocks) of the largest room.
Data range
1≤m,n≤50,0≤P≤15
Input sample:
4 7 
11 6 11 6 3 10 6 
7 9 6 13 5 15 5 
1 10 12 7 13 7 5 
13 11 10 8 10 12 13 

Output example:
5
9

Core: the characteristics of the wall in each block are described by the number P. we use 1 to represent the west wall, 2 to represent the north wall, 4 to represent the east wall, 8 to represent the south wall, and P is the sum of the numbers of the walls contained in the block., This is a binary shell flood algorithm

Analysis: 1 represents the west wall, 2 represents the north wall, 4 represents the east wall, and 8 represents the south wall. For example, 11 = 1 + 2 + 8 represents the south wall in the northwest. At this position, you can only go east. In other words, given a four digit binary number and the corresponding bit is 0, you can start in this direction to calculate the number of connected blocks and the area of the largest connected block.

  • It should be noted that although it is easy to make mistakes, the only one on the map is (- 1,0), which indicates the decrease of abscissa, rather than (0,1), which we often use, because here are rows and columns (0, - 1), (1,0), (0,1), (1,0) respectively represent the four directions of northwest and Southeast, for example, the number at a certain position is 1010, You can move to (0, - 1) and (0, 1).
  • The skills of binary conversion: num > > X & 1 can judge whether the x-1 bit of num binary is 1.
    Since we have to find the largest room, the BFS function returns an int value. We can increase the space size by one at the beginning of the queue cycle.

ac Code:

#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 55;

int n, m;
int g[N][N];
bool st[N][N];
int dx[] = {0, -1, 0, 1}, dy[] = {-1, 0, 1, 0};

int bfs(int x, int y)
{
    int res = 0;//Record room size
    st[x][y] = true;

    queue<PII> q;
    q.push({x, y});

    while(q.size())
    {
        PII tmp = q.front();
        q.pop();
        res ++;

        for(int i = 0; i < 4; i++)
        {
            if(g[tmp.x][tmp.y] >> i & 1) continue;
            int nx = tmp.x + dx[i], ny = tmp.y + dy[i];

            if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
            if(st[nx][ny]) continue;

            st[nx][ny] = true;
            q.push({nx, ny});
        }
    }

    return res;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            cin >> g[i][j];

    int ans = 0, num = 0;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
        {
            if(!st[i][j])
            {
                num ++;//Number of rooms
                int t = bfs(i, j);
                ans = max(ans, t);
            }            
        }

    cout << num << endl;
    cout << ans << endl;

    return 0;
}
  1. Peaks and valleys

FGD children especially like to climb mountains. When climbing mountains, they are studying mountains and valleys. In order to have an arrangement for the journey, he wanted to know the number of peaks and valleys. Given a map, for the area that FGD wants to travel, the map is divided into n × N grid, the height w(i, j) of each grid (i, j) is given. If two lattices have common vertices, they are adjacent lattices. For example, lattices adjacent to (i, j) have (i − 1, J − 1), (i − 1, j), (i − 1, j+1), (i, J − 1), (i+1, J − 1), (i+1, J − 1), (i+1, j), (i+1, j), (i+1, j+1). We define the set S of a lattice as a peak (Valley) if and only if:

  • All squares of S have the same height.
  • All the lattices of S are connected.
  • For S belongs to s, and s' adjacent to s does not belong to s, there are WS > WS' (peak), or WS < WS' (Valley).

If there is no adjacent area around, it is regarded as both a mountain and a valley.
Your task is to find the number of peaks and valleys for a given map. If all grids have the same height, the whole map is both peaks and valleys.

Input format

The first line contains a positive integer n,Represents the size of the map. Next one n×n A matrix representing the height of each grid on the map w. 

Output format

A line containing two integers representing the number of peaks and valleys.

Train of thought analysis:
When searching for connected blocks, we need to judge the type of connected blocks around. We can use two variables to record whether there are connected blocks higher or lower than the current connected block. We can use the flood fill algorithm to search for connected blocks and calculate the number of current peaks and valleys according to the two recorded variables.

ac code

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 1010;
int n;
int peek,valley = 0;
int g[N][N];
bool st[N][N];
int dx[] = {-1,-1,-1,0,1,1,1,0},dy[] = {-1,0,1,1,1,0,-1,-1}
int bfs(int x,int y)
{
    bool high = false;//Indicates that there is a height higher than this point
    bool low = false;
    queue<PII> q;
    st[x][y]  = true;
    q.push({x,y});
    while(!q.empty())
    {
        PII tmp = q.front();
        q.pop();
        for(int i = 0; i < 8; i++)
        {
            int nx = tmp.x + dx[i],ny = tmp.y + dy[i];
            if(nx < 0||nx > n||ny < 0||ny>n)continue;
            if(g[nx][ny]!=g[tmp.x][tmp.y])
            {
                if(g[nx][ny] > g[tmp.x][tmp.y]) high = true;
                if(g[nx][ny] < g[tmp.x][tmp.y]) low = true;
            }
            else if(!st[nx][ny])
            {
                st[nx][ny] = true;
                q.push({nx,ny});
            }
        }
    }
    if(high && low) return -1;
    else if(!high &&!low) return 0;
    else if(!high) return 1;
    else return 2;

}
int main()
{
    cin >> n;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            cin >>g[i][j];
        }
    }
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(!st[i][j])
            {
                int t = bfs(i,j);
                if(t == 0)peek ++,valley ++;
                if(t == 1)peek ++;
                if(t == 2)valley ++;
            }
        }
    }
    cout << peek << " "<< valley <<endl;
    return 0;
}


Topics: C++ Algorithm data structure