【NOIP2018】【洛谷P5017】擺渡車【DP】
阿新 • • 發佈:2018-11-22
題目大意:
題目連結: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;
}