zoukankan      html  css  js  c++  java
  • moiezen(2018.10.16)

    题意:有n件行李,编号为1~n。行李的质量是模 P 意义下的(P不一定是质数)。有 k 个背包,要装下这些行李,为了方便在背包中找行李,每个背包中的行李编号是连续的,允许有背包为空。我们想让最重的背包尽量轻。你可以选择一个x(0<=x<P),给所有行李的质量+x 并%P,然后才装到背包里去。 你要先选择一个 x,再选择一种行李分配方案,使得最重的背包尽量轻。(n<=10000,P<=10000)

    题解:暴力做法直接枚举x,二分答案即可,时间复杂度(O(nPlogn))
    满分做法就是在暴力基础上加上一个random_shuffle,考虑对x枚举的顺序随机一下,这样枚举到一个x时候,可以先去check一下是否比目前的最优解要优,如果是,那么再去二分,否则直接continue。
    由于一个随机排列中比前面所有数都大的数的数量期望为log,所以复杂度为(O(nP+nlognlogP))

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n,p,k,a[10001],b[10001],c[10001],mx;long long ans;
    bool check(int x)
    {
        if(mx>x)return 0;
        int sum=c[1],now=1;
        for(int i=2;i<=n;i++)
        {
            sum+=c[i];
            if(sum>x)
            {
                now++;
                if(now>k)return 0;
                sum=c[i];
            }
        }
        return 1;
    }
    int main()
    {
        scanf("%d%d%d",&n,&p,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),ans+=a[i];
        for(int j=0;j<p;j++)b[j]=j;
        random_shuffle(b+1,b+p+1);
        for(int i=1;i<=p;i++)
        {
            int now=b[i];mx=0;
            for(int j=1;j<=n;j++)c[j]=(a[j]+now)%p,mx=max(mx,c[j]);
            if(!check(ans))continue;
            int l=0,r=ans;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(check(mid))r=mid;
                else l=mid+1;
            }
            ans=r;
        }
        printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    课堂作业之公文流转
    统计字符出现频率(java)
    课堂测试第八周
    HTML学习笔记——语法+骨架
    HTTP协议
    MVC架构模式概述
    CodeIgniter框架——CI中视图路径问题
    CodeIgniter框架——CI组件间信息流走向
    CodeIgniter框架——数据库类(配置+快速入门)
    chm文件无法阅读
  • 原文地址:https://www.cnblogs.com/lcxer/p/9804904.html
Copyright © 2011-2022 走看看