1. 程式人生 > >【CH2501】 矩陣距離 解題報告

【CH2501】 矩陣距離 解題報告

CH2501 矩陣距離

描述

給定一個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 \le x \le N,1 \le y \le M,A[x][y]=1)⁡{dist(A[i][j],A[x][y])}\)
即求與每個位置曼哈頓距離最近的1
\(N,M \le 1000\)

輸入格式

第一行兩個整數N,M。

接下來一個N行M列的01矩陣,數字之間沒有空格。

輸出格式

一個N行M列的矩陣B,相鄰兩個整數之間用一個空格隔開。

樣例輸入

3 4
0001
0011
0110

樣例輸出

3 2 1 0
2 1 0 0
1 0 0 1

思路

有沒有覺得,有點像洪水填充?

假設只有一個1,我們可以用廣搜來實現。因為每次搜下一個位置,距離都會+1,所以佇列裡元素距起始點的距離是單調遞增的。因此,當我們搜到一個沒有被搜到的位置,直接記錄最優答案即可。

但是這裡有好幾個1。不過這也無妨,我們把這幾個1的ans初始值標記為0,把它們都push進佇列,然後廣搜即可。原理十分簡單。

程式碼

#include<bits/stdc++.h>
using namespace std;
#define open(s) freopen( s".in", "r", stdin ), freopen( s".out", "w", stdout )
#define MAXN 1005

int N, M;
bool a[MAXN][MAXN];
int ans[MAXN][MAXN];
queue<int> Qx, Qy;
char t;
int dir[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };

int main(){
    memset( ans, -1, sizeof ans );
    scanf( "%d%d", &N, &M );
    for ( int i = 1; i <= N; ++i )
        for ( int j = 1; j <= M; ++j ){
            while( ( t =  getchar() ) != '1' && t != '0' );
            a[i][j] = t ^ '0'; if ( a[i][j] ) Qx.push(i), Qy.push(j), ans[i][j] = 0;
        }
    int x, y, tx, ty;
    while( !Qx.empty() ){
        x = Qx.front(); y = Qy.front(); Qx.pop(); Qy.pop();
        for ( int i = 0; i < 4; ++i ){
            tx = x + dir[i][0]; ty = y + dir[i][1];
            if ( tx > 0 && ty > 0 && tx <= N && ty <= M && ans[tx][ty] == -1 ){
                ans[tx][ty] = ans[x][y] + 1; Qx.push(tx); Qy.push(ty);
            }
        }
    }
    for ( int i = 1; i <= N; ++i, putchar('\n') )
        for ( int j = 1; j <= M; ++j )
            printf( "%d ", ans[i][j] );
    return 0;
}