题目
http://acm.hdu.edu.cn/showproblem.php?pid=4454
分析
三分
枚举到达的线段,设在圆上的点的方向角为ang,在线段上的比例为t,那么在ang一定时t是单峰的,可以三分
然后容易发现ang的最小值也是单峰的,所以可以三分
所以两次三分即可
代码
/************************************************** * Problem: HDU 4454 * Author: clavichord93 * State: Accepted **************************************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #define sqr(a) ((a) * (a)) using namespace std; const double EPS = 1e-9; const double DINF = 1e30; inline int sgn(double a) { return a > EPS ? 1 : (a < -EPS ? -1 : 0); } struct Point { double x, y; Point() { x = y = 0; } Point(double _x, double _y) : x(_x), y(_y) {} Point operator + (const Point &a) const { return Point(x + a.x, y + a.y); } Point operator - (const Point &a) const { return Point(x - a.x, y - a.y); } Point operator * (const double &k) const { return Point(x * k, y * k); } void read() { scanf("%lf %lf", &x, &y); } }; typedef Point Vector; inline double dist(const Point &a, const Point &b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y)); } struct Circle { double x, y, r; Point getPoint(double ang) const { return Point(x + r * cos(ang), y + r * sin(ang)); } Point center() const { return Point(x, y); } void read() { scanf("%lf %lf %lf", &x, &y, &r); } }; Circle cake; Point start; Point p[4]; double calc2(Point a, Point b, Point p) { Vector v = b - a; double l = 0, r = 1; double ans = DINF; while (l <= r) { double length = (r - l) / 3; double x1 = l + length; double x2 = l + length * 2; double f1 = dist(a + v * x1, p); double f2 = dist(a + v * x2, p); if (sgn(f1 - f2) <= 0) { r = x2 - EPS; ans = f1; } else { l = x1 + EPS; ans = f2; } } return ans; } double calc(Point a, Point b) { double ang = atan2(start.y - cake.y, start.x - cake.x); double dis = dist(start, cake.center()); double alpha = acos(cake.r / dis); double l = ang - alpha, r = ang + alpha; double ans = DINF; while (l <= r) { double length = (r - l) / 3; double x1 = l + length; double x2 = l + length * 2; Point p1 = cake.getPoint(x1); Point p2 = cake.getPoint(x2); double f1 = calc2(a, b, p1) + dist(p1, start); double f2 = calc2(a, b, p2) + dist(p2, start); if (sgn(f1 - f2) <= 0) { r = x2 - EPS; ans = f1; } else { l = x1 + EPS; ans = f2; } } return ans; } int main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); #endif while (start.read(), sgn(start.x) || sgn(start.y)) { cake.read(); double x1, y1, x2, y2; scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); p[0] = Point(x1, y1); p[1] = Point(x1, y2); p[2] = Point(x2, y2); p[3] = Point(x2, y1); double ans = DINF; for (int i = 0; i < 4; i++) { double res = calc(p[i], p[(i + 1) % 4]); if (sgn(ans - res) > 0) { ans = res; } } printf("%.2f\n", ans); } return 0; }