1. 程式人生 > 實用技巧 >P1315 觀光公交(貪心)

P1315 觀光公交(貪心)

題目描述

N個車站,M個人,每個人有一個起始車站,一個結束車站,一個到達起始車站的時間。第i個車站到下一個車站的距離為di,有k個加速器,每個可以使任意兩個相鄰車站的距離減小1。問該如何安排使用加速器,才能使所有乘客的旅行時間總和最小?

思路

每個車站最先到達的人一定要等到最後一個到達的人到達才能出發,所以這段時間沒法優化。預處理出每個車站的資訊,然後k次查詢優化後貢獻最大的方案,進行優化,維護該區間後車站的資訊。

可以優化的東西有:每個車站乘客的上車時間(人不用等車為最優)、每個乘客到達目標車站的時間(儘可能用時短)

#include <cstdio>
#include <cstring>
#include 
<cmath> #include <algorithm> #include <iostream> #include <queue> #include <vector> #include <map> #include <cstdlib> #include <ctime> using namespace std; #define ll long long #define ull unsigned long long #define ld long double #define lowbit(x) ((x) & (-x)) #define
For(x, i, j) for (ll x = (i); x <= (j); x++) #define FOR(x, i, j) for (ll x = (i); x >= (j); x--) #define ls(o) (o << 1) #define rs(o) (o << 1 | 1) #define debug(x) cout << "debug : " << x << endl; inline ll read(){ ll s=0,w=1; char ch=getchar(); while(ch<'
0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w; } #define N 1005 #define M 10005 #define K 100005 ll n, m, k, ans; ll d[N]; struct ps { ll st, ed; //st:這個乘客開始等車的時刻 //ed:這個乘客最終要到達的車站 } p[K]; struct station { ll arrive, latest, off; //arrive:車到該站的時刻 //latest:在該站上車的人中,最晚上車的人的上車時刻 //off:在該站下車的人數 } s[N]; int main() { n = read(), m = read(), k = read(); For(i, 1, n - 1) d[i] = read(); For(i, 1, m) {ll t; p[i].st = read(); t = read(); p[i].ed = read(); s[t].latest = max(s[t].latest, p[i].st); s[p[i].ed].off++; } ll time = 0;//時鐘 For(i, 1, n) { s[i].arrive = time; time = max(time, s[i].latest);//取max的原因:可能是人等車,也可能是車等人 time += d[i]; } ll max_num, max_pos, tmp_num; while (k--) { max_num = 0; For(i, 2, n) {//每次找一個優化後ans減少最大的區間 if (!d[i - 1]) continue;//這段路已經優化光了 tmp_num = 0; For(j, i, n) { tmp_num += s[j].off; if (s[j].arrive <= s[j].latest) break;//已經優化到需要車等人了 } if (tmp_num > max_num) { max_num = tmp_num; max_pos = i; } } d[max_pos - 1]--; For(i, max_pos, n) { s[i].arrive--; if (s[i].arrive < s[i].latest) break; } } For(i, 1, m) {ans += s[p[i].ed].arrive - p[i].st;} printf("%lld\n", ans); return 0; }