poj 2227 & usaco 2005 月赛 The Wedding Juicer 题解 bfs+优先队列

来源:互联网 发布:高清混合矩阵由谁控制 编辑:程序博客网 时间:2024/05/21 16:22

参考http://blog.csdn.net/jiangshibiao/article/details/24132503
题目链接:https://vjudge.net/problem/POJ-2227

【题意】给定N*M的一个矩阵表示某一格的高度,求最多能放多少单位的水。自然,水会漫延。【分析】这道题出的挺好。我觉得这不是考验代码能力(P党就无视吧),重在思维。(哇哈哈,其实我也是看题解的)原来的思想是二分枚举水量或高度,但是发现行不通。于是我自然的想到了bfs,,而且想到从边界向中间bfs。但是究竟该怎么控制呢?主要是有一种情况难以考虑:假设边界的最低点是5,但是中间有一个凸起,中间一圈都是7,那么中间的中间最多可以盛7单位。我们可以先把边界上的点全都加入优先队列,同时维护一个小根堆。整个堆的意义是:已堆中元素为边界去盛水。然后我们找到堆首元素并向四个方向拓展。①如果某个点比当前的点高,那么可以把他也加入优先队列中。②如果某个点比当前的点低,那么我就可以多盛(h-h')单位的水(两个高度差)。为什么呢?因为我当前堆首已经满足是整个边界中的最小值了;这样一点水不可能从任何其他边界出去。更新答案后,我们再把拓展出去的点的高度标为当前的高度h并加入优先队列(因为这个点以后可能还能盛水)。直到队列为空,我们已经拓展了所有可能的点了。
#include<cstdio>#include<queue>using namespace std;struct arr{  int x,y,h;  friend bool operator < (const arr &a,const arr &b)  {    return  a.h>b.h;  }}temp;const int dx[4]={0,0,-1,1};const int dy[4]={1,-1,0,0};priority_queue<arr>q;int n,m,i,j,x,y,xx,yy,ans,a[305][305];bool visit[305][305];int main(){  scanf("%d%d",&m,&n);  for (i=1;i<=n;i++)    for (j=1;j<=m;j++)      scanf("%d",&a[i][j]);  for (i=1;i<=m;i++)    q.push((arr){1,i,a[1][i]}),q.push((arr){n,i,a[n][i]}),visit[1][i]=visit[n][i]=true;  for (i=2;i<n;i++)    q.push((arr){i,1,a[i][1]}),q.push((arr){i,m,a[i][m]}),visit[i][1]=visit[i][m]=true;  while (!q.empty())  {    temp=q.top();q.pop();x=temp.x;y=temp.y;    for (i=0;i<=3;i++)    {      xx=x+dx[i];yy=y+dy[i];      if (xx<1||xx>n||yy<1||yy>m||visit[xx][yy]) continue;      visit[xx][yy]=true;      if (a[xx][yy]>=temp.h) q.push((arr){xx,yy,a[xx][yy]});      else ans+=temp.h-a[xx][yy],q.push((arr){xx,yy,temp.h});    }  }  printf("%d",ans);  return 0;}
原创粉丝点击