题解——Noip2018普及组3摆渡车

题目在这里

感谢Green_Hand的题解让我这个25分的蒟蒻终于懂得了这一题

首先算法是dp,是个人都想的出来
f[i][j]表示第i个人等待时间为j的时候前i个人的最小等待时间(太强了)‘

j的取值范围?

由题可知,若车在人大附中停了m分钟,那么不如在到人大附中时先送走一批人(即便当时没人),所以停车时间T1

设一个人等到车从人民大学回来的时间为T2
因为车往返一次只需m分钟,所以T2

综上,一个人等车的时间

j=T1+T2<2m

该如何转移?

若下一个人能赶上当次车(即t[i]+j>=t[i+1]), 则将f[i][j]+t[i]+j-t[i+1]转移至f[i+1][t[i]+j-t[i+1]];
题解——Noip2018普及组3摆渡车_第1张图片

若下一个人在当次车回来之前开始等车(即t[i]+j+m>=t[i+1]), 则枚举车回来后停的时间k, 用f[i][j]+t[i]+j+m+k-t[i+1]转移f[i+1][t[i]+j+m+k-t[i+1]];
题解——Noip2018普及组3摆渡车_第2张图片

若下一个人在当次车回来之后才到(即t[i]+j+m 题解——Noip2018普及组3摆渡车_第3张图片

时间复杂度O(nm2),正确性显然

#include
using namespace std;
int inf=0x3f3f3f3f;
int n,m,ans=inf;
int t[550],f[550][550];
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		scanf("%d",&t[i]);	
	sort(t+1,t+1+n);

	for(int j=0;j<2*m;j++)
		f[1][j]=j;
	for(int i=2;i<=n;i++)
		for(int j=0;j<2*m;j++)
			f[i][j]=inf;
				
	for(int i=1;i=t[i+1])   //第i+1个人跟i同一辆车 
					f[i+1][lt-t[i+1]]=min(f[i+1][lt-t[i+1]],f[i][j]+lt-t[i+1]);
				
				if(bt>=t[i+1])
					for(int k=0;bt+k-t[i+1]<2*m;k++)
						f[i+1][bt+k-t[i+1]]=min(f[i+1][bt+k-t[i+1]],f[i][j]+bt+k-t[i+1]); 
		
				if(bt

你可能感兴趣的:(题解——Noip2018普及组3摆渡车)