好吧,看到这道题的题目就晕了,好长一串。。。
由于找不出来什么特别NB的算法,就上贪心吧。。。
网上看了下各种题解,对于某个车站i,如果汽车的到达i站的时间比最后一个来到第i站的时间要短的话,我们就可以考虑使用加速器了。因此枚举在哪个车站i使用加速器能够使节约的时间最多,每次使用了加速器后,更新一遍汽车到站的时间。一直不停地找最优的车站使用加速器,直到加速器用光或者用不用加速器都一样的时候就退出循环。
此种写法是一个一个地使用加速器,比较慢,但还是能过完所有点。
#include<cstdio> #include<iostream> #define MAXN 1005 using namespace std; int n,m,k; int d[MAXN],down[MAXN],last[MAXN];//到达第i+1站时间,每站下车人数,最后一个到达第i站的人 int t[10005],fr[10005],to[10005];//每个人的到站时间,起始站,终点站 int arrive[MAXN];//汽车到达第i站的时间 int main() { scanf("%d%d%d",&n,&m,&k); for(int i = 1; i < n; i++) scanf("%d",&d[i]); for(int i = 1; i <= m; i++) { scanf("%d%d%d",&t[i],&fr[i],&to[i]); last[fr[i]] = max(last[fr[i]],t[i]);//统计到每个站的最后一个人 down[to[i]]++;//统计每站下车人数 } arrive[1] = last[1]; while(k) { for(int i = 2; i <= n; i++) arrive[i] = max(arrive[i-1],last[i-1]) + d[i-1];//由于k在变化,更新汽车到达第i站的时间 int pos = 0,maxpeople = 0;//使用加速器的站点,该点使用加速器能作用的最大人数 for(int i = 1; i < n; i++)//枚举使用加速器的站点 if(d[i] > 0) { int temp = 0; for(int j = i+1; j <= n; j++) { temp += down[j]; if(arrive[j] <= last[j]) break;//如果汽车到达j点时,还有乘客没有来或者刚来,使用加速器是对后面没有影响的 } if(temp > maxpeople) { maxpeople = temp; pos = i; } } d[pos]--; k--; } for(int i = 2; i <= n; i++)//更新使用了最后一个加速器后的情况 arrive[i] = max(arrive[i-1],last[i-1]) + d[i-1]; int ans = 0; for(int i = 1; i <= m; i++) ans += arrive[to[i]] - t[i]; printf("%d\n",ans); }
这种写法是通过计算得到在最优的车站i使用多少个加速器能达到的最优解,由于是一堆一堆地使用加速器,比起上面那种写法要快得多。
#include<cstdio> #include<iostream> #define MAXN 1005 using namespace std; int n,m,k; int d[MAXN],down[MAXN],last[MAXN];//到达第i+1站时间,每站下车人数,最后一个到达第i站的人 int t[10005],fr[10005],to[10005];//每个人的到站时间,起始站,终点站 int sum[MAXN],arrive[MAXN],r[MAXN];//汽车到达第i站的时间,在第i站用加速器能影响到的最大站 int main() { scanf("%d%d%d",&n,&m,&k); for(int i = 1; i < n; i++) scanf("%d",&d[i]); for(int i = 1; i <= m; i++) { scanf("%d%d%d",&t[i],&fr[i],&to[i]); last[fr[i]] = max(last[fr[i]],t[i]);//统计到每个站的最后一个人 down[to[i]]++;//统计每站下车人数 } for(int i = 2; i <= n; i++) arrive[i] = max(arrive[i-1],last[i-1]) + d[i-1];//统计汽车到站的时间 for(int i = 1; i <= n; i++)//统计在前i站下车的前缀和 sum[i] = sum[i-1] + down[i]; int R = 1; for(int i = 1; i < n; i++)//计算在第i站使用加速器的影响范围 { while((R < n&&last[R] < arrive[R])||R <= i) R++; r[i] = R; } while(k) { int maxpeople = 0,pos = 0,maxtime = 123456789,usek; for(int i = 1; i < n; i++)//找出使用加速器影响最大的人数 if(sum[r[i]] - sum[i] > maxpeople&&d[i] > 0) { maxpeople = sum[r[i]] - sum[i]; pos = i; } if(maxpeople == 0) break;//已经没有能影响的人了,所以再使用加速器也没用 for(int i = pos+1; i < n&&last[i] < arrive[i]; i++)//使用加速器的个数应该不超过 last[i]-arrive[i]的最小值,如果超过了,那么汽车到达i的时间就会晚于最后一个到达i的人,达不到最优解 maxtime = min(maxtime,arrive[i] - last[i]); maxtime = min(maxtime,k);//使用加速器的限制条件 usek = min(maxtime,d[pos]); k -= usek; d[pos] -= usek; for(int i = pos+1; i <= r[pos]; i++)//更新汽车到站的时间 arrive[i] = max(arrive[i-1],last[i-1])+d[i-1]; for(int i = pos,R = pos; i < r[pos]; i++)//更新使用加速器的影响范围 { while((R < n&&last[R] < arrive[R])||R <= i) R++; if(R >= r[i]) break;//影响范围不可能比没用的时候还大 r[i] = R; } } long long ans = 0; for(int i = 1; i <= m; i++) ans += (long long)arrive[to[i]] - t[i]; printf("%lld\n",ans); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-16 20:48:48