HDU - 6581 Vacation

题意:在马路上有n辆车在你前方,每辆车有三个属性:车长,车头离终点线距离,最大速度;
   道路狭窄不能超车,问你最快多久能到达终点,每辆车到达终点之后还是会继续行驶,当你的车头到达终点时就认为你到达了终点

思路:一眼二分时间,关键是怎么check:
   考虑我到达终点时前面的车需要到达的位置:终点向前走prl[i],prl[i]是l[i]去掉l[0]的前缀和,
   那么在check的t时间下按离终近计算每个车离应到的位点远置的距离les[i],les[i]受他前一个车的位置和v[i]影响,
   即max({les[i+1],s[i] + prl[i] - t*v[i],0})
   考虑les[0]的意义:因为prl[0] = 0,那么你的车车头应到的位置就是终点,如果les[0]<=0,那么就是到达了终点否则就没到达

时间复杂度o(60*n)
如果tle建议换scanf,关闭同步流没用....

const double esp = 1e-7;
const int maxn = 1e5 + 7;
int n;
double l[maxn], s[maxn], v[maxn], les[maxn], tot, prl[maxn];
bool check(double t) {
    for (int i = 0; i <= n; i++)
        les[i] = s[i] + tot;//最远车头到终终点的距离
    les[n + 1] = 0;
    for (int i = n; i >= 0; i--)
        les[i] = max(les[i + 1], max(s[i] + prl[i] - t * v[i], 0));
    return les[0] <= esp;
}
int main(){
    while (scanf("%d",&n)!=EOF) {
        tot = 0;
        for (int i = 0; i <= n; i++)
            scanf("%lf",&l[i]), tot += l[i];
        for (int i = 1; i <= n; i++)
            prl[i] = prl[i - 1] + l[i];
        for (int i = 0; i <= n; i++)
            scanf("%lf",&s[i]);
        for (int i = 0; i <= n; i++)
            scanf("%lf",&v[i]);
        double pl = 0.0, pr = 1e10;
        int cnt = 60;
        while (cnt--) {
            if (check((pl + pr) / 2.0)) {
                pr = (pl + pr) / 2.0;
            } else {
                pl = (pl + pr) / 2.0;
            }
        }
       printf ("%.9f\n",pl);
    }
}
posted @ 2021-03-16 22:05  naymi  阅读(39)  评论(0)    收藏  举报