NOIP2011 观光公交(贪心)

好吧,看到这道题的题目就晕了,好长一串。。。

由于找不出来什么特别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

NOIP2011 观光公交(贪心)的相关文章

P1315 观光公交 贪心

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

[NOIP2011]观光公交 题解

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

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 个游客,

【NOIP2011】观光公交

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

[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).为了使所有乘客都能顺