[华为OD] 污染水域(多源BFS)

【基础算法总结】 BFS_最短路问题 BFS_最短路问题 阅读详情

BFS与多源BFS

BFS广度优先搜索,BFS一般用队列实现,遵循着先进先出的原则,比较典型的例子就是之前说过的二叉树层序遍历。

在二叉树的层序遍历中,入口只有一个,也就是根节点。在遍历过程中,每次都拿出队列的第一个值,并把它的衍生值放在队列的最右边。

在二叉树的层序遍历中,从上往下一层一层走下去,不会出现一个节点重复出现的情况。

多源BFS,就像它的名称一样,有多个源头(也就是入口)。一般用在图中,以多个入口为起点,向周围进行遍历,因为从多个入口出发可能走到同一个位置,为了防止重复遍历,需要对遍历过的位置进行标记。

下面给出了《污染水域》的题解和一些相似的leetcode题目的代码。

污染水域

输入一行字符串,字符串可以转换为N*N的数组,数组可认为是一个水域,判断多少天后,水域被全部污染。
数组中只有1和0两个数,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染或永远无法污染,则返回-1。

输入1,0,1,0,0,0,1,0,1
输出2
说明输入转化为数组是
1,0,1
0,0,0
1,0,1
第一天后水域变为
1,1,1
1,0,1
1,1,1
第二天全部为被污染

这个题就是一个很典型的多源BFS问题,首先要找到遍历的入口,也就是初始水域中为1的位置。将这些位置都加入队列。
如果水域中不存在1,或者水域中全是1,那么不需要再进行污染,直接返回-1。
我们从每个入口出现,向上下左右四个方向进行遍历,并标记。如果要遍历的位置已经被标记了,或者超过了水域的边界,那么就忽略。如果没有被标记,则把它加入队列中去。

我们一步一步地完成这个代码。

  1. 获取输入,构造水域矩阵。
    在华为OD的题目中,输入需要自己获取,所以我们可以先构造一下输入的矩阵。

    link = list(map(int,input().split()))
    n = int(math.sqrt(len(link)))
    mat = [[0]*n for _ in range(n)]
    
  2. 现在我们来找多源BFS中的源, 并把它存到一个队列中去。

    q = []
    for i in range(n):
    	for j in range(n):
    		mat[i][j] = link[i*n+j]
    		if link[i*n+j]==1:  # 如果是污染区
    			q.append([i,j])
    
  3. 如果区域不存在污染或者全是污染,直接返回 - 1。

    if not q or len(q) == len(link):
    	return -1
    
  4. 定义一下遍历的方向,和最大天数。

    direction = [[1,0],[-1,0],[0,1],[0,-1]] # 四个方向
    max_num = 0    # 求最大天数,所以初始化为一个比较小的数
    
  5. 开始遍历!

    while q: # 只要q中有东西就一直遍历
    	cur  = q.pop(0) # 取出队列的第一个值
    	x, y = cur # 当前位置
    	for di in directions:  # 遍历四个方向
    		newx = x+di[0]
    		newy = y+di[1]
    		if newx<0 or newy<0 or newx>=n or newy>=n:
    			continue # 如果越界就跳过
    		if mat[newx][newy]!=0:
    			continue # 如果访问过就跳过
    		mat[newx][newy] = mat[x][y]+1 # 标记当前位置,用的数字可以代表与污染区的距离【也就是扩散用的时间】
    		if max_num < mat[newx][newy]:
    			max_num = mat[newx][newy] # 更新最大天数
    		q.append([newx,newy])
    return max_num-1 # 因为mat[x][y]的初始值是1,所以这里要-1
    

leetcode 1162::地图分析

https://leetcode.cn/problems/as-far-from-land-as-possible/

这道题也是一个典型的多源BFS。要求的是海洋单元到距离它最近的陆地单元格的距离是最大的,可以理解成我们已陆地单元格为源头,开始向四周遍历,最后访问到的海洋就是距离最远的海洋。

我们用海洋到陆地的距离来标记单元格,那么最后找到的海洋的标记,就代表了它到离它最近的陆地单元格的距离。

