观光公交
观光公交
观光公交
观光公交
贪心做法:
如果要贪心的话肯定是从影响人数最多的路径入手,在其中某个路径使用加速器的话一定对后面的路径都有影响吗?
我们可以分类讨论一下:
1.如果加速之后,下一个点还是需要等待,那么对以后将不会有影响。
2.如果加速之后不需要等待了,那么对以后的时间一直加到1或者最后一个点为止。
用数组sum[i]表示到i点的人数,g[i]表示i这个点所能影响到的最远点。
那么sum[i+g[i]]-sum[i]就为能影响到的人数。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=30001;
int n,m,k;
int dis[maxn],last[maxn],g[maxn],enter[maxn];//sum,g,都说过了,enter表示公交车到i点的最短时间,last表示最后一人到i点的时间。dis表示两点间的距离。
int ans,sum[maxn],maxx=-1;
struct node
{
	int time,start,end;
}a[maxn];//存边的信息。
inline void bus(int x)
{
	while(x)
	{
		x--;
		g[n]=g[n-1]=n;
		int tar;
		maxx=-1;
		for(int i=n-2;i>=1;i--)
		{
			if(enter[i+1]<=last[i+1]) g[i]=i+1;
			else g[i]=g[i+1];
		}
		for(int i=1;i<n;i++)
		{
			int tmp=sum[g[i]]-sum[i];
			if(tmp>maxx&&dis[i]>0)
			{
				maxx=tmp;tar=i;
			}
		}
		ans-=maxx;
		dis[tar]--;
		for(int i=2;i<=n;i++)
			enter[i]=max(enter[i-1],last[i-1])+dis[i-1];
	}
} 
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<n;i++)
	 scanf("%d",&dis[i]);
	for(int i=1;i<=m;i++)
	 scanf("%d%d%d",&a[i].time,&a[i].start,&a[i].end);
	for(int i=1;i<=m;i++)
	{
		last[a[i].start]=max(last[a[i].start],a[i].time);
		sum[a[i].end]++;
	}
	enter[1]=last[1];
	for(int i=1;i<=n;i++)
	 sum[i]+=sum[i-1];
	for(int i=2;i<=n;i++)
	enter[i]=max(enter[i-1],last[i-1])+dis[i-1];
	for(int i=1;i<=m;i++)
	 ans+=enter[a[i].end]-a[i].time;
	bus(k);
	printf("%d\n",ans);
	return 0;
}

相关文章: