Description
有一块矩形土地被划分成 n*m 个正方形小块。这些小块高低不 平,每一小块都有自己的高度。水流可以由任意一块地流向周围四个 方向的四块地中,但是不能直接流入对角相连的小块中。 一场大雨后,由于地势高低不同,许多地方都积存了不少降水。 给定每个小块的高度,求每个小块的积水高度。 注意:假设矩形地外围无限大且高度为 0。
Input
第一行包含两个非负整数 n,m。 接下来 n 行每行 m 个整数表示第 i 行第 j 列的小块的高度。
Output
输出 n 行,每行 m 个由空格隔开的非负整数,表示每个小块的积 水高度。
Sample Input
3 3 4 4 0 2 1 3 3 3 -1
Sample Output
0 0 0 0 1 0 0 0 1
Data Constraint
对于 20%的数据 n,m<=4
对于 40%的数据 n,m<=15
对于 60%的数据 n,m<=50
对于 100%的数据 n,m<=300,|小块高度|<=10^9。
在每一部分数据中,均有一半数据保证小块高度非负
对于 40%的数据 n,m<=15
对于 60%的数据 n,m<=50
对于 100%的数据 n,m<=300,|小块高度|<=10^9。
在每一部分数据中,均有一半数据保证小块高度非负
题解
- 首先,我们可以先将周围一圈的先加入小根堆,对于负数的,先将其定为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("\n"); 57 } 58 return 0; 59 }