版权声明:若希望转载,在评论里直接说明即可,谢谢! https://blog.csdn.net/SSL_ZYC/article/details/84326266
题目大意:
题目链接:https://www.luogu.org/problemnew/show/P5017
有
个人分别在
的时间到达,一辆摆渡车要把这些人送到另外一个地方,摆渡车来回一次要
的时间单位。求把这些人都送到的最短时间。
思路:
肯定可以先把
排序。
我们知道,一个人到达后发车只会有两种情况:
- 摆渡车在他到达之前就到了。此时可以直接发车。
- 摆渡车在他到达后 分钟才到。此时要等 分钟才能发车。
可以先预处理出
,表示第
个人到第
个人做同一辆车的等待时间。那么就有
那么我们就设
表示在
个人到达后发车,第
个人等了
分钟时的最小等待时间。
那么肯定要枚举
,表示前
个人已经送到了目的地。
那么如果第
个人到达时,摆渡车已经回来了,那么就可以直接发车(即第
个人的等待时间为
)。此时就有
其中
表示枚举的第
个人等待的时间。
那么如果第
个人到达后摆渡车没有回来,那么第
个人等待的时间就是
其中
是摆渡车回到的时间。
那么就有
答案就是
时间复杂度
,足够过掉本题。
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=510;
const int M=210;
const int Inf=2e9;
int n,m,ans,w,t[N],f[N][M],s[N][N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&t[i]);
sort(t+1,t+1+n);
for (int j=1;j<=n;j++)
for (int i=1;i<j;i++)
for (int k=i;k<j;k++)
s[i][j]+=t[j]-t[k];
memset(f,0x3f3f3f3f,sizeof(f));
t[0]=-Inf;
for (int i=0;i<=m;i++) //初始化
{
f[0][i]=0;
f[1][i]=i;
}
for (int i=2;i<=n;i++)
for (int j=0;j<i;j++)
for (int k=0;k<=m;k++)
{
w=t[j]+k+m-t[i];
if (w>0)
f[i][w]=min(f[i][w],f[j][k]+s[j+1][i]+(i-j)*w);
else
f[i][0]=min(f[i][0],f[j][k]+s[j+1][i]);
}
ans=Inf;
for (int i=0;i<=m;i++)
ans=min(ans,f[n][i]);
printf("%d\n",ans);
return 0;
}