bfs_leetcode 1162 地图分析

将海洋到最近陆地的最长距离,转换为陆地到海洋bfs 最后那个结果的距离。
同理 01矩阵那个题也是一样,将每个元素(0,1)到最近的0的距离,看成0到1的bfs
这两个问题都是正向去思考没办法找到最小。

有时候在纸上画一画就知道将哪个作为源点***更好

以下节选自leetcode题解
你可以想象成你从每个陆地上派了很多支船去踏上伟大航道,踏遍所有的海洋。每当船到了新的海洋,就会分裂成4条新的船,向新的未知海洋前进(访问过的海洋就不去了)。如果船到达了某个未访问过的海洋,那他们是第一个到这片海洋的。很明显,这么多船最后访问到的海洋,肯定是离陆地最远的海洋。

思考:海洋区域和陆地区域,应该哪一个作为源点集? 也许你分析出「我们需要找一个海洋区域,满足它到陆地的最小距离是最大」会把海洋区域作为源点集。我们可以考虑后续的实现,我们知道 Dijkstra 中一个 d 数组用来维护当前源点集到其他点的最短路,而对于源点集中的任意一个点 ss,d[s_x][s_y] = 0,这很好理解,源点到源点的最短路就是 0。如果我们把海洋区域作为源点集、陆地区域作为目标点集,假设 tt 是目标点集中的一个点,算法执行结束后 d[t_x][t_y] 就是海洋区域中的点到 tt 的最短距离,但是我们却不知道哪些 tt 是海洋区域的这些点的「最近陆地区域」,我们也不知道每个 ss 距离它的「最近陆地区域」的曼哈顿距离。考虑我们把陆地区域作为源点集、海洋区域作为目标点集,目标点集中的点 tt 对应的 d[t_x][t_y] 就是海洋区域 tt 对应的距离它的「最近陆地区域」的曼哈顿距离,正是我们需要的,所以应该把陆地区域作为源点集。

直接求解不通,那反着来想,如果遍历陆地,依次筛出到陆地(最近)距离为depth=1,2...的海洋格,那最后剩下的海洋格就是到陆地的最近距离最大的,depth的最后取值就是最大的最近距离。

关键是想明白,以所有陆地格子各为中心、向外一层层延展到每个海洋格子的这种操作,对于每个海洋格子一定是最近的陆地先接触到它,也就是被遍历到,一旦被遍历到它我们就令其对应的grid[p_new[0]][p_new[1]]=1,所以每层记下来的depth就是当前这层格子到陆地的最近距离,最后的depth就是最近距离的最大值。可以参考这个题解中的图

作者:yuer-flyfly
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/di-tu-fen-xi-yan-du-bian-li-python-by-yu-w2ek/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
注意step从-1开始,

class Solution:
    def maxDistance(self, grid: List[List[int]]) -> int:
        # dp=[[0]*len(grid[0]) for _ in range(len(grid))]
        # for i in range(len(grid)):
        #     for j in range(len(grid[0])):
        #         if i-1>=0:
        #             dp[i][j]=max(dp[i-1][j]+1,dp[i][j])
        #         if j-1>=0:
        #             dp[i][j]=max(dp[i][j-1]+1,dp[i][j])

        # for i in range(len(grid)-1,-1,-1):
        #     for j in range(len(grid[0])-1,-1,-1):
        #         if i+1<len(grid):
        #             dp[i][j]=max(dp[i+1][j]+1,dp[i][j])
        #         if j+1<len(grid[0]):
        #             dp[i][j]=max(dp[i][j+1]+1,dp[i][j])
        # maxvalue=0
        # for i in range(len(grid)):
        #     for j in range(len(grid[0])):
        #        maxvalue=max(maxvalue,dp[i][j])

        # return maxvalue
        queue=collections.deque()
        visit=[[0]*len(grid[0]) for _ in range(len(grid))]
        dist=[]
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j]==1:
                    queue.append([i,j])
                    visit[i][j]=1
        directions=[(0,1),(1,0),(-1,0),(0,-1)]
        step=-1
        while queue:
           size=len(queue)
           for _ in range(size):
                item= queue.popleft()
                dx=item[0]
                dy=item[1]
                print([dx,dy])
                for di in directions:
                    x=dx+di[0]
                    y=dy+di[1]
                    if 0<=x<len(grid) and 0<=y<len(grid[0]) and visit[x][y]==0:
                        #print([x,y])
                        queue.append([x,y])

                        visit[x][y]=1
                    else:
                        continue
           #print(visit)
           step+=1
        if step==0:
            return -1
        return step

使用矩阵记录长度

