首页 > 其他分享 >CSP历年复赛题-P5017 [NOIP2018 普及组] 摆渡车

CSP历年复赛题-P5017 [NOIP2018 普及组] 摆渡车

时间:2024-06-10 14:33:40浏览次数:8  
标签:cnt int sum maxt NOIP2018 P5017 发车 时刻 CSP

原题链接:https://www.luogu.com.cn/problem/P5017

题意解读:先将问题进行抽象、建模。

设一条数轴,从左到右,每个点对应一个时刻,每个时刻可能有多个人到达,然后有若干个发车时刻,每两个发车时刻间隔必须>=m,每个人的等待时长就是到最近一个发车时刻的时间累加,计算所有人等待时间最小值。

对样例2进行模拟:

1时刻1人出发,等待0;6时刻两人出发,等待2;14时刻两人出发,等待2;总等待时长4,没有比4更小的等待时长。

解题思路:

如何来求解最小的等待时长?

设f[i]表示前i个时刻,最后在i时刻有发车时,所有人的最小等待时长。

那么考虑上一个发车时刻j,我知道i - j >= m,所以j <= i - m

得到递推关系:f[i] = min{f[j] + (j,i]之间所有人到i的时间之和}

(j,i]之间所有人到i的时间之和如何计算:

设cnt[i]表示前i时刻到达的人数,sum[i]表示前i时刻所有到达人的时刻之和,则有

(j,i]之间所有人到i的时间之和 = (cnt[i] - cnt[j]) * i - (sum[i] - sum[j])

所以,f[i] = min{f[j] + (cnt[i] - cnt[j]) * i - (sum[i] - sum[j])},j <= i - m

还要考虑i < m的情况,f[i] = cnt[i] * i - sum[i]

此时:整体时间复杂度是n^2,n是时刻最大值,在4000000,总体复杂度会超时,需要进行优化。

优化一:减少冗余状态

如果i时刻前m时间之内没有一个人,那么f[i]就不用通过递推算了,直接f[i] = f[i-m],判断条件是cnt[i] == cnt[i-m]

优化二:减少转移范围

当前j<=i-m,而如果j <= i-2m,即j到i之间车可以有两个往返,那么车必然可以增加一次发车,这样能带更多的人,所以j最好>i-2m且<=i-m

结果:f[最后一个达到的人的时刻] ~ f[最后一个达到的人的时刻+m]的最小值

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 4000105;
int n, m, t, maxt;
int cnt[N], sum[N]; //设cnt[i]表示前i时刻到达的人数,sum[i]表示前i时刻所有到达人的时刻之和
int f[N]; //f[i]表示前i个时刻,最后在i时刻有发车时,所有人的最小等待时长。
int ans = INT_MAX;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> t;
        maxt = max(maxt, t);
        cnt[t]++, sum[t] += t;
    }
    //最后一个同学可能等到的时间maxt + m - 1
    for(int i = 1; i < maxt + m; i++)
    {
        cnt[i] += cnt[i - 1];
        sum[i] += sum[i - 1];
    }
    memset(f, 0x3f, sizeof(f));
    for(int i = 0; i < maxt + m; i++)
    {
        if(i >= m && cnt[i] == cnt[i - m])
        {
            f[i] = f[i - m];
            continue;
        }
        if(i < m)
            f[i] = cnt[i] * i - sum[i]; 
        else
            for(int j = max(0, i - 2 * m + 1); j <= i - m; j++)
            {
                f[i] = min(f[i], f[j] + (cnt[i] - cnt[j]) * i - (sum[i] - sum[j]));
            }
    }
    for(int i = maxt; i < maxt + m; i++) ans = min(ans, f[i]);
    cout << ans;

    return 0;
}

 

标签:cnt,int,sum,maxt,NOIP2018,P5017,发车,时刻,CSP
From: https://www.cnblogs.com/jcwy/p/18240648

