HDU-3400 Line belt 計算幾何 三分
阿新 • • 發佈:2018-11-26
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; }