POI 1999 Water

本文探讨了一个关于积水问题的解决方法,通过使用最小堆和Floodfill算法来计算池塘中最多能积存的水量。详细介绍了算法实现过程,并附带了关键代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

积水问题。

题目:http://main.edu.pl/en/archive/oi/6/wod

题意:一个凹凸不平的池塘,每一个块儿高度不同,因而下雨后由于相邻的高度落差会有积水。问:这个池塘最多积水多少。

我们可以用一个最小堆来维护当前堆里高度的最小值。

边界的块儿不可能积水,全部边界点入队列。然后Pop一个点开始Floodfill,寻找比他高度小的,这样的块儿会有积水。积水的多少位高度差,比他高度大的入队列。继续对堆里的点Floodfill

对于堆的维护,直接用S TL优先队列即可。自己手敲也可以。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std;

struct Point
{
    int x,y;
    int h;
    Point()
    {
    }
    Point(int x1,int y1,int h1)
    {
        x = x1;
        y = y1;
        h = h1;
    }
};
int n,m;

int map[105][105];
int vis[105][105];

int disx[4] = {-1,0,1,0};
int disy[4] = {0,1,0,-1};

int total = 0;
//定义比较结构
struct cmp
{
    bool operator ()(Point &a,Point &b)
    {
        return a.h>b.h;
    }
};

priority_queue<Point,vector<Point>,cmp> p;

void floodfill(int x,int y,int h)
{
    for(int i=0;i<4;i++)
    {
        int tempx = x + disx[i];
        int tempy = y + disy[i];
        if(tempx>=1 && tempx<=n && tempy>=1 && tempy<=m && vis[tempx][tempy] == 0)
        {
            vis[tempx][tempy] = 1;
            if(map[tempx][tempy] >= h)
            {
                Point t;
                t.x = tempx,t.y = tempy,t.h = map[tempx][tempy];
                p.push(t);
            }
            else
            {
                total = total + (h - map[tempx][tempy]);
                floodfill(tempx,tempy,h);
            }
        }
    }
}
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif*/

    while(scanf(" %d %d",&n,&m)!=EOF)
    {
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        total = 0;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                scanf(" %d",&map[i][j]);
            }
        }
        //清空最小堆
        while(!p.empty()) p.pop();

        for(int i=1;i<=n;i++)
        {
            Point t1(i,1,map[i][1]),t2(i,m,map[i][m]);
            if(m == 1)
            {
                p.push(t1);
            }
            else
            {
                p.push(t1),p.push(t2);
            }

            vis[t1.x][t1.y] = 1;
            vis[t2.x][t2.y] = 1;
        }
        for(int j=2;j<=m-1;j++)
        {
            Point t1(1,j,map[1][j]),t2(n,j,map[n][j]);
            if(n == 1)
            {
                p.push(t1);
            }
            else
            {
                p.push(t1),p.push(t2);
            }

            vis[t1.x][t1.y] = 1;
            vis[t2.x][t2.y] = 1;
        }

        while(!p.empty())
        {
            Point temp;
            temp = p.top();
            p.pop();
            floodfill(temp.x,temp.y,map[temp.x][temp.y]);

        }
        printf("%d",total);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值