1 条题解
-
0
C++ :
#include <bits/stdc++.h> using namespace std; //t数组:存储第i个同学到达人大附中车站的时间 /* 1.最后一班车的发车时间lt,lt>=t[n]才能保证最后一个人能乘到车 如果lt >= t[n] + m,那么完全可以在lt-x*m时间点发最后一班车 2.倒数第二班车最早发车时间:(lt-2*m,lt-m] d[i]=min(d[j],wait(j,i)) wait(j,i):在j和i之间到达的人,乘坐第i分钟发出的车,所需的等待时间; j=(i-2m,i-m] 最终结果:ans = min(d[i]); i=[t[n],t[n]+m) */ const int N = 505,M = 105,T=4*1e6+10,INF=0x3FFFFFF; int n,m,ans=INF,t[N],c[N],d[T],wt[T],num[T],sum[T]; /* d[i]:最后一班车在i分钟发车,最小总等待时间 d[i]=min(d[j]+wait(j+1,i));j是上一班车的发车时间,j=(i-2m,i-m] wait(j,i):在j和i之间到达的人,搭乘i分钟出发的车所需要的的等待时间; ans=min(d[i]); i=[t[n],t[n]+m) */ int main(){ cin>>n>>m; for(int i = 1;i <= n;i++){ cin>>t[i]; } sort(t+1,t+n+1); /* 优化:如果t[i]-t[i-1]>2*m,t[i]=t[i-1]+2*m 如果t[1]到t[n]同时增加某个固定值x,并不影响最终结果。 (每个人的到达时间都往后移动) 为计算方便,可以将t[1]修改为2*m */ //差值数组 for(int i = 1;i <= n;i++) c[i] = t[i] - t[i-1]; t[1] = 2*m;//上面j的循环就不需要特判了 num[t[1]] = 1; for(int i=2;i<=n;i++){ if(c[i] > 2 * m) c[i] = 2 * m;//超过2*m等待时间不变,载第i个人的。 t[i] = t[i-1] + c[i]; num[t[i]]++; } /* 利用前缀和优化wait(j,i)将复杂度才能从O(n)改为O(1) 1.定义wt[T],wt[i]表示在时间点i之前达到的所有人,乘坐i分钟出发的车,总的等待时间 2.定义数组sum[i]表示在时间点i之前到达的人数。 wait(j,i) = wt[i] - wt[j] - sum[j] * (i - j) num[i]记录在时间点i到达的人数。 */ for(int i = t[1];i < t[n] + m;i++){ wt[i] = wt[i-1] + sum[i-1];//sum[i-1]个人每个人多等了一分钟; sum[i] = sum[i-1] + num[i]; //加上t[i]的竖向 d[i] = wt[i]; } for(int i = t[1];i < t[n] + m;i++){ for(int j = i-2*m+1;j<=i-m;j++){ d[i] = min(d[i],d[j]+wt[i]-wt[j]-sum[j]*(i-j)); } } for(int i = t[n];i < t[n] + m;i++){ ans = min(ans,d[i]); } cout<<ans; return 0; }
- 1
信息
- ID
- 908
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者