class Solution:
    def maxDistance(self, grid: List[List[int]]) -> int:
        # dp=[[0]*len(grid[0]) for _ in range(len(grid))]
        # for i in range(len(grid)):
        #     for j in range(len(grid[0])):
        #         if i-1>=0:
        #             dp[i][j]=max(dp[i-1][j]+1,dp[i][j])
        #         if j-1>=0:
        #             dp[i][j]=max(dp[i][j-1]+1,dp[i][j])

        # for i in range(len(grid)-1,-1,-1):
        #     for j in range(len(grid[0])-1,-1,-1):
        #         if i+1<len(grid):
        #             dp[i][j]=max(dp[i+1][j]+1,dp[i][j])
        #         if j+1<len(grid[0]):
        #             dp[i][j]=max(dp[i][j+1]+1,dp[i][j])
        # maxvalue=0
        # for i in range(len(grid)):
        #     for j in range(len(grid[0])):
        #        maxvalue=max(maxvalue,dp[i][j])

        # return maxvalue
        queue=collections.deque()
        visit=[[0]*len(grid[0]) for _ in range(len(grid))]
        dist=[]
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j]==1:
                    queue.append([i,j])
                    grid[i][j]=0
                else:
                    grid[i][j]=-1
        directions=[(0,1),(1,0),(-1,0),(0,-1)]
        maxvalue=-1
        print(grid)
        while queue:

                item= queue.popleft()
                dx=item[0]
                dy=item[1]
                print([dx,dy])
                for di in directions:
                    x=dx+di[0]
                    y=dy+di[1]
                    if 0<=x<len(grid) and 0<=y<len(grid[0]) and grid[x][y]==-1:
                        #print([x,y])
                        queue.append([x,y])

                        grid[x][y]=grid[dx][dy]+1

                        maxvalue=max(maxvalue,grid[x][y])
                    else:
                        continue
           #print(visit)
        print(grid) 
        if maxvalue==-1:
            return -1
        return maxvalue

动态规划做法,求各元素到海洋的最短距离。
动态规划 从左上角遍历一遍,当(i, j)为陆地时dis[i][j] = 0;当(i, j)为海洋时,dis[i][j]为上边点与左边点的dis最小值加1。

从右下角遍历一遍,当(i, j)为陆地时dis[i][j] = 0;当(i, j)为海洋时,dis[i][j]为(下边点dis加1)、(右边点的dis加1)、(dis[i][j]本身)三者的最小值。

再去求最大

class Solution:
    def maxDistance(self, grid: List[List[int]]) -> int:
        dp=[[0]*len(grid[0]) for _ in range(len(grid))]
        for i in range(len(grid)):
            for j in range(len(grid[0])): 
                if grid[i][j]==0:
                    dp[i][j]=float('inf')

        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if i-1>=0:
                    if grid[i][j]==0:
                        dp[i][j]=min(dp[i-1][j]+1,dp[i][j])
                if j-1>=0:
                    if grid[i][j]==0:
                        dp[i][j]=min(dp[i][j-1]+1,dp[i][j])

        for i in range(len(grid)-1,-1,-1):
            for j in range(len(grid[0])-1,-1,-1):
                if i+1<len(grid):
                    if grid[i][j]==0:
                        dp[i][j]=min(dp[i+1][j]+1,dp[i][j])
                if j+1<len(grid[0]):
                    if grid[i][j]==0:
                        dp[i][j]=min(dp[i][j+1]+1,dp[i][j])
        maxvalue=0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
               maxvalue=max(maxvalue,dp[i][j])

        if maxvalue==0 or maxvalue==float('inf') :
            return -1
        return maxvalue

通过遍历为0的海洋值,bfs每次求出以此为源点的到最近陆地的距离,最后比较最大值。超时

class Solution:

    def maxDistance(self, grid: List[List[int]]) -> int:
        def find_min(i,j):       
            directions=[(0,1),(1,0),(-1,0),(0,-1)]
            queue=collections.deque()
            visit=[[0]*len(grid[0]) for _ in range(len(grid))]

            queue.append([i,j])
            visit[i][j]=1
            step=0

            while queue:
                size=len(queue)
                for _ in range(size):
                    item= queue.popleft()
                    dx=item[0]
                    dy=item[1]

                    for di in directions:
                        x=dx+di[0]
                        y=dy+di[1]
                        if 0<=x<len(grid) and 0<=y<len(grid[0]) and visit[x][y]!=1:

                            if grid[x][y]==1:

                                return step+1
                            queue.append([x,y])

                            visit[x][y]=1

                        else:
                            continue
                step+=1


            return -1

        maxvalue=-1
        for i in range(len(grid)):
            for j in range(len(grid[0])):

                if grid[i][j]==0:

                    maxvalue=max(maxvalue,find_min(i,j))

        return maxvalue

全部评论

相关推荐

Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务