[HDU 4454 Stealing a Cake] 三分套三分

来源:互联网 发布:排水系统模拟软件 编辑:程序博客网 时间:2024/05/16 04:55

题目

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;}



0 0