[SCOI2010]传送带 题解

[SCOI2010]传送带 题解

题目地址:洛谷:【P2571】[SCOI2010]传送带 – 洛谷、BZOJ:Problem 1857. — [Scoi2010]传送带

题目描述

在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间

输入输出格式

输入格式:
输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By
第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy
第三行是3个整数,分别是P,Q,R

输出格式:
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位

输入输出样例

输入样例#1:

0 0 0 100
100 0 100 100
2 2 1

输出样例#1:

136.60

说明

对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000,1<=P,Q,R<=10

题解

我们在AB上取一个点E,CD上取一个点F,路径一定是A→E→F→D这样的。我们来大胆猜测一波,如果固定E,时间关于F在CD上的位置是一个单峰有最小值的函数,再猜测总时间关于E在AB上的位置也是这样一个函数,那么我们就可以三分套三分来解决这个问题。可是我不会证明啊QAQ
三分法是用于解决单峰函数找最值的问题的方法,具体操作可以参见【P3382】【模板】三分法 – 洛谷

代码

// Code by KSkun, 2018/5
#include <cstdio>
#include <cctype>
#include <cmath>

const double EPS = 1e-8;

double ax, ay, bx, by, cx, cy, dx, dy, p, q, r;

// E on AB, F on CD
inline double caltime(double ex, double ey, double fx, double fy) {
    return sqrt((ex - ax) * (ex - ax) + (ey - ay) *(ey - ay)) / p
        + sqrt((dx - fx) * (dx - fx) + (dy - fy) *(dy - fy)) / q
        + sqrt((ex - fx) * (ex - fx) + (ey - fy) *(ey - fy)) / r;
}

inline double terCD(double ex, double ey) {
    double l = 0, r = 1, mid, midd;
    while(r - l > EPS) {
        mid = (l + r) / 2; midd = (mid + r) / 2;
        if(caltime(ex, ey, cx + (dx - cx) * mid, cy + (dy - cy) * mid) < 
            caltime(ex, ey, cx + (dx - cx) * midd, cy + (dy - cy) * midd)) {
            r = midd;
        } else {
            l = mid;
        }
    }
    return caltime(ex, ey, cx + (dx - cx) * l, cy + (dy - cy) * l);
}

inline double terAB() {
    double l = 0, r = 1, mid, midd;
    while(r - l > EPS) {
        mid = (l + r) / 2; midd = (mid + r) / 2;
        if(terCD(ax + (bx - ax) * mid, ay + (by - ay) * mid) <
            terCD(ax + (bx - ax) * midd, ay + (by - ay) * midd)) {
            r = midd;
        } else {
            l = mid;
        }
    }
    return terCD(ax + (bx - ax) * l, ay + (by - ay) * l);
}

int main() {
    scanf("%lf%lf%lf%lf", &ax, &ay, &bx, &by);
    scanf("%lf%lf%lf%lf", &cx, &cy, &dx, &dy);
    scanf("%lf%lf%lf", &p, &q, &r);
    printf("%.2lf", terAB());
    return 0;
}


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据