相关文章

  • 【题解】 [CSP-J 2019] 纪念品
    题目描述题目大意在\(T\)天内,有\(n\)种纪念品和初始的\(m\)元。可以得到每天每种纪念品的价格。每一天可以以当日价格买卖纪念品。特别的,当天卖出得到的钱可以当天买入,当日买入的纪念品也可以当日卖出。当然可以一直持有。但是,\(T\)天过后,手上不可以持有纪念品。思路......
  • CSP历年复赛题-P3957 [NOIP2017 普及组] 跳房子
    原题链接:https://www.luogu.com.cn/problem/P3957题意解读:有n个格子,每个格子有不同的距离和分数,从起点,每次可跳距离为d,用g金币后可跳距离范围可以变成max(d-g,1)~d+g,求最小的g,使得可跳跃得分不少于k。解题思路:1、单调性分析:如果g越大,可跳跃的范围就越大,理论上能得的分数越......
  • 【题解】[CSP-J 2019] 公交换乘
    题目描述题目大意给出\(n\)次出行记录(地铁或公交车),有以下优惠方案:搭乘一次地铁后可以获得一张有效期为45分钟的优惠票,可以免费搭乘一次票价不超过该地铁票价的公交车。优惠票可以累计存储优先使用过期时间早的优惠票。思路枚举每一次出行:如果是地铁。累加花费,并记......
  • CSP历年复赛题-P3956 [NOIP2017 普及组] 棋盘
    原题链接:https://www.luogu.com.cn/problem/P3956题意解读:计算从(1,1)走到(m,m)的最小花费,有几个限定:同色格子可以走,花费为0;不同色格子可以走,花费为1;有色格子可以走到无色格子,花费为2,且用将无色格子临时染色;无色格子不能走到无色格子。解题思路:可以采用DFS来暴搜所有路径,需......
  • CSP历年复赛题-P3955 [NOIP2017 普及组] 图书管理员
    原题链接:https://www.luogu.com.cn/problem/P3955题意解读:给出n个图书编号,q个需求码,找到后缀与需求码匹配的最小图书编号,没有输出-1。解题思路:先对图书编号排序,用枚举法遍历每一个图书编号,看后缀是否与需求码相同。100分代码:#include<bits/stdc++.h>usingnamespacestd;c......
  • CSP历年复赛题-P2119 [NOIP2016 普及组] 魔法阵
    原题链接:https://www.luogu.com.cn/problem/P2119题意解读:在一组数里找出所有的Xa,Xb,Xc,Xd的组合,使得满足Xa<Xb<Xc<Xd,Xb-Xa=2(Xd-Xc),Xb-Xa<(Xc-Xb)/3,并统计出每个数作为A,B,C,D出现的次数。解题思路:1、枚举(O(n^4))首先想到的是通过4重循环枚举所有可能的Xa,Xb,Xc,Xd,然后判......
  • CSP历年复赛题-P2058 [NOIP2016 普及组] 海港
    原题链接:https://www.luogu.com.cn/problem/P2058题意解读:计算24小时时间窗口内不同国家的数量,是队列的典型应用。解题思路:本题需要用到两个关键的数据结构:队列、数组队列用来保存24小时内到达的船的时间,数组用来保存24小时内每个国家有多少人每到一只船,需要把时间放入队列,如......
  • CSP历年复赛题-P2010 [NOIP2016 普及组] 回文日期
    原题链接:https://www.luogu.com.cn/problem/P2010题意解读:计算两个日期之间有多少个日期是回文。解题思路:如果通过枚举两个日期之间的所有日期,然后判断回文,则会有几个问题:枚举数据规模在10^7级别,再加上对于日期加一天、判断回文等处理,有可能超时,而且对日期进行加一天、判断回......
  • CSP历年复赛题-P2672 [NOIP2015 普及组] 推销员
    原题链接:https://www.luogu.com.cn/problem/P2672题意解读:N家住户,每家住户与出入口距离是Si米,推销员每走1米疲劳值+1,向第i家住户推销疲劳值+Ai,推销员推销完原路返回出口,计算在向不同数量X的住户推销时,能达到的最大疲劳值。解题思路:本题是一种贪心选择问题,需要思考出可能的最优......
  • CSP历年复赛题-P2671 [NOIP2015 普及组] 求和
    原题链接:https://www.luogu.com.cn/problem/P2671题意解读:找到所有符合条件的三元组,累加三元组的分数,结果对10007取模。解题思路:仔细读题,并分析数据规模,1~4个数据点可以通过O(n^2)复杂度解决,也就是枚举法。1、枚举法要求x<y<z,y−x=z−y,移项可得x+z=2*y,并且c......