标签:
问题描述
有这样一块土地,它可以被划分N*M个正方形小块,每块面积是一平方英寸,第i行第j列的小块可以表示成P(i,j)。这块土地高低不平,每一小块地P(i,j)都有自己的高度H(i,j)(单位是英寸)。
一场倾盆大雨后,由于这块地地势高低不同,许多低洼地方都积存了不少降水。假如你已经知道这块土地的详细信息,你能求出它最多能积存多少立方英寸的降水么?
输入格式
输入文件的第一行是两个正整数n和m,1<=n<=100,1<=m<=100,表示土地的尺寸。下面n行,每行m个整数(1..10000);第j行第i个数表示第j行第i列立方体的高。
输出格式
输出文件只有一个数,表示在这个建筑上可以聚合的积水的最大值
输入输出样例
输入
3 6 3 3 4 4 4 2 3 1 3 2 1 4 7 3 1 6 4 1
输出
5
下图是其方案:
题解:按高度建一个小根堆,一开始把所有边界上的点入堆,从中取出高度最小的点,从该点开始floodfill,如果碰到比他高的点,就把那个点入堆,如果碰到比他低或相等的点,将高度差累加进答案,然后从那个点继续floodfill。重复以上过程直到堆空。
#include<iostream> #include<cstdio> #include<queue> using namespace std; struct use{ int x,y,h; }; bool operator<(use x,use y){return x.h<y.h;} priority_queue<use>q; int map[101][101],dx[5],dy[5],n,m,ans; bool f[101][101],ff[101][101]; inline int in(){ char c=getchar(); int x=0; while(c<'0'||c>'9')c=getchar(); for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; return x; } inline void floodfill(int x,int y,int hh) { //cout<<x<<' '<<y<<' '<<hh<<endl; for (int i=1;i<=4;i++) { int xx,yy; xx=x+dx[i];yy=y+dy[i]; if (xx>0&&xx<=n&&yy>0&&yy<=m&&!f[xx][yy]) { if (map[xx][yy]<=-hh) {ans+=-hh-map[xx][yy];f[xx][yy]=true;floodfill(xx,yy,hh);} else { if (!ff[xx][yy]) { use a; a.x=xx;a.y=yy;a.h=-map[xx][yy];q.push(a);ff[xx][yy]=true; } } } } } int main() { freopen("wod.in","r",stdin); freopen("wod.out","w",stdout); n=in();m=in(); dx[1]=1;dx[2]=0;dx[3]=-1;dx[4]=0; dy[1]=0;dy[2]=1;dy[3]=0;dy[4]=-1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { map[i][j]=in(); if (i==1||i==n||j==1||j==m) { use a; a.x=i;a.y=j;a.h=-map[i][j]; q.push(a); ff[i][j]=true; } } while (!q.empty()) { use a; a=q.top();q.pop(); if (!f[a.x][a.y]){f[a.x][a.y]=true;floodfill(a.x,a.y,a.h);} } cout<<ans; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
【poi1999】【cogs239】【积水】【堆】【灌水法】【贪心】
标签:
原文地址:http://blog.csdn.net/sunshinezff/article/details/46835271