water
题目描述
有一块矩形土地被划分成n*m个正方形小块。这些小块高低不平,每一小块都有自己的高度。水流可以由任意一块地流向周围四个方向的四块地中,但是不能直接流入对角相连的小块中。
一场大雨后,由于地势高低不同,许多地方都积存了不少降水。给定每个小块的高度,求每个小块的积水高度。
注意:假设矩形地外围无限大且高度为0。
输入格式
第一行包含两个非负整数n,m。
接下来n 行每行 个m整数表示第 i行第j列的小块的高度。
输出格式
输出n行,每行m个由空格隔开的非负整数,表示每个小块的积水高度。
样例
样例输入
3 3
4 4 0
2 1 3
3 3 -1
样例输出
0 0 0
0 1 0
0 0 1
数据范围与提示
对于20%的数据
对于40%的数据
对于60%的数据
对于100%的数据
,|小块高度|
。
在每一部分数据中,均有一半数据保证小块高度非负
思路:据题意,找出最外围一圈小块若为负,则一定可以积水(因为矩形外边高度为0,即使旁边也为负且比它矮,两个块也可存水),放入堆中,维护小根堆,一次弹出高度最小的暴搜,若可以存水则标记存水量(注意:存水后要将该块的高度赋为边上的块,因为若高块将矮块围起来,矮块也能存水)
1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=300+10; 6 typedef long long ll; 7 ll a[maxn][maxn],vis[maxn][maxn],b[maxn][maxn];//vis标记该块有无入堆 8 int ans=0,n,m; 9 struct Node{ 10 int x,y,w; 11 Node(){}; 12 Node(int a,int b,int c){ 13 x=a; 14 y=b; 15 w=c; 16 } 17 bool operator<(const Node &a)const{ 18 return w>a.w; 19 } 20 };//重载维护小根堆 21 priority_queue<Node> q; 22 void Init(){ 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++){ 25 for(int j=1;j<=m;j++){ 26 scanf("%lld",&a[i][j]); 27 if(i==1||j==1||i==n||j==m){ 28 if(a[i][j]<0&&!b[i][j]){ 29 b[i][j]-=a[i][j]; 0 0 0 30 a[i][j]=0;//注意置为0,不然若图为 0 -2 -10 若-10未置0,-2就不能存水 31 } 0 0 0 32 if(!vis[i][j])q.push((Node){i,j,a[i][j]}); 33 vis[i][j]=1; 34 } 35 } 36 } 37 } 38 void solve(){ 39 while(!q.empty()){ 40 Node u=q.top(); 41 q.pop(); 42 int x=u.x; 43 int y=u.y; 44 int w=u.w; 45 if(y+1<=m&&!vis[x][y+1]){//右边 46 if(a[x][y+1]>=w) q.push((Node){x,y+1,a[x][y+1]});//不能写continue,这样循环就结束了而不是 47 else { //只if语句结束 48 b[x][y+1]+=(w-a[x][y+1]); 49 a[x][y+1]=w; 50 q.push((Node){x,y+1,w}); 51 } 52 vis[x][y+1]=1; 53 } 54 if(x-1>=1&&!vis[x-1][y]){//上边 55 if(a[x-1][y]>=w) q.push((Node){x-1,y,a[x-1][y]}); 56 else{ 57 b[x-1][y]+=(w-a[x-1][y]); 58 a[x-1][y]=w; 59 q.push((Node){x-1,y,w}); 60 } 61 vis[x-1][y]=1; 62 } 63 if(x+1<=n&&!vis[x+1][y]){//下边 64 if(a[x+1][y]>=w) q.push((Node){x+1,y,a[x+1][y]}); 65 else{ 66 b[x+1][y]+=(w-a[x+1][y]); 67 a[x+1][y]=w; 68 q.push((Node){x+1,y,w}); 69 } 70 vis[x+1][y]=1; 71 } 72 if(y-1>=1&&!vis[x][y-1]){//左边 73 if(a[x][y-1]>=w) q.push((Node){x,y-1,a[x][y-1]}); 74 else{ 75 b[x][y-1]+=(w-a[x][y-1]); 76 a[x][y-1]=w; 77 q.push((Node){x,y-1,w}); 78 } 79 vis[x][y-1]=1; 80 } 81 } 82 } 83 void print(){ 84 for(int i=1;i<=n;i++){ 85 for(int j=1;j<=m;j++){ 86 printf("%lld ",b[i][j]); 87 } 88 printf(" "); 89 } 90 } 91 int main(){ 92 Init(); 93 solve(); 94 print(); 95 return 0; 96 }