/*
给你一个碗,这个碗有点特殊,形状是一个矩形,每个位置上数字是这儿碗底的高度(即:四周的高度比他高的时候这里就可以盛水),求这个碗最多可以装多少水
思路是:这个碗可以被分解成几个(也可能是一个),每个的形状都和我们见到的普通碗一样(即四周高,中间低),
找到这个碗的边缘最低的那块,这个碗盛的水的最高水位就是这个高度,故从这个点开始扩展,比其低的是可以盛水的(加上高度差,并加入q队列,以便继续扩展下去),
比其高的是边缘(还可能是其他碗的边缘,故加入pre优先队列用于寻找下一个碗,所有的碗都是通过寻找最低边缘找到的)
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int x,y;
__int64 h;
friend bool operator <(node a,node b)
{
return a.h>b.h;
}
};
int dir[][2]={-1,0,0,1,1,0,0,-1};
priority_queue<node>pre;
queue<node>q;
__int64 map[310][310];
int vis[310][310];
int w,h;
__int64 ans;
void ini()
{
int i;
node t;
for(i=1;i<=w;i++)
{
t.x=1;
t.y=i;
t.h=map[t.x][t.y];
pre.push(t);
vis[t.x][t.y]=1;
t.x=h;
t.y=i;
t.h=map[t.x][t.y];
pre.push(t);
vis[t.x][t.y]=1;
}
for(i=2;i<h;i++)
{
t.x=i;
t.y=1;
t.h=map[t.x][t.y];
pre.push(t);
vis[t.x][t.y]=1;
t.x=i;
t.y=w;
t.h=map[t.x][t.y];
pre.push(t);
vis[t.x][t.y]=1;
}
}
void bfs()
{
node t,n;
int k;
while(!pre.empty())
{
t=pre.top();
pre.pop();
__int64 max=t.h;
q.push(t);
while(!q.empty())
{
node cur;
cur=q.front();
q.pop();
for(k=0;k<4;k++)
{
n.x=cur.x+dir[k][0];
n.y=cur.y+dir[k][1];
n.h=map[n.x][n.y];
if(n.x>0&&n.x<=h&&n.y>0&&n.y<=w&&!vis[n.x][n.y])
{
vis[n.x][n.y]=1;
if(n.h>max)//这里错过,之前写成了n.h>cur.h,寻找的是比当前这个池子最大水平线高的岸,若n.h>cur.h会导致不是岸的地方变成岸(本来可以在这儿注水,现在不可以了)
{
pre.push(n);
}else
{
q.push(n);
ans+=max-n.h;
}
}
}
}
//printf("%I64d\n",ans);
}
}
int main()
{
node t,n;
scanf("%d%d",&w,&h);
memset(vis,0,sizeof(vis));
int i,j,k;
ans=0;
for(i=1;i<=h;i++)
for(j=1;j<=w;j++)
scanf("%I64d",&map[i][j]);
ini();
bfs();
printf("%I64d\n",ans);
return 0;
}
poj 2227 The Wedding Juicer--floodfill--bfs
最新推荐文章于 2020-11-20 17:24:01 发布