zoukankan      html  css  js  c++  java
  • CF985C Liebig's Barrels(贪心)(来自洛谷)

    洛谷地址:https://www.luogu.com.cn/problem/CF985C

    题意:

    你有一共m=n*k个木板。第i个木板的长度为ai。你必须用其中的每k条木板组成n个木桶。每条木板只能且必须属于一个木桶。我们把第j个木桶的最短的木板长度作为这个木桶的容积vj

    你想要让这组合起来的n个木桶总容积最大。但是你需要让他们的容积尽量差不多,使得无论那两个木桶的容积差不超过l,即|vx-vy|<=l(1<=vx,vy<=n)。

    输出这n个尽量相等的木桶的最大容积。如果无法组成满足要求的n个木桶,输出“0”

    输入格式

    第一行包括三个分开的整数n,k,l(1<=n,k<=10^5, 1<=n·k<=10^5, 0<=l<=10^9)

    第二行包括m=n*k个整数,表示木板长度a1,a2,...,am ( 1<=ai<=10^9)

    输出格式

    输出一个整数,即n个满足要求的木桶的容积最大值

    输入输出样例

    输入 #1
    4 2 1
    2 2 1 2 3 2 2 3
    
    输出 #1
    7
    
    输入 #2
    2 1 0
    10 10
    
    输出 #2
    20
    
    输入 #3
    1 2 1
    5 2
    
    输出 #3
    2
    
    输入 #4
    3 2 1
    1 2 3 4 5 6
    
    输出 #4
    0

    说明/提示

    In the first example you can form the following barrels: [1,2][1,2] , [2,2][2,2] , [2,3][2,3] , [2,3][2,3] .

    In the second example you can form the following barrels: [10][10] , [10][10] .

    In the third example you can form the following barrels: [2,5][2,5] .

    In the fourth example difference between volumes of barrels in any partition is at least 22so it is impossible to make barrels equal enough.

    解析:

    注意,这个木板选择,是可以不连续的

    首先对木板高度进行从小到大的排序

    1:我们先考虑容积最小的情况:

    n个木桶,对每个木桶的最短处,取a[1]~a[n],是最小的情况,此时最大差值为:a[n]-a[1],如果这个值>l,那么不管怎么组合,都是不能满足题意的。

    那么直接输出0即可。

    2:不管怎么组合,a1一定是某个木桶的容积,那么从这里入手,从前往后找到a[p]-a[1]<=l&&a[p+1]-a[1]>l

    容积最大取到i=p处,p和末尾k-1个组合,即n*k-k+2到n*k,p-1处再和后第2*(k-1)个组合,依次类推。

    如果p后的木板不够用了,就从i=1从前往后每隔k个取1个即可。

    #include<cstdio>
    #include<stack>
    #include<map>
    #include<set>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    priority_queue<int,vector<int>,greater<int> > q;//优先为小的优先队列 
    typedef long long ll;
    const int maxn=1e5+20;
    ll a[maxn];
    struct node
    {
        int x,id;
    }st[maxn];
    bool cmp(node a , node b)
    {
        if(a.x==b.x)
            return a.id<b.id;
        return a.x<b.x;
    }
    int main()
    {    // 4 0 20
        ll n,k,l;
        cin>>n>>k>>l;
        for(int i=1;i<=n*k;i++)
            cin>>a[i];
        sort(a+1,a+1+n*k);
        if(a[n]-a[1]>l)
            cout<<"0"<<endl;
        else
        {
                ll sum=0;
                int p=n*k;
                while(a[p]-a[1]>l)
                    p--;
                int num=0;
                int md=p;
                for(int i=n*k;i-(k-1)>p;i-=(k-1))
                {
                    sum+=a[md--];
                    num++;    
                }
                for(int i=1;i<=(p-num);i+=k)
                    sum+=a[i];
                cout<<sum<<endl;        
        }
    
    }
  • 相关阅读:
    Oracle的function存储函数简单实例
    Java保留小数点后两位,解决精度丢失问题
    天津贷款买房提取公积金相关问题
    Springboot配置连接两个数据库
    JDK8:Lambda根据 单个字段、多个字段,分组求和
    原生Ajax方式请求后端导出Excel,在浏览器页面显示下载Excel表(前端请求带header)
    Java实现 微信小程序 + 消息推送
    Centos7安装docker
    将博客搬至CSDN
    读书笔记——数学之美
  • 原文地址:https://www.cnblogs.com/liyexin/p/13281128.html
Copyright © 2011-2022 走看看