算法實踐:公主的攻擊範圍

公主的攻擊範圍

描述

塞爾達公主瘦弱的身體裏面蘊含着不可思議的神聖力量,這個力量從公主所在的位置釋放,可以逐層擴散到加農污穢掌控的區域。

給定一個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;    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章