• water


    题目描述:

    有一块矩形土地被划分成$n$ $*$ $m$个正方形小块。这些小块高低不平,每一小块都有自己的高度。水流可以由任意一块地流向周围四个方向的四块地中,但是不能直接流入对角相连的小块中。

    一场大雨后,由于地势高低不同,许多地方都积存了不少降水。给定每个小块的高度,求每个小块的积水高度。

    注意:假设矩形地外围无限大且高度为$0$。

    输入格式:

    第一行两个非负整数$n$,$m$。

    接下来一个$n$ $*$ $m$的矩阵,表示每个小块的高度。

    输出格式:

    输出一个$n$ $*$ $m$的矩阵,表示每个小块的积水高度。

    输入样例:

    3 3
    4 4 0
    2 1 3
    3 3 -1
    

    输出样例:

    0 0 0
    0 1 0
    0 0 1

    数据范围:

    $n$,$m$ $≤$ $300$,小块高度 $≤$ $10$9




    思路:

    首先可以了解到积水高度和周围最高的小块的高度有关。

    对于小块$i$,它的积水高度会与四周最高的山峰的最低值相等,如木桶原理。

    因此可以考虑对于每个小块$i$,将它与它四周的小块连边,边权为两座山峰中的最大值,然后跑最小生成树,最后通过dfs求得周围最高山峰中的最低的那一个即为它的积水高度。

    对于在边界上的小块,只需要与定义$0$号点为边界外的点连边,然后$0$号点的高度为$0$。

    代码:

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 using namespace std;
     4 int n, m, q[1010][1010], z, fa[1000010], num, head[1000010];
     5 struct Tree {int x, y, z;}tree[2000010];
     6 struct node {int next, to, val;}stu[2000010];
     7 int cmp(Tree a, Tree b) {return a.z < b.z;}
     8 int find(int x) {return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);}
     9 void unity(int x, int y) {fa[find(x)] = find(y); return;}
    10 void add(int x, int y, int z) {stu[++num].next = head[x], stu[num].to = y, stu[num].val = z, head[x] = num; return;}
    11 void edge(int ax, int ay, int bx, int by)
    12 {
    13     int numa, numb;
    14     if(ax < 1 || ay < 1 || ax > m || ay > n) numa = 0; else numa = (ax - 1) * m + ay;
    15     if(bx < 1 || by < 1 || bx > m || by > n) numb = 0; else numb = (bx - 1) * m + by;
    16     tree[++z].x = numa, tree[z].y = numb, tree[z].z = max(q[ax][ay], q[bx][by]);
    17     tree[++z].x = numb, tree[z].y = numa, tree[z].z = max(q[ax][ay], q[bx][by]);
    18     return;
    19 }
    20 void kruskal()
    21 {
    22     for(int i = 1; i <= n * m; ++i) fa[i] = i;
    23     sort(tree + 1, tree + z + 1, cmp);
    24     for(int i = 1; i <= z; ++i)
    25     {
    26         if(find(tree[i].x) != find(tree[i].y))
    27         {
    28             unity(tree[i].x, tree[i].y);
    29             add(tree[i].x, tree[i].y, tree[i].z), add(tree[i].y, tree[i].x, tree[i].z);
    30         }
    31     }
    32     return;
    33 }
    34 void dfs(int u, int father, int sum)
    35 {
    36     for(int i = head[u]; i; i = stu[i].next)
    37     {
    38         int k = stu[i].to;
    39         if(k == father) continue;
    40         int xx = k / m + 1, yy = k % m;
    41         if(!yy) --xx, yy = m;
    42         q[xx][yy] = max(sum, stu[i].val) - q[xx][yy];
    43         dfs(k, u, max(sum, stu[i].val));
    44     }
    45     return;
    46 }
    47 int main()
    48 {
    49     scanf("%d %d", &n, &m);
    50     for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) scanf("%d", &q[i][j]);
    51     for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) edge(i, j, i - 1, j), edge(i, j, i + 1, j), edge(i, j, i, j - 1), edge(i, j, i, j + 1);
    52     kruskal();
    53     dfs(0, -1, -INF);
    54     for(int i = 1; i <= n; ++i) {for(int j = 1; j <= m; ++j) printf("%d ", q[i][j]); puts("");}
    55     return 0;
    56 }
  • 相关阅读:
    活久见!Jmeter也能实现文件传输和发送邮件啦
    震惊!资深测试开发已经不用postman测试接口了!
    app测试日志如何获取,logcat值得拥有
    TestNG学会了,Java单元测试你就掌握了一半
    超实用:精准衡量接口测试覆盖率
    Reviewboard用户指南(1.3)—— Getting Started: General Workflow
    Reviewboard用户指南(1.2)—— Getting Started: What is Code Review?
    Reviewboard用户指南(1.4)—— Getting Started: Account Settings
    Reviewboard管理员指南(4.1)—— Overview of the Administration UI
    Reviewboard用户指南(6.4)——Issue Tracking
  • 原文地址:https://www.cnblogs.com/qqq1112/p/13578010.html
Copyright © 2020-2023  润新知