【NOIP2018】摆渡车

 

 

 【题意】

1、第i个同学在第t[i]分钟到达车站

2、摆渡车一次可以装下无数人

3、两次发车的间隔时间m分钟

求所有等车时间和的最小值

【解题】

我们不妨认为时间是一条数轴,每名同学按照到达时刻分别对应数轴上可能重合的点。

安排车辆的工作,等同于将数轴分成若干个左开右闭段,每段的长度⩾m。原本的等车时间之和,自然就转换成所有点到各自所属段右边界的距离之和。

.

令f(i)表示在第i分钟发出一班车时,所需要等待的最小时间。最后一个人到车站的时间为t

则有: f(i)=min{f(k)+∑(i-a[j],k<a[j]<=i)} 其中 0<=k<=i-m

其最终答案:ans=min{f(i)} 其中t<=i<t+m

这个DP方程的复杂度为O(t2n)

1、前缀和优化

对于∑(i-a[j],k<a[j]<=i)

令cnt[i]表示从0到i时间为止到达车站的人数和

令sum[i]表示从0到i时间为止到达车站的人的时间总和

则有∑(i-a[j],k<a[j]<=i) =i*(cnt[i]-cnt[k])-(sum[i]-sum[k])

即DP方程为 f(i)=min{f(k)+i*(cnt[i]-cnt[k]) -(sum[i]-sum[k])} 其中k<=i-m

此时,时间复杂度降为O(t2)

2、转移优化

试想一下,没有一个同学会等待超过2m分钟。

因为最坏情况下,在k时刻发出了一辆车,有位同学在k+1时刻到达了车站,摆渡车将会在k+m时刻返回,考虑到等待其他学生的情况,摆渡车最晚会在k+2m-1时刻发出(不然还不如在k+m时刻和k+2m时刻各发出一辆)

此时,DP方程为: f(i)=min{f(k)+i*(cnt[i]-cnt[k]) -(sum[i]-sum[k])} 其中i-2m<k<=i-m

此时,时间复杂度为O(tm)

3、状态压缩

很显然,根据上一条优化的结论,当顺序相邻的两位同学的时间间隔超过2m的时候,其中的状态都是无用的,可以直接压缩至2m

即对a排序后,若a[i+1]-a[i]>2m, 则对后续所有的a[k,k>i]-=a[i+1]-a[i]-2m

另外,可以将DP的起点定为第一个同学到达的时间 则最后到车站的时间t最大为2m*n

此时,时间复杂度为O(tm)=O(m2n) 解决

【代码】

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 500 +5;
 4 const int M = 100 +5;
 5 const int T = 4000000 +5;
 6 typedef long long ll;
 7 ll n,m,t;
 8 l
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值