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

题目

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



你可能感兴趣的:([HDU 4454 Stealing a Cake] 三分套三分)