版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}