(作爲一名已經離開了普及組的退役選手感到萬分慶幸)
題目鏈接:https://www.luogu.org/problemnew/solution/P5017
1.感覺就是一個類似線性的以時間作爲維度的dp,再一看範圍:4*10^6 沒啥大問題。
2.開始思考f[t]的含義:擺渡車在t分鐘離開時所有人最少的等待時間。
3.接着就是轉移:首先比t早出發2*m分鐘之前(浪費啊)的和m分鐘之後的(轉移不了)都可以不考慮
4.最後,枚舉j從i-2*m到i-m的方案加上這一段時間內的轉移,就是我們的答案了。
(5.但是,由於CCF的機器一言難盡,,,所以我們還是考慮一下優化吧。。。如果在i-i-m之間都沒有人的話,那麼i其實可以直接賦值,不用計算了)
over
#include <bits/stdc++.h>
using namespace std;
const int maxn=5000005;
int t[maxn],num[maxn],st[maxn],f[maxn];int T=0;
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);num[t[i]]++;
T=max(T,t[i]);
st[t[i]]+=t[i];
}
for(int i=1;i<=T+m-1;i++)
{
num[i]+=num[i-1];st[i]+=st[i-1];
}
int minv=0x3f3f3f3f;
for(int i=1;i<=T+m-1;i++)
{
if(i>=m&&num[i-m]==num[i]) {f[i]=f[i-m];continue;}//中間沒有點,直接轉移即可
f[i]=num[i]*i-st[i];
for(int j=i-m;j>=max(0,i-2*m);j--)
{
f[i]=min(f[i],f[j]+(num[i]-num[j])*i-(st[i]-st[j]));
}
}
for(int i=T;i<=T+m-1;i++) minv=min(minv,f[i]);
printf("%d",minv);
return 0;
}