#2306. NOIP2018 普及组 第三题 摆渡车

NOIP2018 普及组 第三题 摆渡车

Description

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

Input Format

第一行包含两个正整数n,m,以一个空格分开,分别代表等车人数和摆渡车往返一趟的时间
第二行包含n个正整数,相邻两数之间以一个空格隔开,第i个非负整数ti代表第i个学生到达车站的时刻

Output Format

输出一行,一个整数,表示所有同学等车时间之和的最小值(单位:分钟)。
【输入输出样例 1】
5 1 
3 4 4 3 5 
【输入输出样例 2】
5 5 
11 13 1 5 5 
【输入输出样例 1】
0
【输入输出样例 2】
4

Hint

对于100%的数据,n<=500,m<=100,0<=ti<=4*10^6;

f[i][j]代表前i个同学,第i个同学在第t[i]+j分钟到达的最小等待时间总和,这样的状态就不会出错。其实,这样设置后我们可以很简单地划分阶段,f[i][j]不需要从f[k][l]转移,只需要从f[i−1][k]转移即可,因为i个同学必然属于以下两类中的一类:

1.第i个同学和第i−1个同学坐同一辆车

2.第i个同学和第i−1个同学不坐同一辆车

那么我们来讨论转移的细节。

先看一个最基本的问题,两位到达时间差超过m且到达时间相邻的同学必然不坐同一辆车,因为他们的时间间隔足以让车往返一趟。

那么状态第二维的上限只需要开到2m大小即可,达到上限的情况就是和他同时来的一个同学直接坐车走了,花费m分钟,车回来后再送他,又花费m分钟,在第t[i]+2m分钟时,前i位同学全部到达。

此时,我们利用阶段转移:

1. if(t[i−1]+k==t[i]+j) f[i][j]=min(f[i][j],f[i−1][k]+j)

2. if(t[i−1]+k+m<=t[i]+j) f[i][j]=min(f[i][j],f[i−1][k]+j)
初值:

for(int i=1; i<=m*2; i++) f[1][i]=i;

是第1位同学等待的时间。