ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NC20276 [SCOI2010]传送带

2022-06-29 03:31:33  阅读:140  来源: 互联网

标签:dist 传送带 Point double Fx1 NC20276 mid2 mid1 SCOI2010


NC20276 [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

输出

136.60

备注

对于 \(100\%\) 的数据,\(1\le A_x,A_y,B_x,B_y,C_x,C_y,D_x,D_y\le10^3\) 。

题解

思路

知识点:三分,计算几何。

关于时间计算有两个变量,一个是在 \(AB\) 上的终点 \(E\),一个是 \(CD\) 上的起点 \(F\) ,则总时长为 \(\frac{|AE|}{P} + \frac{|EF|}{R} + \frac{|FD|}{Q}\) 。若固定 \(E\) ,则总时间关于 \(F\) 是单谷函数,就可以用三分确定使时间最短的 \(F\) ,得到在 \(E\) 这个点的最短时间。若对每个 \(E\) 都用三分取时间最短的 \(F\) ,则总时间关于 \(E\) 也是个单谷函数,用三分确定让时间最短的 \(E\) 。综上,在三分 \(E\) 的计算两个分点时间的过程中,各自对 \(F\) 三分得到固定 \(E\) 后的最小时间,作为两个三分\(E\) 的分点的时间进行判断。

实际上,总时长关于 \(E\) 和 \(F\) 的多元函数只有一个最小值,而对每个 \(E\) 都取最小值得到的总时长关于 \(E\) 的函数是一定过最小点的曲线,因此对 \(E\) 三分就能得到最小值。

细节上用参数方程来实现在直线上三分,用两点距离作为误差判断条件。

坑点:速度和右端点变量名重了,会炸qwq。

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

const double esp = 1e-3;

struct Point {
    double x, y;
}A, B, C, D;
double P, Q, R;//!R 和 r不要搞混了,被坑死了

double dist(Point a, Point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

Point Fx1(double t) {
    return { (B.x - A.x) * t + A.x,(B.y - A.y) * t + A.y };
}

Point Fx2(double t) {
    return { (D.x - C.x) * t + C.x,(D.y - C.y) * t + C.y };
}

double calc(Point E) {
    double ans = dist(A, E) / P;
    double l = 0, r = 1;
    while (dist(Fx2(l), Fx2(r)) >= esp) {
        double mid1 = l + (r - l) / 3;
        double mid2 = r - (r - l) / 3;
        Point F1 = Fx2(mid1);
        Point F2 = Fx2(mid2);
        if (dist(E, F1) / R + dist(F1, D) / Q >= dist(E, F2) / R + dist(F2, D) / Q) l = mid1;
        else r = mid2;
    }
    Point F = Fx2(l);
    ans += dist(E, F) / R + dist(F, D) / Q;
    return ans;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> A.x >> A.y >> B.x >> B.y;
    cin >> C.x >> C.y >> D.x >> D.y;
    cin >> P >> Q >> R;

    double l = 0, r = 1;
    while (dist(Fx1(l), Fx1(r)) >= esp) {
        double mid1 = l + (r - l) / 3;
        double mid2 = r - (r - l) / 3;
        Point E1 = Fx1(mid1);
        Point E2 = Fx1(mid2);
        if (calc(E1) >= calc(E2)) l = mid1;
        else r = mid2;
    }
    Point E = Fx1(l);
    cout << fixed << setprecision(2) << calc(E) << '\n';
    return 0;
}

标签:dist,传送带,Point,double,Fx1,NC20276,mid2,mid1,SCOI2010
来源: https://www.cnblogs.com/BlankYang/p/16421862.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有