• [BZOJ] IOI2015 Boxes纪念品盒


    问题描述

    IOI2015 开幕式正在进行最后一个环节。按计划在开幕式期间,每个代表队都将收到由主办方发放的一个装有纪念品的盒子。然而所有志愿者都被精彩的开幕式所吸引,除 Aman外其他人完全忘记了发放纪念品这件事。Aman 是一位热情的志愿者,为使得 IOI 尽量圆满,他要用最短的时间将所有纪念品发放出去。

    开幕式的场地是一个圆环,被分为 个完全相等的区域,这些区域的编号依次为 0 到 L-1,也就是说,对于 0≤i≤L-2,区域 i 与区域 i+1 相邻,且区域 L-1 与区域 0 相邻。场地上共有N 个代表队,每队坐在上面的一个区域上,每个区域可以包含任意多个代表队,也可以为空。共有 N 个相同的纪念品。开始,Aman 和所有纪念品都在区域 0。Aman 应该给每队一个纪念品,并且在发放完最后一个纪念品后他必须回到区域 0。注意,有些队可能坐在区域 0。

    在任意时刻,Aman 只能够携带至多 K 个纪念品。Aman 必须从区域 0 取走这些纪念品,且取纪念品不需要时间。纪念品一旦从区域 0 被取走后,Aman 只能将其发放给某个代表队或者随身携带。无论何时,Aman 携带一个或更多的纪念品到达一个这样的区域,该区域有一个代表队尚未收到纪念品,Aman 便可将他携带的一个纪念品发给这个代表队。这种发放也在瞬间完成。他所花的时间都消耗在区域之间的移动上。无论携带多少纪念品,Aman 都需要 1 秒钟从一个区域移动到其相邻的区域(可以顺时针移动也可以逆时针移动)。

    你的任务是计算出 Aman 发放完所有纪念品并返回到他的最初区域所需要的最短时间(秒数)。

    输入格式

    第一行: N K L
    第二行: positions[0] ... positions[N-1]
    N: 代表队的数目。
    K: Aman 在同一时间能够携带纪念品的最大数目。
    L: 开幕式场地上的区域数目。
    positions: 一个长度为 N 的数组,positions[0],...,positions[N-1]给出了所有代表队所在区域的编号。positions 的元素按非递减排序。

    输出格式

    一个整数,表示 Aman 能够完成这一任务所需的最短时间(秒数)。

    样例输入输出

    Input
    3 2 8
    1 2 5
    Output
    10

    解析

    考虑到只有三种移动方式,往左再回来,往右再回来,以及绕一圈。再仔细考虑,绕一圈在最优解中只有可能进行一次,因为假设绕了两次,一共发放了2k件物品,那么左右半圈一定有一个的团队数量大于等于k,所以在最开始往左或往右后在绕一圈不会更差。

    由此,我们使用贪心策略,用第一第二种方法将靠近0的一些团队解决,再绕一圈解决中间没拿到纪念品的。分别预处理左半圈和右半圈每个点i送到所需的时间,然后枚举长度为k的连续区间,这段区间内通过绕一圈解决,计算答案取最小值即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define N 10000002
    using namespace std;
    long long n,k,l,i,pos,s1[N],s2[N],f1[N],f2[N],top1,top2;
    long long read()
    {
    	char c=getchar();
    	long long w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int main()
    {
    	n=read();k=read();l=read();
    	for(i=1;i<=n;i++){
    		pos=read();
    		if(pos<=l/2) s1[++top1]=pos;
    		else s2[++top2]=pos;
    	}
    	int tmp[N];
    	for(i=1;i<=top2;i++) tmp[i]=s2[top2-i+1];
    	for(i=1;i<=top2;i++) s2[i]=tmp[i];
    	for(i=1;i<=top1;i++){
    		if(i<=k) f1[i]=s1[i];
    		else f1[i]=f1[i-k]+s1[i];
    	}
    	for(i=1;i<=top2;i++){
    		if(i<=k) f2[i]=l-s2[i];
    		else f2[i]=f2[i-k]+l-s2[i];
    	}
    	long long ans=(f1[top1]+f2[top2])*2;
    	for(i=top1-k;i<=top1;i++){
    		ans=min(ans,(f1[max(i,1LL*0)]+f2[max(top2-k+top1-i,1LL*0)])*2+l);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    Linux服务器查看日志命令总结
    nginx高可用(5)
    nginx动静分离(4)
    nginx负载均衡(3)
    nginx反向代理(2)
    nginx安装及使用(1)
    Nginx 简易教程
    uiautomator2中文文档
    TKinter之输入框
    nginx解决反向代理session丢失问题
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11415331.html
Copyright © 2020-2023  润新知