UPC-放牛奶的冰箱(二分)

放牛奶的冰箱

时间限制: 1 Sec 内存限制: 256 MB
[提交] [状态]
题目描述
冬冬在古子城购买了一台冰箱,冰箱内部可以表示为高度为h,深度为1,宽度为2的矩阵,最初冰箱底部只有一个架子,但冬冬可以在任何一个格子顶部放隔板,隔板的宽为2,不占用任何空间,将冰箱内部分隔成上、下两部分。
冬冬有n瓶牛奶要按顺序放入冰箱里。第i瓶牛奶的高度是ai,深度和宽度均为1。如果架子上方的相应空间至少与瓶子一样高,他可以在一个架子上放一瓶牛奶,他不能将两瓶牛奶叠在一起(如果它们之间没有架子)。

上图为一个高为7,宽为2的冰箱,在高为5的位置放了一块隔板,冰箱内放了高3瓶牛奶,高度为3、5、2。
冬冬按顺序将牛奶往冰箱里放,他最多能往冰箱里放k瓶牛奶,他想知道k的值为多少?
输入
第一行包含两个整数n和h(1≤n≤106,1≤h≤106)表示牛奶的数量和冰箱的高度。
第二行包含n个整数a1,a2,…,an(1≤ai≤min(100,h))表示第i瓶牛奶的高度。
输出
输出k的值。
样例输入 Copy
【样例1】
5 7
2 3 5 4 1
【样例2】
10 10
9 1 1 1 1 1 1 1 1 1
【样例3】
5 10
3 1 4 2 4
样例输出 Copy
【样例1】
3
【样例2】
4
【样例3】
5
提示

对于60%的数据,1≤n≤1000,1≤h≤1000,1≤ai≤min(100,h)。
对于100%的数据,1≤n≤106,1≤h≤106,1≤ai≤min(100,h)。

思路:
这题太可了!
比赛时没想出来是因为思维被限制了,一直在考虑对于一瓶新的牛奶是另开辟一个隔板还是在原来有牛奶的旁边放,还以为是dp~
其实可以二分做的,因为是按顺序放的,你放多少瓶牛奶和这些牛奶能否放得下一定是具有单调性的。比如,前4瓶牛奶放不下,那么前5瓶牛奶一定也放不下。
接下来就考虑check函数的写法,我们假设的是前mid瓶牛奶都可以放得下,那么在放的过程中一定是取一个最优解,如何才是最优解呢?
我们把前mid瓶牛奶从小到大排序后,因为两个一组,最优解一定是每一组的第二个的和。

for(int i=2;i<=cnt;i+=2){
        tmp-=b[i];
        if(tmp<0) return 0;
    }

但是如果是奇数的话,那么最后一个牛奶的高度就没有被计算上,所以我又改成了这样:

for(int i=2;i<=cnt;i+=2){
        tmp-=b[i];
        if(tmp<0) return 0;
    }
    if(cnt%2) tmp-=b[cnt];

这样就会忽略一个问题,在有些情况下,这种计算方式并不是最优的。
随便举个栗子:
假设当前需要check的牛奶的值分别是1,2,3,4,5
如果按这种方式,所需要的高度x=2+4+5=11;
但是,如果我们把4和5分到一组,3和4分到一组,1自己一组,所需高度就变成了5+3+1=9;

所以:在check函数中,要根据个数的奇偶决定放置方式~(妙啊)
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void read(ll &x){
   ll s = 0, w = 1; char ch = getchar();
   while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
   while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
   x = s*w;
}
const int maxn=1e6+100;
ll a[maxn],n,h,b[maxn];
bool check(ll x){
    int cnt=0;
    for(ll i=1;i<=x;i++)
        b[++cnt]=a[i];
    sort(b+1,b+cnt+1);///从小到大
    ll tmp=h;
    if(cnt%2==0){
        for(int i=2;i<=cnt;i+=2){
            tmp-=b[i];
            if(tmp<0) return 0;
        }
        return 1;
    }
    else{
        tmp=h;
        for(int i=cnt;i>=1;i-=2){
            tmp-=b[i];
            if(tmp<0) return 0;
        }
        return 1;
    }
}
int main(){
     	read(n);read(h);
     	ll sum=0;
        for(ll i=1;i<=n;i++) read(a[i]),sum+=a[i];
        if(sum<h){
            printf("%lld\n",n);
        }
        ll l=0,r=n,res;
        while(l<=r){
            ll mid=(l+r)>>1;
            if(check(mid)) l=mid+1,res=mid;
            else r=mid-1;
        }
        printf("%lld\n",res);
    return 0;
}
全部评论

相关推荐

来个大佬救一下,为上投了都是石沉大海了,没实习经历的话怕秋招直接进不了面。什么实习这么难找,基本
心态爆炸了:现在正式的岗位都少,实习基本不咋招的,除了大厂,中小企业其实没那么多岗位需求,就算是有,大多都是招一两个廉价劳动力,同时,他们也会希望你一来就能干活的,没时间培训你,就让你了解公司的项目,你了解完就可以开始干活。再者是,很多低质量的实习其实用处没有那么大的。我去年也是找实习找到破防,最后去了一家深圳的小公司实习,工作对我来说很简单,甚至不如我在学校做的项目,秋招的时候,这段实习经历也并没有帮上什么忙,投递简历,依旧非常低的回复率。低回复率是常态,尤其是找实习,找不到,那就把重心放在优化自己的简历和项目,多看八股文,锻炼自己的面试能力,多看别人的面经,自己模拟面试,等秋招的时候,只要有那么寥寥几次,好好抓住那几次机会。
点赞 评论 收藏
分享
06-07 17:17
嘉兴学院 教师
心爱的idea:你孩
点赞 评论 收藏
分享
06-26 22:20
门头沟学院 Java
码农索隆:让你把简历发给她,她说一些套话,然后让你加一个人,说这个人给你改简历,然后开始卖课
我的求职精神状态
点赞 评论 收藏
分享
找到实习了&nbsp;给了150一天&nbsp;但是说是低代码&nbsp;值得去吗
码农索隆:是在没实习,可去,待个一两周,不行就润呗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务