题目描述
风景迷人的小城Y 市,拥有n 个美丽的景点。由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务。观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2、3 、4 ……n 号景点。从第 i 号景点开到第 i+1 号景点需要 Di 分钟。任意时刻,公交车只能往前开,或在景点处等待。
设共有m 个游客,每位游客需要乘车1 次从一个景点到达另一个景点,第i 位游客在Ti 分钟来到景点 Ai ,希望乘车前往景点Bi (Ai< Bi )。为了使所有乘客都能顺利到达目的地,公交车在每站都必须等待需要从该景点出发的所有乘客都上车后才能出发开往下一景点。假设乘客上下车不需要时间。一个乘客的旅行时间,等于他到达目的地的时刻减去他来到出发地的时刻。因为只有一辆观光车,有时候还要停下来等其他乘客,乘客们纷纷抱怨旅行时间太长了。于是聪明的司机ZZ给公交车安装了 k 个氮气加速器,每使用一个加速器,可以使其中一个 Di 减1 。对于同一个Di 可以重复使用加速器,但是必须保证使用后Di 大于等于0 。
那么ZZ该如何安排使用加速器,才能使所有乘客的旅行时间总和最小?
【题目分析】
贪心。
【代码】
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int t[10001],a[10001],b[10001];
int arr[1001],lst[1001],sum[1001],d[1001];
int next[1001],n,m,k,ans;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<n;++i) scanf("%d",&d[i]);
for (int i=1;i<=m;++i)
{
scanf("%d%d%d",&t[i],&a[i],&b[i]);
lst[a[i]]=max(lst[a[i]],t[i]);
sum[b[i]]++;
}
for (int i=2;i<=n;++i) sum[i]+=sum[i-1];
while (true)
{
arr[1]=0;
for (int i=2;i<=n;++i)
arr[i]=max(arr[i-1],lst[i-1])+d[i-1];
next[n]=n;
for (int i=n-1;i>=1;--i)
{
next[i]=next[i+1];
if (arr[i+1]<=lst[i+1]) next[i]=i+1;
}
int st=1;
while (!d[st]&&st<n) st++;
if (st==n) break;
if (k==0) break;
for (int i=st+1;i<n;++i)
if (d[i]&&sum[next[st]]-sum[st]<sum[next[i]]-sum[i]) st=i;
if (sum[next[st]]-sum[st]==0) break;
int tmp=0x3f3f3f3f;
for (int i=st+1;i<next[st];++i) tmp=min(tmp,arr[i]-lst[i]);
tmp=min(tmp,k);
tmp=min(tmp,d[st]);
k-=tmp;
d[st]-=tmp;
}
for (int i=1;i<=m;++i)
ans+=arr[b[i]]-t[i];
printf("%d\n",ans);
}