【CH2501】 矩陣距離 解題報告
阿新 • • 發佈:2018-12-11
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; }