nyoj 547 优先队列

#include<stdio.h>
#include<string.h>
#include<queue>//水杯盛水问题,用优先队列不断从最小的边缘开始
using namespace std;
int n,m;
#define N 400
int p[N][N];
struct node {
  int x,y,w;
  friend bool operator<(node a,node b) {//优先队列
   return a.w>b.w;//从小到大出队
  }
};
int visit[N][N];
int dis[4][2]={1,0,0,1,-1,0,0,-1};//四个方向
int judge(int x,int y) {
if(x<=n&&x>=1&&y<=m&&y>=1&&!visit[x][y])
    return 1;
return 0;
}
int main() {
    int i,j,sum;
while(scanf("%d%d",&m,&n)!=EOF) {
        priority_queue<node>q;
        node cur,next;
        memset(visit,0,sizeof(visit));
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++) {
        scanf("%d",&p[i][j]);
        if(j==1||j==m||i==1||i==n) {//先将杯子的边缘加入
        cur.x=i;cur.y=j;
        cur.w=p[i][j];
        visit[i][j]=1;//标记边缘不能搜索
        q.push(cur);
        }
        }
        sum=0;
        while(!q.empty()) {//每次从最小的边缘开始
            cur=q.top();
            q.pop();
            for(i=0;i<4;i++) {
                int xx=next.x=cur.x+dis[i][0];
                int yy=next.y=cur.y+dis[i][1];
                if(judge(xx,yy)) {//判断
                        visit[xx][yy]=1;
                    if(p[xx][yy]<cur.w) {//如果当前的边缘大于水杯内部
                        sum+=cur.w-p[xx][yy];//高度差即为所能盛的水
                        next.w=cur.w;//改变当前点值
                        q.push(next);
                    }
                    else {//
                        next.w=p[xx][yy];/
                        q.push(next);//
                    }
                }
            }
        }
        printf("%d ",sum);//
    }
return 0;
}
原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410803.html