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])=∣i−k∣+∣j−l∣
输出一个 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]=min1≤x≤N,1≤y≤M,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});
}