NOIp2018普及组-摆渡车

(作为一名已经离开了普及组的退役选手感到万分庆幸)

题目链接: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 

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;
 } 

 

你可能感兴趣的:(dp)