标签:最小 初始 评测 for 阶段 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;
        }
    }
3.dfs阶段:
void dfs(int times,int k) 
$times$表示上次在第$times$分钟发车, $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]&×+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]]&×+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的
不会,请lhy大佬来讲吧
标签:最小 初始 评测 for 阶段 dfs 个人 结束 排序
原文地址:https://www.cnblogs.com/pyyyyyy/p/11087879.html