FloodFill模型和最短路模型-AcWing提高课(自我整理)

Flood Fill模型

1097. 池塘计数

简单分析:

模板题
统计有几个连接的池塘,本质上的flood fill就是用dfs或bfs去搜索,搜索到了就把是否访问标签设置为true,
如果仍有没访问的点,则对这个点继续做一次dfs或bfs
八个方向,可以用一个小trick:dx=[-1, -1, 0, 1, 1, 1, 0, -1], dy=[0, 1, 1, 1, 0, -1, -1, -1] (上,右上,左,左下..顺时针)
#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second

using namespace std;

const int N = 1010;

typedef pair<int, int> PII;

int n , m;
char ch[N][N];
bool st[N][N];
PII q[N * N];

void bfs(int sx, int sy){
    int hh = 0, tt = -1;
    q[++ tt] = {sx, sy};
    st[sx][sy] = true;
    while(hh <= tt){
        PII t = q[hh ++];
        for(int i = t.x - 1; i <= t.x + 1; i ++){
            for( int j = t.y - 1; j <= t.y + 1; j ++){
                if(i == t.x && j == t.y) continue;
                if(i < 0 || i >= n || j < 0 || j >= m) continue;
                if(st[i][j] || ch[i][j] == '.') continue;
                q[++ tt] = {i, j};
                st[i][j] = true;
            }
        }
    }    
}

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

python3写法:

from collections import deque

if __name__ == "__main__":

    n, m = map(int, input().split())
    st = [[False] * m for _ in range(n)]
    mapp = []
    cnt = 0
    dx, dy = [-1, -1, 0, 1, 1, 1, 0, -1], [0, 1, 1, 1, 0, -1, -1, -1]
    
    # def dfs(x: int, y: int) -> None:
    #     '''dfs在这道题会爆栈'''
    #     st[x][y] = True
    #     for i in range(8):
    #         nx, ny = x + dx[i], y + dy[i]
    #         if nx < 0 or nx >= n or ny < 0 or ny >= m:
    #             continue
    #         if st[nx][ny]:
    #             continue
    #         if mapp[nx][ny] == 'W':
    #             dfs(nx, ny)
                
    def bfs(x: int, y: int) -> None:
        q = deque([(x, y)])
        st[x][y] = True
        while q:
            t = q.popleft()
            for i in range(8):
                nx, ny = t[0] + dx[i], t[1] + dy[i]
                if nx < 0 or nx >= n or ny < 0 or ny >= m:
                    continue
                if st[nx][ny]:
                    continue
                if mapp[nx][ny] == 'W':
                    st[nx][ny] = True
                    q.append((nx, ny))

    for _ in range(n):
        mapp.append(input())
    for i in range(n):
        for j in range(m):
            if mapp[i][j] == 'W' and st[i][j] == False:
                bfs(i, j)
                cnt += 1
    print(cnt)

1098. 城堡问题

简单分析:

'''
在flood fill模板上稍微复杂了一下
现在我们需要思考什么时候可以向上下左右四个方向去走?
1. 没有被墙挡住
    对于每一个位置,用一个数p(0-15)来表示,可以转化成2进制数,1111从左往右分别表示是否有南、东、北、西墙,
    p >> i & 1 可以来判断是否存在i墙(i表示墙索引,从西开始反着编号)
2. 还没有访问过
'''

c++代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second

using namespace std;
typedef pair<int, int> PII;
const int N = 55;

int m, n;
int g[N][N];
bool st[N][N];
PII q[N * N];

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; // 分别是上右下左

