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

版权声明:菜鸡博客大佬随便转 https://blog.csdn.net/qq_40642465/article/details/83040352

  

比赛的时候这题的题意一直没看懂,后面才明白意思就是有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\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40642465/article/details/83040352