公主的攻擊範圍
描述
塞爾達公主瘦弱的身體裏面蘊含着不可思議的神聖力量,這個力量從公主所在的位置釋放,可以逐層擴散到加農污穢掌控的區域。
給定一個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;
}