zoukankan      html  css  js  c++  java
  • LG P5017 [NOIP2018]摆渡车

    题目描述

    (n)名同学要乘坐摆渡车从人大附中前往人民大学,第(i) 位同学在第(t_i) 分钟去 等车。只有一辆摆渡车在工作,但摆渡车容量可以视为无限大。摆渡车从人大附中出发、 把车上的同学送到人民大学、再回到人大附中(去接其他同学),这样往返一趟总共花费(m)分钟(同学上下车时间忽略不计)。摆渡车要将所有同学都送到人民大学。凯凯很好奇,如果他能任意安排摆渡车出发的时间,那么这些同学的等车时间之和最小为多少呢? 注意:摆渡车回到人大附中后可以即刻出发。

    分析

    (f_i)表示在时段([0,i])内用摆渡车接送,且最后一次接送的终止时间为(i)时的时间最小值。枚举上一次的端点(j),注意到(jin [0,i-m]),有

    [f_ileftarrowminleft{sum_{t_kle i}(i-t_k),min_{jle i-m}left{f_j+sum_{j<t_kle i}(i-t_k) ight} ight}, iin[0,t+m)igcupmathbb Z ]

    其中(t=max_{1le kle n}t_k)

    注意到

    [sum_{j<t_kle i}(i-t_k)=sum_{j<t_kle i}i-sum_{j<t_kle i}t_k=icdot (mathrm{cnt}_i-mathrm{cnt}_j)-mathrm{sum}_i+mathrm{sum}_j\ sum_{t_kle i}(i-t_k)=sum_{t_kle i}i-sum_{t_kle i}t_k=icdot mathrm{cnt}_i-mathrm{sum}_i ]

    其中(mathrm{cnt}_i)为时段([0,i])内点的个数,(mathrm{sum}_i)为时段([0,i])内点的时间之和。

    另一方面,最优的(j)只有可能在((i-2m,i-m])之间出现,因为若(jle i-2m),可以再次分割([0,j])使得总时间减少。综上所述,

    [f_ileftarrow minleft{icdot mathrm{cnt}_i-mathrm{sum}_i,min_{i-2m<jle i-m}{f_j+icdot (mathrm{cnt}_i-mathrm{cnt}_j)-mathrm{sum}_i+mathrm{sum}_j ight} ]

    总复杂度(O(tm))

    考虑继续优化。注意到若(mathrm{cnt}_i=mathrm{cnt}_{i-m}),即((i-m,i])中不含任何点,那么(i)是无用的。此时只需令(f_ileftarrow f_{i-m})。复杂度优化至(O(nm^2+t))

    Code

    #include <cstdio>
    #include <iostream>
    
    using namespace std;
    
    const int Maxt=4e6+7;
    const int Maxn=507;
    
    int T,n,m;
    int f[Maxt],sum[Maxt],cnt[Maxt],t;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	
    	for(int i=1;i<=n;++i)
    		scanf("%d",&t),
    		T=max(T,t),
    		sum[t]+=t,
    		++cnt[t];
    	
    	for(int i=1;i<T+m;++i)
    		sum[i]+=sum[i-1],
    		cnt[i]+=cnt[i-1];
    	
    	for(int i=1;i<T+m;++i)
    	{
    		if(i>=m&&cnt[i]==cnt[i-m])
    		{
    			f[i]=f[i-m];
    			continue;
    		}
    		
    		f[i]=i*cnt[i]-sum[i];
    		
    		for(int j=max(0,i-2*m+1);j<=i-m;++j)
    			f[i]=min(f[i],f[j]+i*(cnt[i]-cnt[j])-sum[i]+sum[j]);
    	}
    	
    	int ans=0x3f3f3f3f;
    	
    	for(int i=T;i<T+m;++i)
    		ans=min(ans,f[i]);
    	
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    计算机网络学习目录
    手把手教你玩微信小程序跳一跳
    (三)python函数式编程
    跟托福说分手
    (二)python高级特性
    BitCoin工作原理
    反向传播的工作原理(深度学习第三章)
    1.22计划
    梯度下降——神经网络如何学习?(深度学习第二章)
    什么是神经网络 (深度学习第一章)?
  • 原文地址:https://www.cnblogs.com/Anverking/p/solution-lgp5017.html
Copyright © 2011-2022 走看看