观光公交(codevs 1139)题解

【问题描述】

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

【样例输入】

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

【样例输出】

    10

【解题思路】

     本题为NOIP2011提高组day2第三题,其实这道题虽然被放在第三题但它仅仅只需要一个贪心就好,我们首先记录下来到每一站下车的人数,然后枚举每一个加速器,由于每个乘客的旅行时间只与他到达的时间与下车的时间有关,因此,我们在枚举每一个加速器的时候,只需要把能够造福最多人的那一段路加速即可,于是我们可以记录每一段路所造福的人数,我们暂定每个景点的出发时间为需要从该景点上车的最晚到达的乘客,那么到达时间即为上一个景点的出发时间或到达时间更大的一个值加上从上一个景点到该景点所需要的时间。如果某个景点的出发时间小于到达时间,那么说明若在这段旅程中使用加速器,能够造福到下一个景点下车的人。通过这个,我们就可以贪心了,然后每次贪心完之后都更新到达景点的时间即可。为了方便计算,我在初始化的时候把所有人的到达景点的时间都减去,这样就不用最后再减了,就可以直接求需要在每个景点下车的人数*到达该景点的时间的和就行了。

【代码实现】

 1 uses math;
 2 var n,m,k,i,j,a,b,c,cct,ans,max1:longint;
 3     time,last,d,data,num:array[0..2000] of longint;
 4 begin
 5  readln(n,m,k);
 6  for i:=2 to n do
 7   read(d[i]);
 8  for i:=1 to m do
 9   begin
10    readln(a,b,c);
11    ans:=ans-a;
12    inc(num[c]);
13    last[b]:=max(last[b],a);
14   end;
15  for i:=2 to n do
16   time[i]:=max(time[i-1],last[i-1])+d[i];
17  for i:=1 to k do
18   begin
19    for j:=n downto 2 do
20     begin
21      data[j]:=num[j];
22      if last[j]<time[j] then
23       data[j]:=data[j]+data[j+1];
24     end;
25    max1:=0;
26    for j:=2 to n do
27     if (data[j]>max1)and(d[j]>0) then
28      begin
29       max1:=data[j];
30       cct:=j;
31      end;
32    dec(d[cct]);
33    for j:=cct to n do
34     time[j]:=max(time[j-1],last[j-1])+d[j];
35   end;
36  for i:=2 to n do
37   ans:=ans+num[i]*time[i];
38  writeln(ans);
39 end.

 

你可能感兴趣的:(观光公交(codevs 1139)题解)