思路: 實際上是用已經確定水位高度的點去更新還沒有確定高度的點。一開始有坑的點的水位高度就是方塊高度。每次取當前最小水位高度的點去更新其他點,就可以保證每個點只需要更新一次。
本題中邊界無限高,所以不用管邊界的影響(更新完就是無窮大)。假設沒有邊界或者邊界高度爲0,那麼同理可以看作已經確定邊界水位高度了,把邊界入堆即可。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 505;
struct Node {
int x,y,h;
bool operator < (const Node&rhs) const {
return h > rhs.h;
}
};
int n,m;
int mxh[maxn][maxn],h[maxn][maxn];
int dirx[] = {0,0,-1,1};
int diry[] = {1,-1,0,0};
priority_queue<Node>q;
void bfs() {
while(!q.empty()) {
Node now = q.top();q.pop();
int x = now.x,y = now.y,H = now.h;
for(int d = 0;d < 4;d++) {
int dx = x + dirx[d];
int dy = y + diry[d];
if(dx < 1 || dy < 1 || dx > n || dy > n) continue;
if(mxh[dx][dy]) continue;
mxh[dx][dy] = max(h[dx][dy],mxh[x][y]);
q.push({dx,dy,mxh[dx][dy]});
}
}
}
int main() {
int T;scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
scanf("%d",&h[i][j]);
mxh[i][j] = 0;
}
}
for(int i = 1;i <= m;i++) {
int x,y;scanf("%d%d",&x,&y);
mxh[x][y] = h[x][y];
q.push({x,y,mxh[x][y]});
}
bfs();
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
printf("%d ",mxh[i][j] - h[i][j]);
}
printf("\n");
}
}
return 0;
}