water---------------bfs,堆

题目描述

有一块矩形土地被划分成 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%的数据 n,m<=4

对于 40%的数据 n,m<=15

对于 60%的数据 n,m<=50

对于 100%的数据 n,m<=300,|小块高度|<=10^9。

在每一部分数据中,均有一半数据保证小块高度非负

1. 考虑每处的积水是从哪流出去的。

2. 那么反过来做,考虑当前位置是哪些地方的出口。

3. 由于水往低处流,所以当然要先考虑低处,于是用小根堆维护。

4. 先将最外围全部入队。向其他点扩展,如果扩展点的高度低于

 当前点,那么对其累加答案;否则如果扩展点的高度高于当前

 点,则扩展点不会积水。更新完扩展点后,将其入队,其高度

 取当前点与扩展点的最大值。

5. 需要明确的一点是我们每次都是从最低点出发的,即每个点一

 定是被主要限制其高度的一个方向的节点更新的。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int nx[4]={-1,1,0,0};
 5 const int ny[4]={0,0,-1,1};
 6 int n,m,tx,ty;
 7 bool vis[350][350];
 8 int a[350][350],ans[350][350];
 9 struct node
10 {
11     int x,y,val;
12     bool operator<(const node & p)const
13     {
14         return val>p.val;
15     }
16 }tmp;
17 priority_queue<node > q;
18 bool check(int x,int y)
19 {
20     return x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y];
21 }
22 void bfs()
23 {
24     while(!q.empty())
25     {
26         tmp=q.top();
27         q.pop();
28         for(int i=0;i<=3;++i)
29         {
30             tx=tmp.x+nx[i];
31             ty=tmp.y+ny[i];
32             if(!check(tx,ty))
33                 continue;
34             if(a[tx][ty]<tmp.val)
35                 ans[tx][ty]=tmp.val-a[tx][ty];
36             vis[tx][ty]=true;
37             q.push(node{tx,ty,max(a[tx][ty],tmp.val)});
38         }
39     }
40 }
41 int main()
42 {
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=n;++i)
45         for(int j=1;j<=m;++j)
46             scanf("%d",&a[i][j]);
47     for(int i=1;i<=n;++i)
48     {
49         q.push(node{0,i,0});
50         q.push(node{n+1,i,0});
51     }
52     for(int i=0;i<=m+1;++i)
53     {
54         q.push(node{i,0,0});
55         q.push(node{i,m+1,0});
56     }
57     bfs();
58     for(int i=1;i<=n;++i)
59     {
60         for(int j=1;j<=m;++j)
61             printf("%d ",ans[i][j]);
62         printf("\n");
63     }
64     return 0;
65 }
代码

 

posted @ 2018-10-25 15:35  Hevix  阅读(257)  评论(0编辑  收藏  举报