noip2011 观光公交 (贪心)

P1741观光公交

描述

风景迷人的小城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该如何安排使用加速器,才能使所有乘客的旅行时间总和最小?

格式

输入格式

第1行是3个整数n, m, k,每两个整数之间用一个空格隔开。分别表示景点数、乘客数和氮气加速器个数。

第2行是n-1个整数,每两个整数之间用一个空格隔开,第i个数表示从第i个景点开往第i+1个景点所需要的时间,即Di。

第3行至m+2行每行3个整数Ti, Ai, Bi,每两个整数之间用一个空格隔开。第i+2行表示第i位乘客来到出发景点的时刻,出发的景点编号和到达的景点编号。

输出格式

共一行,包含一个整数,表示最小的总旅行时间。

样例1

样例输入1[复制]

3 3 2
1 4
0 1 3
1 1 2
5 2 3

样例输出1[复制]

10

限制

1s

提示

样例说明:

对D2使用2个加速器,从2号景点到3号景点时间变为2分钟。

公交车在第1分钟从1号景点出发,第2分钟到达2号景点,第5分钟从2号景点出发,第7分钟到达3号景点。

第1个旅客旅行时间7 - 0 = 7分钟;
第2个旅客旅行时间2 - 1 = 1分钟;
第3个旅客旅行时间7 - 5 = 2分钟。

总时间7 + 1 + 2 = 10分钟。

数据范围:

对于10%的数据,k = 0;
对于20%的数据,k = 1;
对于40%的数据,2 ≤ n ≤ 50,1 ≤ m ≤ 1,000,0 ≤ k ≤ 20,0 ≤ Di ≤ 10,0 ≤ Ti ≤ 500;
对于60%的数据,1 ≤ n ≤ 100,1 ≤ m ≤ 1,000,0 ≤ k ≤ 100,0 ≤ Di ≤ 100,0 ≤ Ti ≤ 10,000;
对于100%的数据,1 ≤ n ≤ 1,000,1 ≤ m ≤ 10,000,0 ≤ k ≤ 100,000,0 ≤ Di ≤ 100,0 ≤ Ti ≤ 100,000。

来源

NOIp2011提高组Day2第三题

代码:

#include<cstdio>
#include<algorithm>
#define maxn 1000
#define maxm 10000
using namespace std;

int n,m,k,d[maxn+20];
int t[maxm+20],a[maxm+20],b[maxm+20];
int people[maxn+20],go[maxn+20],arrive[maxn+20];

int main()
{
  int i,j,x,y,z,ans=0;
  scanf("%d%d%d",&n,&m,&k);
  for(i=1;i<n;i++)scanf("%d",&d[i]);
  for(i=1;i<=m;i++)
    {
      scanf("%d%d%d",&t[i],&a[i],&b[i]);
      people[b[i]-1]++;
      go[a[i]]=max(go[a[i]],t[i]);
    }
  for(i=2;i<=n;i++)
    arrive[i]=max(go[i-1],arrive[i-1])+d[i-1];
  while(k--)
    {
      x=y=z=0;
      for(j=n;j>1;j--)
        {
          if(arrive[j]<=go[j])z=0;
          z+=people[j-1];
          if(d[j-1]>0 && z>x)x=z,y=j-1;
        }
      if(y==0)break;
	  d[y]--;
	  for(i=y+1;i<=n;i++)
	    arrive[i]=max(arrive[i-1],go[i-1])+d[i-1];  
    } 
  for(i=1;i<=m;i++)
    ans+=arrive[b[i]]-t[i];
  printf("%d\n",ans);	 		  
  return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值