nyoj 547 水池加水 priority_queue优先级队列初体验

Interesting Punch-Bowl

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
描述

Dr.Kong has taken a side job designing interesting punch-bowl designs. The designs are created as follows:

      * A flat board of size W cm *  H cm is procured        (3 <= W <= 300, 3 <= H <= 300)

      * On every 1 cm x 1 cm square of the board, a 1 cm x 1 cm block is placed.  This block has some integer height B     (1 <= B <= 1,000,000,000)

The blocks are all glued together carefully so that punch will not drain  through them. They are glued so well, in fact, that the corner blocks really don't matter!

Dr.Kong can never figure out, however, just how much punch their bowl designs will hold. Presuming the bowl is freestanding (i.e., no special walls around the bowl), calculate how much juice the bowl can hold.  Some juice bowls, of course, leak out all the juice on the edges and will hold 0.

输入
* Line 1: Two space-separated integers, W and H
* Lines 2..H+1: Line i+1 contains row i of bowl heights: W space-separated integers each of which represents the height B of a square in the bowl. The first integer is the height of column 1, the second integers is the height of column 2, and so on.
There are several test cases and end with the end of the file.
输出
* Line 1: A single integer that is the number of cc's the described bowl will hold.
样例输入
4 5 
5 8 7 7
5 2 1 5
7 1 7 1
8 9 6 9
9 8 9 9
样例输出
12

题目大意:给一个二维数组,在里面加水,不让水流出来,最外层不能加水
解题思路:从最外层向里层遍历,最外层是水池边,将边向里缩小。方法是在最外边找出最低的,找出与之相邻的点,如果给他高,则把该店加入队列,反之,则把高点添加于最低边
相差的水,然后吧修改后的点加入队列,此时水池边就改变了。这样反复进行,至到队列空。
解题关键:这里用优先级队列的诀窍在于,每次加边,我们都能在队列的顶端直接得到最小边,不用遍历
解题难点:这里用到优先级队列的自定义,需要重载:
代码:
View Code
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
using namespace std;
struct node{
    int x,y;
    int h;
    bool operator < (const node &b) const
    {
        return h>b.h;
    };
};
priority_queue<node>q;
int n,m;
int map[301][301];
int visit[301][301];
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int Isborder(int a,int b)
{
    if(a<1||a>n)
        return 1;
    if(b<1||b>m)
        return 1;
    return 0;

}
int  bfs()
{
    node p;
    int ans=0;
    int i;
    while(!q.empty())
        q.pop();
    memset(visit,0,sizeof(visit));
    for(i=1;i<=n;++i)/////***1
    {
        p.x=i;
        p.y=1;
        p.h=map[i][1];
        visit[i][1]=1;
        q.push(p);
        p.x=i;
        p.y=m;
        p.h=map[i][m];
        q.push(p);
        visit[i][m]=1;
    }
    for(i=2;i<m;++i)//***2 将外边加入队列
    {
        p.x=1;
        p.y=i;
        p.h=map[1][i];
        visit[1][i]=1;
        q.push(p);
        p.x=n;
        p.y=i;
        p.h=map[n][i];
        visit[n][i]=1;
        q.push(p);
    }
    int a,b,h2,z,x,h;
    node p2;
    while(!q.empty())
    {
        p2=q.top();
        q.pop();
        z=p2.x;
        x=p2.y;
        h=p2.h;////必须赋值,不然在下面P改变就错啦,自己给自己挖了个坑,检查半天 - -
        for(i=0;i<4;++i)
        {
            a=z+d[i][0];
            b=x+d[i][1];
            h2=map[a][b];
            if(!Isborder(a,b)&&!visit[a][b])
            {
                if(h>h2)
                {
                    ans+=h-h2;
                    h2=h;
                }
                p2.x=a;
                p2.y=b;
                p2.h=h2;
                q.push(p2);
                visit[a][b]=1;
            }
        }
    }
    return ans;
}

            

int main()
{
    int i,j;
    while(scanf("%d%d", &m, &n)!=EOF)
    {
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j)
                scanf("%d",&map[i][j]);
        printf("%d\n",bfs());
    }
    return 0;
}
    
原文地址:https://www.cnblogs.com/zibuyu/p/2970818.html