暴力BFS or 多源最短路 or DP: Leetcode 1162 地图分析

暴力BFS or 多源最短路 or DP: Leetcode 1162 地图分析

问题:

在这里插入图片描述
在这里插入图片描述

思路:

暴力BFS:

对所有海洋坐标点进行BFS,求出它们到最近陆地的曼哈顿距离,再从中选取最大值

对每个(x,y)需向四个方向进行搜索,
即(x,y+1),(x,y-1),(x+1,y),(x-1,y)

需记录遍历到每个坐标点时已走过的距离,因此将坐标点定义为结构体,结构体成员为坐标以及已走过的距离

由于求的是到最近陆地的曼哈顿距离,因此遍历到陆地BFS函数即可返回距离,无需和经典BFS一样等到队列为空

多源最短路:

问题是求所有海洋点集到陆地点集的最短路,是一个多源最短路问题,多源最短路问题可以转化为单源最短路问题,即建立一个超级源点S,它与源点集中的所有点都有边,但权值为0,这样求源点集到目标点集的最短路就变成了求超级源点 S 到它们的最短路。

源点集和目标点集的选择:
源点集为陆地,目标点集为海洋,理由如下:

若源点集为海洋,目标点集为陆地,则目标点集中的点的距离信息为海洋点集中的点到该点的最短路径,举个例子,若海洋1到陆地1的距离为4,海洋2到陆地1的距离为5,则陆地1的距离信息为4,若离海洋1,2最近的陆地均为陆地1,则会发生结果错误,结果应为5而不是4

若源点集为陆地,目标点集为海洋,则目标点集中的点的距离信息为陆地点集中的点到该点的最短路径,即记录了每个海洋节点的最近陆地节点信息,在其中取最大值即可

建立距离矩阵distance, distance[i ] [j ] 表示超级源点到点(i,j)的最短路径距离,初始值为:对于源点集,距离均为0,对于目标点集,距离为无穷大

将源点集中的点全部入队列,进行BFS,对每个节点,向四个方向进行遍历,若当前点的距离值+1小于遍历到的点的距离值,则更新遍历到的点的距离值,并将其入队列

当队列为空时多源BFS执行完毕

遍历目标点集中每个点的距离,取最大值返回


将上述BFS过程看成结点状态更新的过程,在上述过程中,除开最开始就入队的源点集,之后入队的点为状态可更新的点(状态更新后,该状态更新造成的结果可能进一步传播,因此必须入队),状态不能更新的点无须入队。因此是不需要visit标记数组的,在队列为空遍历完成时,所有结点的状态均为最佳


DP:

用f(x,y)表示(x,y)到最近的陆地点的曼哈顿距离
离(x,y)最近的点若在其上方,则需向上走一步,即
f(x,y)=f(x,y-1)+1
若在其左方,则需向左一步
f(x,y)=f(x-1,y)+1
若在其下方,需向下一步
f(x,y)=f(x,y+1)+1
若在其右方,需向右一步
f(x,y)=f(x+1,y)+1

f(x,y)的初始值为:陆地点为0,海洋点为INF
对左和上方的情况进行一轮DP,DP对表的填充从左上方到右下方
在这里插入图片描述
对右和下方的情况进行一轮DP,DP对表的填充从右下方到左上方
在这里插入图片描述
找到海洋点中f(x,y)的最大值,即为所求

代码:

暴力BFS:

class Solution {
public:
    int dx[4]={ 0,0,1,-1 };
    int dy[4]={ 1,-1,0,0 };
    int n,m;
    int visited[101][101];
    vector<vector<int>> matrix;
    struct point
    {
        int x,y;
        int step;
    }; 
    int BFS( int x,int y )
    {      
        int i;
        memset( visited,0,sizeof(visited) );
        queue<point> q;
        q.push( {x,y,0} );
        visited[x][y]=1;
        while( q.size()!=0 )
        {
            auto temp=q.front();
            q.pop();
            for( i=0;i<4;i++ )
            {
                int nx=temp.x+dx[i];
                int ny=temp.y+dy[i];
                if( nx<0 || nx>=m || ny<0 || ny>=n )
                    continue;
                if( visited[nx][ny]==0 )
                {
                    visited[nx][ny]=1;
                    q.push( {nx,ny,temp.step+1} );
                    if( matrix[nx][ny]==1 )
                        return temp.step+1;
                }
            }
        }
        return -1;
    }
    int maxDistance(vector<vector<int>>& grid) {
        int ans=-1;
        int i,j;
        n=grid.size();
        m=grid[0].size();
        matrix=grid;
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
                if( grid[i][j]==0 )
                    ans=max( ans,BFS( i,j ) );
        return ans;
    }
};

多源最短路:

class Solution {
public:
    int dx[4]={ 0,0,1,-1 };
    int dy[4]={ 1,-1,0,0 };
    int n,m;
    int distance[101][101];
    vector<vector<int>> matrix;
    struct point
    {
        int x,y;
    };      
    int maxDistance(vector<vector<int>>& grid) {
        int ans=-1;
        int i,j;
        n=grid.size();
        m=grid[0].size();
        memset( distance,1e+06,sizeof(distance) );
        queue<point> q;
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
                if( grid[i][j]==1 )
                {
                    distance[i][j]=0;
                    q.push( {i,j} );
                }
        while( q.size()!=0 )
        {
            auto temp=q.front();
            q.pop();
            for( i=0;i<4;i++ )
            {
                int nx=temp.x+dx[i];
                int ny=temp.y+dy[i];
                if( nx<0 || nx>=n || ny<0 || ny>=m )
                    continue;
                if( distance[nx][ny]>distance[ temp.x ][ temp.y ]+1 )
                {
                    distance[nx][ny]=distance[ temp.x ][ temp.y ]+1;
                    q.push( {nx,ny} );
                }
            }
        }
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
                if( grid[i][j]==0 )
                    ans=max( ans,distance[i][j] );
        return ans>=1e+05? -1:ans;
    }
};

DP:

class Solution {
public:
    int maxDistance(vector<vector<int>>& grid) {
        int n=grid.size();
        int m=grid[0].size();
        int f[101][101];
        int i,j;
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
            {
                if( grid[i][j]==1 )
                    f[i][j]=0;
                else
                    f[i][j]=1e+06;
            }
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
            {
                if( grid[i][j]==0 )
                {
                    if( i-1>=0 )
                        f[i][j]=min( f[i-1][j]+1,f[i][j] );
                    if( j-1>=0 )
                        f[i][j]=min( f[i][j-1]+1,f[i][j] );
                }
            }
        for( i=n-1;i>=0;i-- )
            for( j=m-1;j>=0;j-- )
            {
                if( grid[i][j]==0 )
                {
                    if( i+1<n )
                        f[i][j]=min( f[i+1][j]+1,f[i][j] );
                    if( j+1<m )
                        f[i][j]=min( f[i][j+1]+1,f[i][j] );
                }
            }
        int ans=-1;
        for( i=0;i<n;i++ )
            for( j=0;j<m;j++ )
            {
                if( grid[i][j]==0 )
                    ans=max(ans,f[i][j]);
            }
        return ans>=1e+05? -1:ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happy19991001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值