Juice

【题目描述】

Jonh正在研制一种有趣的“水杯”:

1)底面是W x H 的相同小方格组成 

2)每个小方格上放置一个底面是1x1的,高度是B的水晶块。

这些水晶块都粘贴在一块,之间不会漏水。

John在制成之前,想知道他所要制的这种“水杯”能最多装多少水?

 

【数据范围】

 3 <= W <= 300, 3 <= H <= 300

1 <= B <= 1,000,000,000


【输入文件】

(juice.in)

第一行:两个整数: W 和 H

下面有H行:每行有W个整数。1+i行表示第i行的每个格子上的水晶块的高度。

【输出文件】

 (juice.out)

只一个整数,表示最多可装水多少。1单位为:1(宽)*1(长)*1(高)


【样例输入】

4 5

5 8 7 7

5 2 1 5

7 1 7 1

8 9 6 9

9 8 9 9

【样例输出】

12

【样例解释】

两个高度为1的和一个高度为2的

可装水到高度为5;一个高度

为6的可装水到高度为7。共装

水2*4 + 3 + 1 = 12.




一开始想的是枚举每一层 验证有多少空白的上下左右有方块

后来看B的范围太大 只能放弃

也有机房小伙伴bfs写 写了一会也放弃了。。。


正解是堆

盛水的多少,不在于木桶上那块最长的木板,而在于木桶上最短的那块木板。

因此,我们从“边上”考虑,每次优先处理的是“最短的那块木板”,由于本题中间可能有更高的“块”,可以由外向内地逐步处理,“边”也逐步“加高”

5 8 7 7
5 2 1 5
7 1 7 1
8 9 6 9
9 8 9 9

我们首先处理的是(3,4) 发现它没法向内扩展 也没法向上下扩展

然后处理5  以处理(2,4)为例 它比(2,3)高 可以以(2,4)的高度围出一个至少为5的边框(因为高度小的排在前面)

那么可以将(2,3)更新为高度5 然后将(2,3)加入队列 作为新的边框 向内更新


蒟蒻不会堆怎么办 现成的优先队列啊!!!

另外还要注意输入的先列后行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int mx[5]={0,1,0,-1,0};
const int my[5]={0,0,1,0,-1};

struct node{
    int x,y,h;
    bool operator<(node a1)const
    {
        if(h==a1.h)
        {
            if(x==a1.x)return y>a1.y;
            return x>a1.x;
        }
        return h>a1.h;
    }
};
priority_queue<node>q;

int m,n;
int s[313][313];
int z,a,b,c;
bool p[313][313];

void add(int x,int y,int h)
{
    int xx,yy;
    for(int k=1;k<=4;k++)
    {
        xx=x+mx[k],yy=y+my[k];
        if(xx<1||xx>m||yy<1||yy>n)continue;
        if(!p[xx][yy])
        {
            q.push((node){xx,yy,s[xx][yy]});
            p[xx][yy]=1;
        
            if(s[x][y]>s[xx][yy])
            {
                int t=s[x][y]-s[xx][yy];
                s[xx][yy]=s[x][y];
                z+=t;
            }
        }
    }
}

int main()
{
    freopen("juice.in","r",stdin);freopen("juice.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(a=1;a<=m;a++)
       for(b=1;b<=n;b++)
       {
            scanf("%d",&s[a][b]);
            if(a==1||b==1||a==m||b==n)
            {
                q.push((node){a,b,s[a][b]});
                p[a][b]=1;
            }
       }

    while(!q.empty())
    {
        node u=q.top();
        q.pop();
        add(u.x,u.y,u.h);
    }
    
    cout<<z<<'\n';
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值