P2571 [SCOI2010]传送带

链接:https://www.luogu.org/problemnew/show/P2571

题目描述

在一个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 上从哪个点离开,那么 上从哪个点离开,那么 上从哪个点离开,那么 CD 上点的 上点的 距离函数一定是个单谷,可以三分来求。 
• 如何求解 AB 上的点呢?
• 他也满足单谷的性质,可以三分来求。用CD上的点来更新AB上的点

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

const double eps = 1e-6;
double Ax, Ay, Bx, By, Cx, Cy, Dx, Dy, p, q, r;
double dis(double x1, double y1, double x2, double y2){
    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
double work(double nx, double ny){
    double lf = Cx, rg = Dx, hlf = Cy, hrg = Dy, ans = 1000000008;
    while(1){
        double midx = (lf + rg) / 2, midy = (hlf + hrg) / 2;
        double midxm = (midx + rg) / 2, midym = (midy + hrg) / 2;    
        double tmp1 = dis(nx, ny, midx, midy)/r + dis(Ax, Ay, nx, ny)/ p + dis(midx, midy, Dx, Dy)/q;
        double tmp2 = dis(nx, ny, midxm, midym)/r + dis(Ax, Ay, nx, ny)/ p + dis(midxm, midym, Dx, Dy)/q;
        if(tmp1 < tmp2) rg = midxm, hrg = midym;
        else lf = midx, hlf = midy;
        ans = min(ans, min(tmp1, tmp2));
    //    printf("%lf %lf
", tmp1, tmp2);
        if(fabs(midx-midxm) < eps && fabs(midy-midym) < eps)break;
    }
    return ans;
    
}

int main(){
    double ans = 100000000008;
    
    scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &Ax, &Ay, &Bx, &By, &Cx, &Cy, &Dx, &Dy, &p, &q, &r);
    double lf = Ax, rg = Bx, hlf = Ay, hrg = By;
    while(1){
        double midx = (lf + rg) / 2, midy = (hlf + hrg) / 2;
        double midxm = (midx + rg) / 2, midym = (midy + hrg) / 2;
        double ans1 = work(midx, midy), ans2 = work(midxm, midym);
        if(ans1 < ans2) rg = midxm, hrg = midym;
        else lf = midx, hlf = midy;
        ans = min(ans, min(ans1, ans2));
        if(fabs(midx-midxm) < eps && fabs(midy-midym) < eps)break;
    } 
    printf("%.2lf
", ans);
}
View Code
原文地址:https://www.cnblogs.com/EdSheeran/p/9277885.html