1 条题解

  • 0
    @ 2025-8-24 22:31:59

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 封禁用户
    None

    搬运于2025-08-24 22:31:59,当前版本为作者最后更新于2021-07-29 15:37:44,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    供题人前来报到,现分享自己的解题思路及代码、官方解题代码、双倍经验告知。
    题目传送>>P7666

    题意简述

    JOI 君会在家中有客人时开着可随时开关闭的炉子。现他有 KK 根可开炉子的火柴,将有 NN 名客人分别在已知的特定时刻 TiT_i 前来并在 Ti+1T_i+1 离开,求炉子最短总运行时间。

    题目分析:

    因为客人在的时刻是零零散散的,所以就会存在一些无客人的时间间隔,而要想使炉子运行总时间最短,那么我们应尽可能地在合适的时刻及时关闭炉子,避免在无客人时造成炉子浪费,即尽可能做到只有有客人在时炉子才开着。而在下一次来客人时再打开炉子是需要消耗火柴的,而火柴数量又有限,所以有时我们可能需要保持炉子运行(即使此时无客人)。
    当第一位客人前来时我们必须消耗一根火柴打开炉子,但如果一直保持运行到最后一名客人走显然是不理智的。我们需要尽可能的避免较长时间无客人间隔运行炉子,此时我们就可在当前客人走时关闭炉子,在下一名客人来时再开炉子。即每多一根火柴,我们就可尽可能的避免一个无客间隔浪费。
    综上分析,我们可以分别计算各无客间隔时长(共 N1N-1 个无客间隔),然后优先依靠炉子关开避免较大无客间隔期间的浪费。

    Code1(己):

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,k;   //定义客人数、火柴数 
    int a[100010],b[100010];   //开数组存各客人前来的时刻、各无客间隔时长 
    int ans=0;   //定义炉子运行总时长 
    int main()
    {
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	cin>>n>>k; 
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	ans+=a[n]-a[1]+1;   //如不能避免无客间隔的全程时长 
    	for(int i=1;i<n;i++)
    	{
    		b[i]=a[i+1]-a[i]-1;   //分别计算各无客间隔时长
    	}
    	sort(b+1,b+n);   //对各无客间隔时长排序(默认递增) 
    	for(int i=n-1;i>=n-k+1;i--)   //因为递增排的序所以回着循环 ,注意共n-1个间隔,共k根火柴 
    	{
    		ans-=b[i];   //优先依靠炉子关开避免较大无客间隔期间的浪费并,减去间隔时长 
    	}
    	cout<<ans;	
    	return 0;
    }
    

    Code2(官方)(C++11及以上):

    #include <bits/stdc++.h>
    using namespace std;
    
    #define REP(i,n) for(int i=0;i<n;i++)
    #define PB push_back
    
    using vi=vector<int>;
    
    int read(){
    	int i;
    	scanf("%d",&i);
    	return i;
    }
    
    int main(){
    	int n=read(),k=read();
    	int mn,mx,last;
    	vi len;
    	REP(i,n){
    		int t=read();
    		if(i==0)mn=t;
    		if(i==n-1)mx=t+1;
    		if(0<i)len.PB(t-last-1);
    		last=t;
    	}
    	sort(len.begin(),len.end(),greater<int>());
    	int ans=mx-mn;
    	REP(i,k-1)ans-=len[i];
    	cout<<ans<<endl;
    }
    

    结果(己)(未吸氧):

    JieGuo

    双倍经验

    本供题人在供此题时即发现了此题与之前做过的一题基本同思路,现分享双倍经验>>P1209 [USACO1.3]修理牛棚 Barn Repair,区别即为后者输入数据多了一个无关变量且输入数据可能无序需多一次排序。
    企鹅的题解到此结束,祝各位 OIers 进步 ++~

    • 1

    信息

    ID
    6866
    时间
    1000ms
    内存
    256MiB
    难度
    2
    标签
    递交数
    0
    已通过
    0
    上传者