int bfs(int sx, int sy){
    st[sx][sy] = true;
    int hh = 0, tt = -1;
    q[ ++ tt] = {sx, sy};
    while( hh <= tt ){
        PII t = q[hh ++];
        // 下述过程建议优化一下,这是我初版的思路,没优化,其实可以合并起来,参照python代码
        if(t.x + dx[0] >= 0 && t.x + dx[0] < m && t.y + dy[0] >= 0 && t.y + dy[0] < n && !st[t.x + dx[0]][t.y + dy[0]] && !(g[t.x + dx[0]][t.y + dy[0]] >> 3 & 1)){
            q[++ tt] = {t.x + dx[0], t.y + dy[0]};
            st[t.x + dx[0]][t.y + dy[0]] = true;
        }
        if(t.x + dx[1] >= 0 && t.x + dx[1] < m && t.y + dy[1] >= 0 && t.y + dy[1] < n && !st[t.x + dx[1]][t.y + dy[1]] && !(g[t.x + dx[1]][t.y + dy[1]] & 1)){
            q[++ tt] = {t.x + dx[1], t.y + dy[1]};
            st[t.x + dx[1]][t.y + dy[1]] = true;
        }
        if(t.x + dx[2] >= 0 && t.x + dx[2] < m && t.y + dy[2] >= 0 && t.y + dy[2] < n &&!st[t.x + dx[2]][t.y + dy[2]] && !(g[t.x + dx[2]][t.y + dy[2]] >> 1 & 1)){
            q[++ tt] = {t.x + dx[2], t.y + dy[2]};
            st[t.x + dx[2]][t.y + dy[2]] = true;
        }
        if(t.x + dx[3] >= 0 && t.x + dx[3] < m && t.y + dy[3] >= 0 && t.y + dy[3] < n &&!st[t.x + dx[3]][t.y + dy[3]] && !(g[t.x + dx[3]][t.y + dy[3]] >> 2 & 1)){
            q[++ tt] = {t.x + dx[3], t.y + dy[3]};
            st[t.x + dx[3]][t.y + dy[3]] = true;
        }
    }
    return tt + 1;
}


/*
    对于墙壁的情况分别有:(1,西墙)(2,北墙)(4,东墙)(8,南墙)(3 西北墙)(5,西东墙)(6,东北墙)
    (7,西北东墙)(9,西南墙)(10,北南墙)(11, 西北男墙)(12,东南墙)(13,西东南墙)(14,北东南墙)
    (15,西北东南墙)
    1.首先读入所有的数字信息,
    2.需要定义每一个空间是否已经访问
    3.从1,1空间开始访问,用bfs向外边扩散,分别去看上下左右的空间,如果上边没有南墙则访问(g[i][j] >> 3 & 1),
        如果下边没有北墙可以访问(g[i][j] >> 1 & 1)
        如果左边没有东墙可以访问(g[i][j] >> 2 & 1)
        如果右边没有西墙可以访问。(g[i][j] & 1)
*/
int main()
{
    int cnt = 0;
    int res = 0;
    cin >> m >> n;
    for(int i = 0; i < m ; i++){
        for(int j = 0 ; j < n; j ++){
            cin >> g[i][j];
        }
    }
    for(int i = 0 ; i < m; i ++){
        for(int j = 0; j < n ; j++){
            if(!st[i][j]){
                int s = bfs(i, j);
                if(s > res){
                    res = s;
                }
                cnt ++;
                
            }
        }
    }
    cout << cnt << endl;
    cout << res;
    return 0;
}

python3代码:

from collections import deque
if __name__ == "__main__":
    m, n = map(int, input().split())
    mapp = [ list(map(int, input().split())) for _ in range(m)]
    st = [[False] * n for _ in range(m)]
    cnt, max_size = 0, 0
    dx, dy = [0, -1, 0, 1], [-1, 0, 1, 0]

    def bfs(x: int, y: int) -> int:
        q = deque([(x, y)])
        st[x][y] = True
        size = 0
        while q:
            tx, ty = q.popleft()
            size += 1
            for i in range(4):
                nx, ny = tx + dx[i], ty + dy[i]
                if nx < 0 or nx >= m or ny < 0 or ny >= n:
                    continue
                if st[nx][ny]:
                    continue
                if mapp[tx][ty] >> i & 1 == 0:
                    st[nx][ny] = True
                    q.append((nx, ny))
        return size

    for i in range(m):
        for j in range(n):
            if not st[i][j]:
                max_size = max(bfs(i, j), max_size)
                cnt += 1
    print(cnt)
    print(max_size)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值