题解
- 首先,我们可以先将周围一圈的先加入小根堆,对于负数的,先将其定为0
- 然后,bfs每次找到x四周第一个大于它的高度,那么小于它的就是加上h-a[x][y](x和y是当前四周搜到的高度,h为x的高度)
- 以此类推
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <queue>
4 using namespace std;
5 struct edge
6 {
7 int x,y;long long v;
8 bool operator < (const edge &a) const { return v>a.v; }
9 }u;
10 priority_queue <edge> Q;
11 int n,m,visit[310][310],dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},a[310][310],h[310][310];
12 bool pd(int x,int y)
13 {
14 if (x<1||x>n||y<1||y>m||visit[x][y]==1) return false;
15 return true;
16 }
17 void work(int x,int y,int v)
18 {
19 visit[x][y]=1;
20 if (a[x][y]>v)
21 {
22 Q.push((edge){x,y,a[x][y]});
23 return;
24 }
25 h[x][y]+=v-a[x][y];
26 for (int i=0;i<=3;i++)
27 if (pd(x+dx[i],y+dy[i]))
28 work(x+dx[i],y+dy[i],v);
29 }
30 void bfs()
31 {
32 while (!Q.empty())
33 {
34 u=Q.top(),Q.pop();
35 for (int i=0;i<=3;i++)
36 if (pd(u.x+dx[i],u.y+dy[i]))
37 work(u.x+dx[i],u.y+dy[i],u.v);
38 }
39 }
40 int main()
41 {
42 //freopen("water.in","r",stdin);
43 //freopen("water.out","w",stdout);
44 scanf("%d%d",&n,&m);
45 for (int i=1;i<=n;i++)
46 for (int j=1;j<=m;j++)
47 {
48 scanf("%d",&a[i][j]);
49 if (a[i][j]<0) h[i][j]=-a[i][j],a[i][j]=0;
50 if (i==1||j==1||i==n||j==m) Q.push((edge){i,j,a[i][j]}),visit[i][j]=1;
51 }
52 bfs();
53 for (int i=1;i<=n;i++)
54 {
55 for (int j=1;j<=m;j++) printf("%d ",h[i][j]);
56 printf("
");
57 }
58 return 0;
59 }