風景迷人的小城 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.