[bfs][堆] Jzoj P5830 water

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。
在每一部分数据中,均有一半数据保证小块高度非负

题解

  • 首先,我们可以先将周围一圈的先加入小根堆,对于负数的,先将其定为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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9498353.html
今日推荐