【NOIP2011】观光公交

Description

风景迷人的小城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 该如何安排使用加速器,才能使所有乘客的旅行时间总和最小?

Input

第1 行是3 个整数n, m, k,每两个整数之间用一个空格隔开。分别表示景点数、乘客数和氮气加速器个数。 
第2 行是n-1 个整数,每两个整数之间用一个空格隔开,第i 个数表示从第i 个景点开往第i+1 个景点所需要的时间,即Di。 
第3 行至m+2 行每行3 个整数Ti, Ai, Bi,每两个整数之间用一个空格隔开。第i+2 行表示第i 位乘客来到出发景点的时刻,出发的景点编号和到达的景点编号。

Output

共一行,包含一个整数,表示最小的总旅行时间。

Sample Input

3 3 2 
1 4 
0 1 3 
1 1 2 
5 2 3

Sample Output

10

Hint

对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%的数据,0≤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。

题解:

贪心真的难想,自己写的时候只差最后一步就写出来了,只要把最后答案的表达式拆开就不难发现对答案真正有贡献的是减少边权之后影响的人数与减少的量之积,所以我们对于每条边只要求出他最多能影响到哪些站点,然后乘以对应站的人数就是他最后能影响的人数,因为我们每次只加速一次,所以相当于乘以1,就以这个作为贪心,然后最多影响到哪个站点可以递推求出。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
const int MAXN=300000;
using namespace std;
int cost[MAXN],last[MAXN],timee[MAXN],sum[MAXN],g[MAXN];
struct people{
    int t;
    int from;
    int to;
}a[MAXN];
int n,m,k,ans=0;

void cl(){
    memset(cost,0,sizeof(cost));
    memset(last,0,sizeof(last));
    memset(timee,0,sizeof(timee));
    memset(sum,0,sizeof(sum));
    memset(g,0,sizeof(g));
}

int main(){
    cl();
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<n;i++) scanf("%d",&cost[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a[i].t,&a[i].from,&a[i].to);
        last[a[i].from]=max(last[a[i].from],a[i].t);
        sum[a[i].to]++;
    }
    for(int i=2;i<=n;i++) sum[i]+=sum[i-1];
    timee[1]=0;
    for(int i=2;i<=n;i++){
        timee[i]=max(timee[i-1],last[i-1])+cost[i-1];
    }
    for(int i=1;i<=m;i++)
    ans+=timee[a[i].to]-a[i].t;
    while(k){
        g[n]=g[n-1]=n;
        for(int i=n-2;i;i--){
            if(timee[i+1]<=last[i+1]) g[i]=i+1;
            else g[i]=g[i+1];
        }
        int maxx=0,id=0;
        for(int i=1;i<=n;i++)
        if(sum[g[i]]-sum[i]>maxx&&cost[i]>0)
        maxx=sum[g[i]]-sum[i],id=i;
        if(!maxx) break;
        k--;
        ans-=maxx;
        cost[id]--;
        timee[1]=0;
        for(int i=2;i<=n;i++){
            timee[i]=max(timee[i-1],last[i-1])+cost[i-1];
        }
    }
    printf("%d\n",ans);
}

代码:

时间: 2024-11-21 01:16:17

【NOIP2011】观光公交的相关文章

[NOIP2011]观光公交 题解

题目大意: 就省了吧 思路: 应该算是贪心. 不难发现,加速只对所有在使用加速器之后连续的一段下车时不用等人的站点下车的人有用.这非常重要. 先算出不加速时的和,并预处理出每个站点最迟到的人的时间.每个站下车的人数.然后一个一个放加速器,加速器放在惠及最多的人的一段,同时维护到每个站点的时间(判断用不用等人). 代码: 1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int M=10000

NOIP2011 观光公交(贪心)

好吧,看到这道题的题目就晕了,好长一串... 由于找不出来什么特别NB的算法,就上贪心吧... 网上看了下各种题解,对于某个车站i,如果汽车的到达i站的时间比最后一个来到第i站的时间要短的话,我们就可以考虑使用加速器了.因此枚举在哪个车站i使用加速器能够使节约的时间最多,每次使用了加速器后,更新一遍汽车到站的时间.一直不停地找最优的车站使用加速器,直到加速器用光或者用不用加速器都一样的时候就退出循环. 此种写法是一个一个地使用加速器,比较慢,但还是能过完所有点. #include<cstdio>

vijos1741 观光公交 (贪心)

https://www.vijos.org/p/1741 P1741观光公交 请登录后递交 标签:NOIP提高组2011[显示标签] 描述 风景迷人的小城Y市,拥有n个美丽的景点.由于慕名而来的游客越来越多,Y市特意安 排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0分钟出现在1号景点,随后依次前往2.3.4……n号景点.从第i号景点开到第i+1 号景点需要Di分钟.任意时刻,公交车只能往前开,或在景点处等待. 设共有m个游客,每位游客需要乘车1次从一个景点到达另一个景点,第i位

noip 2011观光公交

P1315 观光公交 95通过 244提交 题目提供者该用户不存在 标签贪心递推2011NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2.3 .4 ……n 号景点.从第 i 号景点开到第 i+1 号景点需要 Di 分钟.任意时刻,公交车只能往前开,或在景点处等待. 设共有m 个游客,

P1315 观光公交 贪心

  P1315 观光公交 贪心 题目链接:https://www.luogu.org/problemnew/show/1315 哇,这个题贪心?好高级的贪心……完全没看出来QAQ 看到这个题, 刚开始想能不能dp, 然后某大神说不满足无后效性, 首先对于每个点当然是能走就走, 不能走就等待,这是无法控制的. 所以只考虑氮气加速器加在哪里可以使时间总和尽量少. 后效性: 如果选择加速,可能会使后面等待的时间更长,或者更短,对后面都会有影响. 虽然dp不行,但是可以受启发,着这一条边加速会影响后面的

[NOIP2011] 提高组 洛谷P1315 观光公交

题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2.3 .4 ……n 号景点.从第 i 号景点开到第 i+1 号景点需要 Di 分钟.任意时刻,公交车只能往前开,或在景点处等待. 设共有m 个游客,每位游客需要乘车1 次从一个景点到达另一个景点,第i 位游客在Ti 分钟来到景点 Ai ,希望乘车前往景点Bi (Ai<B i ).为了使所有乘客都能顺

noip2011——提高组——观光公交

这题主要思想就是贪心了. 每次找出最优加速点,更新时间,就可以了. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int read(){ int t=1,num=0; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} wh

观光公交(codevs 1139)

题目描述 Description 风景迷人的小城 Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号景点,随后依次前往2.3.4……n 号景点.从第i 号景点开到第i+1 号景点需要Di 分钟.任意时刻,公交车只能往前开,或在景点处等待.设共有 m 个游客,每位游客需要乘车1 次从一个景点到达另一个景点,第i 位游客在Ti 分钟来到景点Ai,希望乘车前往景点Bi(Ai<Bi).为了使所有乘客都能顺

【NOIP 2011】 观光公交

题目描述 Description 风景迷人的小城 Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号景点,随后依次前往2.3.4……n 号景点.从第i 号景点开到第i+1 号景点需要Di 分钟.任意时刻,公交车只能往前开,或在景点处等待.设共有 m 个游客,每位游客需要乘车1 次从一个景点到达另一个景点,第i 位游客在Ti 分钟来到景点Ai,希望乘车前往景点Bi(Ai<Bi).为了使所有乘客都能顺