(算法提高课)搜索-多源BFS

173. 矩阵距离

给定一个 N行 M列的 01矩阵 A, A [ i ] [ j ] A[i][j] A[i][j] A [ k ] [ l ] A[k][l] A[k][l]之间的曼哈顿距离定义为: d i s t ( A [ i ] [ j ] , A [ k ] [ l ] ) = ∣ i − k ∣ + ∣ j − l ∣ dist(A[i][j],A[k][l])=|i−k|+|j−l| dist(A[i][j],A[k][l])=ik+jl
输出一个 N行 M列的整数矩阵 B,其中:
B [ i ] [ j ] = m i n 1 ≤ x ≤ N , 1 ≤ y ≤ M , A [ x ] [ y ] = 1 d i s t ( A [ i ] [ j ] , A [ x ] [ y ] ) B[i][j]=min_{1≤x≤N,1≤y≤M,A[x][y]=1}dist(A[i][j],A[x][y]) B[i][j]=min1xN,1yM,A[x][y]=1dist(A[i][j],A[x][y])
输入格式
第一行两个整数 N,M。
接下来一个 N行 M列的 01矩阵,数字之间没有空格。
输出格式
一个 N 行 M列的矩阵 B,相邻两个整数之间用一个空格隔开。
数据范围
1≤N,M≤1000
输入样例:
3 4
0001
0011
0110
输出样例:
3 2 1 0
2 1 0 0
1 0 0 1
难度:简单

自己写版本

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 1010;

int a[N][N];
int dis[N][N];
queue<PII> q;  //用来存储起始原点
int n,m;

void bfs()
{
    PII t;
    int dx[] = {-1,0,0,1};
    int dy[] = {0,-1,1,0};

    while(!q.empty()){
        t = q.front(); q.pop();
        int x = t.first;
        int y = t.second;

        for(int i = 0;i < 4;i ++){
            int sx = x + dx[i];
            int sy = y + dy[i];
            if(sx < 0 || sy < 0 || sx >= n || sy >= m) continue;
            if(dis[sx][sy] == 0 || dis[sx][sy] == 1) continue;
            
            int s = dis[x][y] + 1;
            if(dis[sx][sy] == -1 || s < dis[sx][sy]){
                dis[sx][sy] = s;
                q.push({sx,sy});    
            }
        }

    }

}
int main()
{
    cin>>n>>m;
    memset(dis, -1 ,sizeof dis);
    PII t;
    for(int i = 0;i < n;i ++){
        string s;
        cin>>s;
        for(int j = 0;j < m;j ++){
            a[i][j] = s[j] - 48;
            if(a[i][j]){
                dis[i][j] = 0;
                t = {i,j};
                q.push(t);
            }
        }
    }

    bfs();
    
    for(int i = 0;i < n;i ++){
        for(int j = 0;j < m;j ++){
            cout<<dis[i][j]<<" ";
        }
        cout<<endl;
    }

    return 0;
}

通过了测试但是运行时间很长
运行图片
本质上对广搜的认识不够准确,之所以在最短路径问题中使用BFS模型,就是因为我是逐层访问,当一个节点第一次被访问到时,它一定位于距离远点最短/近的一层,所以在这里做判断后再更新值完全是非必要的
但改进后对时长的缩短效果不是特别明显,看题解区的答案时间大多也不短,对循环内部的改进如下

for(int i = 0;i < 4;i ++){
    int sx = x + dx[i];
    int sy = y + dy[i];
    if(sx < 0 || sy < 0 || sx >= n || sy >= m) continue;
    if(dis[sx][sy] != -1) continue;  
    //这里相当于dis[][]既是一个保存层数的数组,也是一个是否访问的数组,按照源头节点是第一层直接逐层访问就好了
    
    dis[sx][sy] = dis[x][y] + 1;
    q.push({sx,sy});
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值