• Codeforces Round #515 (Div. 3) D. Boxes Packing


      

    比赛的时候这题的题意一直没看懂,后面才明白意思就是有n个物品,然后要求最多可以挑选出多少物品,挑选过程是从第一给物品开始往右边挑选,对于每一个物品,如果目前的盒子剩余空间是>=该物品的体积的就直接放进盒子,继续挑选下一个物品,若目前的盒子剩余空间是<该物品的体积的,那就要另外开一个盒子来放物品了,若目前已经没有可用的盒子了,说明这次选取是非法的,那么之前选取的所有物品都不可以得到,然后就把选取的第一个物品退回去,看是否有剩余的空间放下该物品,如果还是放不下的话,继续把第二个拿的物品退回去,直至可以放下该物品为止,然后继续选取下去,若目前还有可用的盒子,那就继续选取下去。选取物品的终点是把最后一个物品也选取了,这样的选取才是合法的,那么盒子的选取的物品的数量的最大值即是我们要的,这个过程可以看出是依次从第1个至第n个物品开始选取物品,若可以把最后一个也选了,那就更新答案,但是这样的话复杂度2e5*2e5是会超时的,然后可以发现起点越大挑选成功的可能性越大,具有单调性,因此可以用二分。

    #include<bits/stdc++.h>
    using namespace std;
    #define fuck(x) cout<<#x<<" "<<x<<endl;
    const int maxn=2e5+10;
    int n,m,k,a[maxn];
    bool check(int mid)
    {
        int rp=k,num=1;
        for(int i=mid;i<=n;i++)
        {
            if(rp>=a[i])
            {
                rp-=a[i];
            }
            else
                if(num<m)
                {
                    num++;
                    rp=k-a[i];
                }
                else
                    return false;
        }
        return true;
    }
    int main()
    {
        scanf("%d %d %d",&n,&m,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&(a[i]));
        }
        int low=1,high=n,mid,ans=0;
        while(low<=high)
        {
            mid=(low+high)/2;
            if(check(mid))
            {
                ans=max(ans,n-mid+1);
                high=mid-1;
                //fuck(mid);
            }
            else
                low=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    217MySQL读写分离mysqlproxy
    shell脚本自动化安装LAMP
    Mybatis的如何根据下划线_,百分号%模糊查询escape的作用
    springboot下MVC的MessageConverters和静态资源位置的配置
    全局性事务控制如何在springboot中配置
    最详细的@Transactional讲解
    常用网址
    truncate、drop、delete区别
    CommandLineRunner、ApplicationRunner 接口
    交叉编译,为什么需要交叉编译
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754862.html
Copyright © 2020-2023  润新知