zoukankan      html  css  js  c++  java
  • 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("
    ");
    63     }
    64     return 0;
    65 }
    代码
  • 相关阅读:
    动态规划精讲(一)53. 最大子序和
    ACM计算几何总结
    三角形外心的坐标公式
    三角形外心的坐标公式
    高精度模板
    位运算模板
    同余定理与逆元
    扩展欧几里得算法求二元一次方程
    1004. 最大连续1的个数 III
    剑指 Offer 04. 二维数组中的查找
  • 原文地址:https://www.cnblogs.com/wyher/p/9850196.html
Copyright © 2011-2022 走看看