class Solution(object):
    def maxDistance(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """

        direction = [[-1,0],[1,0],[0,1],[0,-1]]
        q = []
        n = len(grid)
        for i in range(n):
            for j in range(n):
                if grid[i][j] == 1:
                    q.append([i,j])
        if not q or len(q)==n**2:
            return -1
        
        while q:
            cur = q.pop(0)
            x,y = cur
            for di in direction:
                tmp_x = x + di[0]
                tmp_y = y + di[1]

                if tmp_x<0 or tmp_y<0 or tmp_x>=n or tmp_y>=n or grid[tmp_x][tmp_y]!=0:
                    continue

                grid[tmp_x][tmp_y] = grid[x][y]+1

                q.append([tmp_x,tmp_y])

        return grid[cur[0]][cur[1]]-1

leetcode 542:01矩阵

https://leetcode.cn/problems/01-matrix/

求每一个非0元素到最近的0的距离。可以理解成以0为起点,向周围扩散,并用起到到当前位置的距离进行标记。要返回的是距离矩阵,其实就是被标记后的矩阵。

class Solution(object):
    def updateMatrix(self, matrix):
        """
        :type mat: List[List[int]]
        :rtype: List[List[int]]
        """

        q = []
        m = len(matrix)
        n = len(matrix[0])
        for i in range(m):
            for j in range(n):
                if matrix[i][j]==0:
                    q.append([i,j])
                else:
                    matrix[i][j] = -1

        direction = [[1,0],[-1,0],[0,1],[0,-1]]
        while q:
            cur = q.pop(0)
            x,y = cur
            for di in direction:
                newx = x+di[0]
                newy = y+di[1]
                if newx<0 or newy<0 or newx>=m or newy>=n or matrix[newx][newy]!=-1:
                    continue
                matrix[newx][newy] = matrix[x][y]+1
                q.append([newx,newy])
        return matrix

leetcode 1020:飞地的数量

https://leetcode.cn/problems/number-of-enclaves/

找到无法离开网格边界的陆地单元格的数量,就是找没有和边界相连的陆地单元格的数量。我们可以换个思路,找到所有与边界相连的陆地单元格,并把它们置0,那么剩下的陆地单元格就是不相连的。

我们的源就是边界上的陆地单元格,以此为入口向四个方向遍历。

class Solution(object):
    def numEnclaves(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """

        m = len(grid)
        n = len(grid[0])

        if m<=2 or n<=2:
            return 0

        q = []
        for i in range(m):
            if grid[i][0]==1:
                q.append([i,0])
            if grid[i][n-1]==1:
                q.append([i,n-1])
        for j in range(1,n-1):
            if grid[0][j] == 1:
                q.append([0,j])
            if grid[m-1][j] ==1:
                q.append([m-1,j])
        direction = [[-1,0],[1,0],[0,1],[0,-1]]
        while q:
            cur = q.pop(0)
            x,y = cur
            grid[x][y] = 0

            for di in direction:
                newx = x+di[0]
                newy = y+di[1]

                if newx<0 or newy<0 or newx>=m or newy>=n or grid[newx][newy]==0:
                    continue
                grid[newx][newy] = 0
                q.append([newx,newy])

        return sum([sum(grid[i]) for i in range(m)])
算法沉淀—— BFS(leetcode真题剖析) `BFS` 是指从点同时进行广度优先搜索的算法。在传统的 `BFS` 中,我们通常从一个起始点开始,逐层遍历所有的相邻节点。而在 `BFS` 中,我们可以同时从点开始,从这些点出发,逐层向外扩展,直到达到目标或者遍历完整个图。 阅读详情

相关推荐

华为OD机试 - 污染水域(Java)

数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。可以采用图的BFS来解决。图的BFS实现关键点在于理解queue的作用。更解析请看上面链接博客的解释。输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染

qq_34143141的博客 319

BFS

BFS 一、简介 BFS与单BFS有什么区别呢? 单BFS:从某一个点开始(起点) BFS:从个点同时开始走 如何解决BFSBFS个起点 ——> 个起点同时加入队列! 核心:在求解BFS问题时,同时将所有起点加入队列即可! 二、练习 1.矩阵距离 【题目链接】173. 矩阵距离 - AcWing题库 给定一个 NN 行 MM 列的 0101 矩阵 AA,A[i] [j] 与A[k] [l] 之间的曼哈顿距离定义为: dist(A[i] [j],

涛涛的个人博客 1450

华为OD机试 - 污染水域 - 图的BFS(Java 2024 E卷 200分)

每一题都有详细的答题思路,完整代码,欢迎私信 加入华为OD刷题群~ ·

学Java,找哪吒 1533

【重难点算法】 BFS

BFS 是从图中的某一点(点)开始出发,向周围进行广度优先搜索,在搜索的过程中记录每一点到点的距离。广度优先搜索是用队列来实现的,对于单的问题,队列的初始化就是某一个单一点;典型的广度优先搜索问题,我们从每一个烂橘子的单元格子出发,一圈一圈的污染周围四方向上的新鲜橘子,直到新鲜橘子的数量为 0。请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该距离。到最近的 1 的距离,如果记录矩阵中 1 的位置的队列的大小为空或者为。位置距离最近的 1 的曼哈顿距离。

weixin_54383080的博客 1013

华为OD机试 - 污染水域 - 图的BFSPython/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中,刷题。

学Java,找哪吒 1071

华为od统一考试B卷【污染水域】Java&Go 实现

输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染。数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。

MISAYAONE的博客 5289

2023华为od统一考试B卷【污染水域Python 实现

输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染。数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。

MISAYAONE的博客 5187

华为OD 污染水域(200分)【java】A卷+B卷

注:这里有一个小细节就是,可以直接修改原数组,扩散到了就在原数组上加1,最后统计数组中最大值-1即可。数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。这道题是典型的图的BFS问题,可以参考【Leetcode】图的BFS详解加强对图的BFS方法的学习。输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染。然后从各个污染同时开始一圈一圈的向净水扩散,那么最后扩散到的净水就是花费的天数!

即使再小的帆也能远航 457

【2024年华为OD机试】 (C卷,200分)- 污染水域(JavaScript&Java & Python&C/C++)

本题通过 BFS模拟污染水域的扩散过程,能够高效地计算出水域被全部污染所需的天数。将问题建模为图的 BFS。使用队列存储污染水域,并逐层扩散。处理边界条件,确保结果的正确性。代码通过 BFS模拟污染水域的扩散过程,能够高效地计算出水域被全部污染所需的天数。时间复杂度为O(N^2),空间复杂度为O(N^2),能够很好地处理最大输入规模。代码通过 BFS模拟污染水域的扩散过程,能够高效地计算出水域被全部污染所需的天数。时间复杂度为O(N^2),空间复杂度为O(N^2)

嵌入式技术开发 859

华为od统一考试B卷【污染水域】C语言 实现

输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染。数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。

MISAYAONE的博客 477

华为od统一考试B卷【污染水域】JavaScript 实现

输入一行字符串,字符串可转换为N*N的数组,数组可认为是一个水域,判断少天后,水域被全部污染。数组中只有0和1,0表示纯净,1表示污染,每天只可污染上下左右的水域,如果开始全部被污染,或永远无法污染,则返回-1。

MISAYAONE的博客 4930

广度优先搜索BFS进阶()BFS、优先队列BFS、双端队列BFS

普通队列BFS:适用于无权图;双端队列BFS:适用于边权为0或1且到每个顶点的边权都相等的带权图;优先队列BFS:适用于边权不为负且到每个顶点的边权都相等的带权图;如果图上到每个顶点的边权不等,则需使用最短路算法。

yuhaomogui的博客 2266

【算法】BFS 系列之 BFS

最短路问题是图论中一种经典的题型,包括单最短路、最短路、边权为 1 的最短路等等。本篇主要讲述的是边权为 1 的最短路问题。简单来说,边权为 1 的单最短路问题即为:求从单个起点到终点的最短路径距离,而边权为 1 的最短路问题即为:求从个起点到终点的最短路径距离。对于的最短路问题,我们将个相邻的起点看作是一个整体,进而简化成一个起点,将转化成单并利用 BFS 来处理,具体的方式是,在用队列进行 BFS 时,将所有起点入队,然后一层一层向外扩展。​。

NeeEk0的博客 1599

BFS问题

一文带你了解bfs问题

m0_64226820的博客 796

1107. 魔板(bfs宽搜)

Rubik 先生在发明了风靡全球的魔方之后,又发明了它的二维版本——魔板。 这是一张有 8 个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 我们知道魔板的每一个方格都有一种颜色。 这 8 种颜色用前 8 个正整数来表示。 可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。 对于上图的魔板状态,我们用序列 (1,2,3,4,5,6,7,8) 来表示,这是基本状态。 这里提供三种基本操作,分别用大写字母 A,B,C 来表示(可以通过这些操作改变魔板

m0_46656833的博客 795

【算法】BFS算法解决最短路问题(C++)

此前我们对 单最短路 问题进行的讲解:画图来说,单最短路问题即为:而对于最短路问题:自然是 利用BFS算法解决,下面提出解法: 当我们将所有的点作为一个点来进行解题时,问题又变成了单最短路问题,而为什么可以认为这种解法是正确的呢?我们对于 单最短路 问题的bfs解法为:自然,对于 最短路 的bfs解法为: 542.01矩阵 1020.飞地的数量 1765.地图中的最高点 1162.地图分析

卜及中的博客 1644

BFSBFS问题

将所有原点变成一个超级原点

weixin_51142926的博客 1369
上一篇: 二叉树的三序遍历
下一篇: 第十九章 番外篇:google-research《深度学习调参指南》
江米江米
博客等级 码龄9年 80粉丝 49原创
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值