• P5017 摆渡车


    摆渡车这题是真的毒瘤,放在普及组里是真的皮

    几个基本的东西:

    1、车肯定要等到某个人来再出发是吧,于是可以先枚举第一次的出发时间。

    2、一辆车到达的时候,如果有些人已经在等了,所以车一到就马上出发

    3、既然要等,那就要等到人再走等几个人都有可能,这里就可以在(dfs)时单独处理一下全都在等的情况可以省点时间。要是发车时无人上车,那么发车时间就可以提前到上一个人上车的时间,这样不会导致等待时间更长

    思路一: 记忆化搜索

    1.先把到达的时间从小到大排序

    2.记忆化搜索的实现方法开 (f[max])数组,(f[i])表示车在第(i)分钟可以出发,此时已经积累的最少的等车时间利用前缀和初始化一下f数组,注意f数组要先弄成一个很大的数防止记忆化搜索的时候瞎jb更新

    初始化:

        for(int i=1; i<=n; i++) {
            p+=(i-1)*(a[i]-a[i-1]);
            f[a[i]]=p;
            }
        }
    

    这里的初始化解释的详细一点,来接第(i)个人时还没上车的人的等待时间就是(a[i]-a[i-1]),那么有(i-1)个人在等 ,这里默认的就是所有人等车,因为我想要知道的是当前时间发出的等待时间,如果考虑太复杂的话就没法初始化了,而且这已经是最蛋疼的情况了,一次全接走不可能比这等待时间在长了

    3.dfs阶段:

    void dfs(int times,int k) 
    

    (times)表示上次在第(times)分钟发车, (k)表示上次已经接走了(k)个人

    至于为什么用上一次发车的时间可以看下面记忆化的实现

    k的作用:

    1.判断dfs结束

     if(k==n) {
            if(f[times]<minn) {
                minn=f[times];
            }
            return ;
        }
    

    2.用于枚举下一次上车的人

    for(int i=k+1; i<=n; i++)
    

    记忆化的实现:

    (dfs)更新f数组可以减少以后的冗余计算,之后计算时直接利用f[times](注意times是上一次发车的时间

    下面是默认的车一回来就出发的情况:

     if(f[times]+s<f[times+m]&&times+m>=a[k+1]) {
            f[times+m]=f[times]+s;
            dfs(times+m,to);
        }
    

    to是通过循环找的(a[i]<=times+m)的:
    如下

     for(int i=k+1; i<=n; i++) {
            if(a[i]<=times+m) {
                s+=times+m-a[i];
                if(s>=minn)       return;//此处用了一点小技巧,当累计的时间已经超过了最小值就没必要继续找了
                to=i;
            } else {
                break;
            }
        }
    

    但是车一会来不一定会立刻出发,这也应该是比较难处理的地方之一

            if(f[times]+s<f[a[i]]&&times+m<=a[i]&&a[i]!=a[i+1]) {//看这里的if语句有优化
                f[a[i]]=f[times]+s;
                dfs(a[i],i);
            }
    

    这里就又出现了一个优化就是当(n)个人同一时间发车时,他们需要一起上而不是每个人都进行一次搜索

    也就是]这里

        a[i]!=a[i+1
    

    记忆化搜索就是这样比较慢,在机房的垃圾电脑上评测会TLE的

    思路二: DP

    不会

  • 相关阅读:
    Python高级数据处理与可视化(四)---- 数据存储
    Python高级数据处理与可视化(三)---- Matplotlib图像属性控制 & Pandas作图
    Notepad++
    HDU2819 Swap(二分匹配+输出结果)
    HDU1281 棋盘游戏(二分匹配+找必要的点)
    HDU1083 Courses(二分匹配)
    HDU2444 二分图判断+最大匹配
    HDU1045 Fire Net(二分匹配)
    exam1802 Bounty Hunter II(DAG的最小路径覆盖)
    SDUSTOJ 1801 LIS2(最长上升子序列不同值的数量)
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/11087879.html
Copyright © 2020-2023  润新知