HDU-3400 Line belt 计算几何 三分

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37753409/article/details/83593169

HDU-3400 Line belt

题意:给定两条线段AB和CD, 在AB上的速度为p, CD上的速度为q,其他地方的速度为r, 求从A->D的所需的最短时间。
分析: AB和CD上分别有一个点是满足最小条件的, 满足凸函数性质,可以对AB和CD区间进行分别三分求解, 详情见代码。
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const double eps = 1e-10;
struct Point
{
    double x, y;
    Point() {}
    Point(double _x, double _y)
    {
        x = _x;
        y = _y;
    }
    Point mid(Point b)
    {
        return Point((x + b.x) / 2, (y + b.y) / 2);
    }
    double distance(Point p)
    {
        return hypot(x - p.x, y - p.y);
    }
};
Point A, B, C, D;
double P, Q, R;
//CD三分
double solve(Point x)
{
    Point l, r, mid, midmid;
    l = C, r = D;
    double dis1, dis2;
    while (r.distance(l) > eps)
    {
        mid = l.mid(r);
        midmid = mid.mid(r);

        dis1 = x.distance(mid) / R + mid.distance(D) / Q;
        dis2 = x.distance(midmid) / R + midmid.distance(D) / Q;
        if (dis1 > dis2)
        {
            l = mid;
        }
        else
        {
            r = midmid;
        }
    }
    return x.distance(l) / R + l.distance(D) / Q;
}
//AB三分
double solve()
{
    Point l, r, mid, midmid;
    l = A, r = B;
    double dis1, dis2;
    while (r.distance(l) > eps)
    {
        mid = l.mid(r);
        midmid = mid.mid(r);

        dis1 = A.distance(mid) / P + solve(mid);
        dis2 = A.distance(midmid) / P + solve(midmid);

        if (dis1 > dis2)
        {
            l = mid;
        }
        else
        {
            r = midmid;
        }
    }
    return A.distance(l) / P + solve(l);
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y);
        scanf("%lf%lf%lf%lf", &C.x, &C.y, &D.x, &D.y);
        scanf("%lf%lf%lf", &P, &Q, &R);
        printf("%.2f\n", solve());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37753409/article/details/83593169
今日推荐