NOIP2011.day2.觀光公交 題解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1005,maxm=10005;
int n,m,k,ans;
int d[maxn],bt[maxm],e[maxm],v[maxn],last[maxn]={0},t[maxn]={0},reduce[maxn]={0};
void work(int p)
{
for (int i=p;i<n;i++)
t[i]=max(last[i],t[i-1])+d[i];
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<n;i++)
scanf("%d",&d[i]);
int tmp,x,y;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&tmp,&x,&y);
bt[i]=tmp;
e[i]=y;
v[y]++;
last[x]=max(last[x],tmp);
}
t[0]=last[1];
work(1);
ans=0;
for (int i=1;i<=m;i++)
ans+=t[e[i]-1]-bt[i];
for (int i=1;i<=k;i++)
{
int maxt=0,p=-1;
for (int j=n-1;j>=1;j--)
{
if (t[j]>last[j+1])
reduce[j]=reduce[j+1]+v[j+1];
else
reduce[j]=v[j+1];
if ((reduce[j]>maxt)&&(d[j]>0))
{
maxt=reduce[j];
p=j;
}
}
if (p==-1) break;
if (ans>maxt)
{
d[p]--;ans-=maxt;
}
else
{
ans=0;break;
}
work(p);
}
printf("%d\n",ans);
}
(bus.cpp/c/pas)
【問題描述】
風景迷人的小城 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 該如何安排使用加速器,才能使所有乘客的旅行時間總和最小?
【輸入】
輸入檔名為 bus.in。 第 1 行是 3 個整數 n, m, k,每兩個整數之間用一個空格隔開。分別表示景點數、乘客數 和氮氣加速器個數。
第 2 行是 n-1 個整數,每兩個整數之間用一個空格隔開,第 i 個數表示從第 i 個景點開 往第 i+1 個景點所需要的時間,即 Di。
第 3 行至 m+2 行每行 3 個整數 Ti, Ai, Bi,每兩個整數之間用一個空格隔開。第 i+2 行表 示第 i 位乘客來到出發景點的時刻,出發的景點編號和到達的景點編號。
【輸出】
輸出檔名為 bus.out。共一行,包含一個整數,表示最小的總旅行時間。
【輸入輸出樣例】
bus.in bus.out 3 3 2 1 4 0 1 3 1 1 2 5 2 3
10
【輸入輸出樣例說明】
對 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
【解題思路】
滿足最優子結構性質,考慮貪心。每次選一條能減少的時間最多的路修改,直到不能修改為止。
具體做法:
由於每個人到站的時間是確定的,所以影響總時間的只是某人到達終點站的時間。
用t[i]記錄車到達第i+1站的時間,則有t[i]=max(t[i-1],last[i])+d[i]。
其中d[i]表示從i站出發到i+1站的時間,last[i]表示以i站為出發點的人中最後一個到達的時間,所以t可在O(n)內處理出來。
現在假設我們修改了d[p]的值,則t[1..p-1]不會變化,t[p]-1,考慮t[p+1]的值。
因為t [p+1] = max (t [p] , last [p+1] ) + d [p+1],所以若修改後t[p]>=last[p+1],則t[p+1]-1;即修改前t[p]>last[p+1],則t[p+1]會因t[p]的修改而修改。如果修改前t[p]<=last[p+1],則t[p+1]沒有修改,則t[p+1..n]不變。
以此類推,當修改d[p]的知識,在以i開始的某一段區間內 t 值-1;
設這個區間的左端點為p,其右端點為r[p],則對於i屬於[ p , r [ p ]),有t[i]>last[i+1],且t [ r [ p ] ] <= last [ r [ p ] + 1 ]。
易得到 r 的求解方法:
若t [i] >= last [i+1] ,則r[i] = r[i+1] +visit[i+1];否則 r[i] = visit [i+1]。
設修改d[i]是=時減少的時間為reduce[i],則有reduce[i] =v[i+1] + v[i+2] +...+v[r[i]+1],其中v[i]表示以i為終點站的人數。
顯然有reduce[i]=v[i+1]或v[i+1]+reduce[i+1].
每一次修改後要重新計算t的值。
時間複雜度為O(kn)
【AC程式碼】
相關文章
- 矽谷觀光指南
- 公交wifi隱患多,安全問題堪憂WiFi
- 公交車站
- JAVA實現附近範圍內公交定位問題Java
- 智慧公交監控系統瞭解一下
- [省選聯考 2024] 重塑時光 題解
- 雲閃付刷公交教程 雲閃付怎麼坐公交?
- 城市公交查詢-Api介面API
- 5G智慧物聯之智慧公交監控解決方案
- 刷蘋果iPhone公交卡之前,你必須瞭解的12件事蘋果iPhone
- LLM面面觀之LLM復讀機問題及解決方案
- 馬斯克新視訊:Boring公司將優先解決公交快速通勤馬斯克
- MySQL 悲觀鎖與樂觀鎖的詳解MySql
- iOS 極光推送遇到的問題iOS
- [Python手撕]公交路線Python
- 1120 公交換乘
- 擴充套件前作世界觀:《沙石鎮時光》開發團隊專訪套件
- 光之盟:從ONA的握手,解鎖全光網產業未來產業
- 燈光不應是單純的照明解決方案,而是有美學意圖的主觀設計行為
- 微信一分錢刷公交設定方法 微信一分錢刷公交在哪開通?
- [SceneKit專題]8-Lights燈光
- 資料 結構客觀題複習題集
- 韓國文化體育觀光部:2019韓國遊戲產業白皮書遊戲產業
- 依舊樂觀的李彥宏,十年尋光的百度AIAI
- 雷觀(二十五):定義和分析問題,往往比解決具體問題更重要
- 光纜在施工中注意點問題解析
- 悲觀鎖與樂觀鎖的實現(詳情圖解)圖解
- 【Flutter 專題】63 圖解 Flutter 整合極光 JPush 小結|8月更文挑戰Flutter圖解
- 基於圓柱體鏡子和光線跟蹤實現鏡反射觀測全景觀圖的matlab模擬模擬反射Matlab
- Apple Pay交通卡常見問題彙總解答 iPhone如何開通公交卡?APPiPhone
- 經典問題之樂觀鎖和悲觀鎖及使用場景
- 常見的光纖故障及其解決方案
- 聯想天津光纖被挖斷問題已解決,佈置了異地伺服器伺服器
- 不一樣的海信!《海信智慧公交擁擠度檢測解決方案》獲大獎
- 408路公交上的程式設計師程式設計師
- 利用python爬取城市公交站點Python
- iOS —— 極光推送和極光IMiOS
- 北京實時公交查詢——Flutter 入坑實戰Flutter