公主的攻击范围
描述
塞尔达公主瘦弱的身体里面蕴含着不可思议的神圣力量,这个力量从公主所在的位置释放,可以逐层扩散到加农污秽掌控的区域。
给定一个N行M列的区域,代号为1的区域是公主能力释放的初始区,代号为0的区域表示需要洁净的区域。
每经过1毫秒,公主的神圣之光向外扩散一格,洁净相邻区域(4个方向),请计算每个标记为0的区域中加农的势力最多还能得瑟几毫秒。
格子与格子之间的距离使用曼哈顿距离计算。
给定一个N行M列的01矩阵A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为:
dist(A[i][j],A[k][l])=|i-k|+|j-l|
输出一个N行M列的整数矩阵B,其中:
B[i][j]=min_{1≤x≤N,1≤y≤M,A[x][y]=1}{dist(A[i][j],A[x][y])}
根据如上公式可知:曼哈顿距离指两点之间的行坐标i距离和列坐标j距离之和。
题目的意思就是求出矩阵中所有节点为0的点,到节点为1的点的曼哈顿距离。
输入
第一行两个整数n,m。
接下来一个N行M列的01矩阵,数字之间没有空格。
数据范围:
1≤N,M≤1000
输出
一个N行M列的矩阵B,相邻两个整数之间用一个空格隔开。每个整数表示加农势力存在的毫秒数(最小曼哈顿距离值)
输入样例
3 4
0001
0011
0110
输出样例
3 2 1 0
2 1 0 0
1 0 0 1
难度
高,BFS
题解
把所有的1的点设置为源点(多源点)
转化为多源点广搜问题
代码
#include<bits/stdc++.h>
using namespace std;
//定义方向向量
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
const int N=1010;
//战斗区域
char g[N][N];
//计算从1的点出发抵达每个0的最短距离
int d[N][N],n,m;
//pair类型变量保存x,y
typedef pair<int,int> PII;
queue<PII>q; //BFS使用的队列
//读入数据
void Build(int n,int m){
memset(d,-1,sizeof(d));
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
char c = getchar();
while (c!='0' && c!='1'){
c = getchar();
}
if(c=='1'){
d[i][j]=0;
q.push(make_pair(i,j)); //压入队列,多源广搜
}
}
}
//输出
void Print(int n,int m){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++) cout<<d[i][j]<<' ';
cout<<endl;
}
}
void bfs(){
while(q.size()){
auto t=q.front();
q.pop();
int x=t.first,y=t.second;
for(int i=0;i<4;i++){
int a=x+dx[i],b=y+dy[i];
if(a>=0 && a<n && b>=0&& b<m && d[a][b]==-1){ //判断是否合法
d[a][b]=d[x][y]+1;
q.push({a,b});
}
}
}
}
int main(void){
cin>>n>>m;
Build(n,m);
bfs();
Print(n,m);
return 0;
}