poj 2227 The Wedding Juicer--floodfill--bfs

/*
给你一个碗,这个碗有点特殊,形状是一个矩形,每个位置上数字是这儿碗底的高度(即:四周的高度比他高的时候这里就可以盛水),求这个碗最多可以装多少水
思路是:这个碗可以被分解成几个(也可能是一个),每个的形状都和我们见到的普通碗一样(即四周高,中间低),
找到这个碗的边缘最低的那块,这个碗盛的水的最高水位就是这个高度,故从这个点开始扩展,比其低的是可以盛水的(加上高度差,并加入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)