算法知识点: 贪心,递推
复杂度:
解题思路:
这道题目的信息较多,我们先将其整理一下。
首先预处理出每个站台的发车时间,即最后一个到达站台i的时间。然后预处理出从每个站台下车的人数。
接下来求出车到达每个站台的时间,那么每个乘客的旅行时间就是,其中是乘客的终点站,是乘客到达起点的时间。
然后考虑每个氮气加速器该用在哪一段,这里使用贪心策略:每次选择当前节约时间最多的一段。(正确性仍未得证)
节约时间取决于能影响多少位乘客,当我们将某一段的行驶时间减一之后,如果下一个车站的,则车从下一个车站发车的时间也会早一个单位时间,依次类推,每次加速之后,可以影响一段连续的区间。
每次选择节约时间最多的一段来加速即可。
时间复杂度分析:
C++ 代码:
#include <iostream> #include <algorithm> using namespace std; const int N = 1010, M = 10010; int n, m, k; int d[N]; int t[M], a[M], b[M]; int tm[N], last[N]; int sum[N]; int reduce[N]; int main() { scanf("%d%d%d", &n, &m, &k); for (int i = 1; i < n; i++) scanf("%d", &d[i]); for (int i = 0; i < m; i++) { scanf("%d%d%d", &t[i], &a[i], &b[i]); last[a[i]] = max(last[a[i]], t[i]); sum[b[i]]++; } for (int i = 1; i <= n; i++) tm[i] = max(tm[i - 1], last[i - 1]) + d[i - 1]; while (k--) { for (int i = n; i >= 2; i--) if (!d[i - 1]) reduce[i - 1] = 0; else { reduce[i - 1] = sum[i]; if (tm[i] > last[i]) reduce[i - 1] += reduce[i]; } int p = 0; for (int i = 1; i < n; i++) if (reduce[p] < reduce[i]) p = i; if (!p) break; d[p]--; for (int i = p + 1; i <= n; i++) tm[i] = max(tm[i - 1], last[i - 1]) + d[i - 1]; } int res = 0; for (int i = 0; i < m; i++) res += tm[b[i]] - t[i]; printf("%d\n", res); return 0; }