water(搜索)

                                                     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 }
View Code
原文地址:https://www.cnblogs.com/HZOIDJ123/p/13416745.html