描述
有n名同学要乘坐摆渡车从人大附中前往人民大学,第i位同学在第ti分钟去等车。只有一辆摆渡车在工作,但摆渡车容量可以视为无限大。摆渡车从人大附中出发、把车上的同学送到人民大学、再回到人大附中(去接其他同学),这样往返一趟总共花费m分钟(同学上下车时间忽略不计)。摆渡车要将所有同学都送到人民大学。 凯凯很好奇,如果他能任意安排摆渡车出发的时间,那么这些同学的等车时间之和最小为多少呢? 注意:摆渡车回到人大附中后可以即刻出发。
输入
第一行包含两个正整数n,m,以一个空格分开,分别代表等车人数和摆渡车往返一趟的时间。 第二行包含n个正整数,相邻两数之间以一个空格分隔,第i个非负整数ti代表第i个同学到达车站的时刻。
输出
输出一行,一个整数,表示所有同学等车时间之和的最小值(单位:分钟)。
范围
对于 10 % 10\% 10%的数据 , n ≤ 10 , m = 1 , 0 ≤ t i ≤ 100 。 ,n≤10,m=1,0≤ti≤100。 ,n≤10,m=1,0≤ti≤100。
对于 30 % 30\% 30%的数据 , n ≤ 20 , m ≤ 2 , 0 ≤ t i ≤ 100 。 ,n≤20,m≤2,0≤ti≤100。 ,n≤20,m≤2,0≤ti≤100。
对于 50 % 50\% 50%的数据 , n ≤ 500 , m ≤ 100 , 0 ≤ t i ≤ 1 0 4 。 ,n≤500,m≤100,0≤ti≤10^4。 ,n≤500,m≤100,0≤ti≤104。
另有 20 % 20\% 20%的数据 , n ≤ 500 , m ≤ 10 , 0 ≤ t i ≤ 4 × 1 0 6 。 ,n≤500,m≤10,0≤ti≤4×10^6。 ,n≤500,m≤10,0≤ti≤4×106。
对于 100 % 100\% 100%的数据 , n ≤ 500 , m ≤ 100 , 0 ≤ t i ≤ 4 × 1 0 6 ,n≤500,m≤100,0≤ti≤4×10^6 ,n≤500,m≤100,0≤ti≤4×106
样例
【样例输入1】
5 1
3 4 4 3 5
【样例输出1】
0
【样例输入2】
5 5
11 13 1 5 5
【样例输出2】
4
都看的出来是DP吧。
关键就是怎么定义状态,当时我在考场推了很久,直接放弃,随手打了一个暴力,15分(真炸了)
可以知道的是,时间在本题中是一个比较重要的变量,所以我们DP中的一维就要用到时间,那到底是什么时间?是车的时间还是人的时间?其实都可以,但我觉得以人的时间可能会复杂一点点,因为我觉得如果车一一的遍历人,还不如人等车,一下就把所有人就都转移了
我定义的就是这般车开走的时间(因为即来即走,所以你说车回来的时间也可以),当前第 i i i个人,其实就意味着前 i − 1 i-1 i−1个人已经处理了。那么对于车开走的时间,有的人小于等于这个时间,那么就需要等车;而有的人的时间大于这个时间,那么车就需要等人。
那么如何计算出等待的时间呢
注意人等车和车等人的概念不要混淆了,
人等车指车还没来
车等人指车已经来了,在等人
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
int n, m;
int dp[505][505], a[505];
inline int calc(int i, int time_point){
if( i == n+1 )
return 0;
if( a[i] > time_point )//如果等车的人,直接跳往下一个人来的时间
return calc(i, a[i]);
if( dp[i][time_point-a[i]] )//记忆化
return dp[i][time_point-a[i]];
int sum = 0;
int j = i;
while( j <= n && a[j] <= time_point )//人等车
sum += a[j++];
int m_in = time_point*(j-i)-sum+calc(j, time_point+m);
while( j <= n ){//车等人
sum += a[j];
m_in = min(m_in, a[j]*(j-i+1)-sum+calc(j+1, a[j]+m));
j++;
}
return dp[i][time_point-a[i]] = m_in;
}
int main(){
freopen("bus.in","r",stdin);
freopen("bus.out","w",stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
}
sort(a+1, a+1+n);//排序
printf("%d\n", calc(1, 0) );
return 0;
}