蒟蒻感言
这道题真的是普及组的难度?!(自闭怀疑人生orz)
分析
动态规划(真的特别玄学,想不出来只能打爆力了)
先对每个人开始等候的时间从小到达排序,并保存当前时间的人数
F[ I][ J ]表示第i个人等了刚好等了J分钟的时刻,前I个人已经到达B地(/上车),所需要的最少总等候时间。
每个人等待的不会超过m ,即 0<=J<m
第k个人的等待时间是:
Tmp=max( t[i] + j + m - t[k], 0 )
f[k][tmp]=f[i][j]+ 第 (i+1)个学生到第 k 个学生的总等车时间(预处理出来)。
最后的状态转移方程如下:
f[k][tmp]=f[i][j]+(tmp+t[k])×(k-i)?(t[k]-t[i])
代码如下
#include<bits/stdc++.h>
using namespace std;
int t[501],s[501],f[501][101];
int read(){
int sum=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
sum=(sum<<3)+(sum<<1)+ch-'0';
ch=getchar();
}
return sum*f;
}
const int inf=2139062143;
int main()
{
int n=read(),m=read();
for(int i=1;i<=n;i++)
t[i]=read();
sort(t+1,t+n+1);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+t[i];
memset(f,0x7f,sizeof(f));
t[0]=-inf;
f[0][0]=0;
for(int i=0;i<=n;i++)
{
int MAX=min(m-1,t[i+1]-t[i]);
for(int j=0;j<=MAX;j++)
if(f[i][j]!=inf)
for(int k=1;i+k<=n;k++)
{
int tmp=max(t[i]+j+m-t[i+k],0);
f[i+k][tmp]=min(f[i+k][tmp],f[i][j]+(tmp+t[i+k])*k-(s[i+k]-s[i]));
}
}
int ans=inf;
for(int i=0;i<m;i++)
ans=min(ans,f[n][i]);
printf("%d\n",ans);
return 0;
}