牛客多校3 J Distance to Work

傻逼模板题

#include<bits/stdc++.h>
using namespace std;

const double eps = 1e-8;
const double pi = acos(-1);

int dcmp(double x) {
    if (fabs(x) <eps) return 0;
    return x < 0 ? -1 : 1;
}

struct point {
    double x, y;
    point (double x = 0, double y = 0) :x(x), y(y) {}
    void input() {
        scanf("%lf%lf", &x, &y);
    }
    void output() {
        printf("x = %f y = %f\n", x, y);
    }
    point operator + (const point &rhs) const {
        return point(x + rhs.x, y + rhs.y);
    }
    point operator - (const point &rhs) const {
        return point(x - rhs.x, y - rhs.y);
    }
    point operator * (const double &k) const {
        return point(x * k, y * k);
    }
    point operator / (const double &k) const {
        return point(x / k, y / k);
    }
    double len2() {
        return x * x + y * y;
    }
    point change_len(double r) {
        double l = sqrt(len2());
        if (dcmp(l) == 0) return *this;
        r /= l;
        return point(x * r, y * r);
    }
};
double cross(point a, point b) {
    return a.x * b.y - a.y * b.x;
}
double dot(point a, point b) {
    return a.x * b.x + a.y * b.y;
}
double dis(point a, point b) {
    return sqrt(dot(a - b, a - b));
}
double rad(point a, point b) {
    return fabs(atan2(fabs(cross(a, b)), dot(a, b)));
}
struct circle {
    point p;
    double r;
    circle() {}
    circle(point p, double r) :p(p), r(r) {}
    double area() {
        return pi * r * r;
    }
};
struct line {
    point s, e;
    double length() {
        return dis(s, e);
    }
    line() {}
    line(point s, point e) :s(s), e(e) {}
};
double point_to_line(point p, line a) {
    return fabs(cross(p - a.s, a.e - a.s) / a.length());
}
point projection(point p, line a) {
    return a.s + (((a.e - a.s) * dot(a.e - a.s, p - a.s)) / (a.e - a.s).len2());
}
int relation(line a, circle b) {
    double p = point_to_line(b.p, a);
    if (dcmp(p - b.r) == 0) return 1;
    return dcmp(p - b.r) < 0 ? 2 : 0;
}
int relation(point p, circle a) {
    double d = dis(p, a.p);
    if (dcmp(d - a.r) == 0) return 1;
    return dcmp(d - a.r) < 0 ? 2 : 0;
}
int line_circle_intersection(line v, circle u, point &p1, point &p2) {
    if (!relation(v, u)) return 0;
    point a = projection(u.p, v);
    double d = point_to_line(u.p, v);
    d = sqrt(u.r * u.r - d * d);
    if (dcmp(d) == 0) {
        p1 = p2 = a;
        return 1;
    }
    p1 = a + (v.e - v.s).change_len(d);
    p2 = a - (v.e - v.s).change_len(d);
    return 2;
}
double cir_tra_area(point a, point b, circle c) {
    point p = c.p; double r = c.r;
    if (dcmp(cross(p - a, p - b)) == 0) return 0;
    point q[5];
    int len = 0;
    q[len++] = a;
    line l(a, b);
    point p1, p2;
    if (line_circle_intersection(l, c, q[1], q[2]) == 2) {
        if (dcmp(dot(a - q[1], b - q[1])) < 0) q[len++] = q[1];
        if (dcmp(dot(a - q[2], b - q[2])) < 0) q[len++] = q[2];
    }
    q[len++] = b;
    if (len == 4 && dcmp(dot(q[0] - q[1], q[2] - q[1])) > 0) swap(q[1], q[2]);
    double res = 0;
    for (int i = 0; i < len - 1; i++) {
        if (relation(q[i], c) == 0 || relation(q[i + 1], c) == 0) {
            double ang = rad(q[i] - p, q[i + 1] - p);
            res += r * r * ang / 2.0;
        }
        else {
            res += fabs(cross(q[i] - p, q[i + 1] - p)) / 2;
        }
    }
    return res;
}
double area_poly_cir(circle c, point *p, int n) {
    double ans = 0;
    for (int i = 0; i < n; i++) {
        int j = (i + 1) % n;
        if (dcmp(cross(p[j] - c.p, p[i] - c.p)) >= 0) ans += cir_tra_area(p[i], p[j], c);
        else ans -= cir_tra_area(p[i], p[j], c);
    }
    return fabs(ans);
}
double poly_area(point *p, int n) {
    double area = 0;
    for (int i = 1; i < n - 1; i++) {
        area += cross(p[i] - p[0], p[i + 1] - p[0]);
    }
    return fabs(area / 2);
}

point poly[222];
int n, p, q, m;
circle cc;

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) poly[i].input();
    long double s = poly_area(poly, n);
    scanf("%d", &m);
    while (m--) {
        cc.p.input();
        scanf("%d%d", &p, &q);
        p = q - p;
        long double l = 0, r = 1e4;
        for (int i = 0; i < 100; i++) {
            long double mid = (l + r) / 2;
            cc.r = mid;
            long double tmp = area_poly_cir(cc, poly, n);
            if (tmp * q < s * p) l = mid;
            else r = mid;
        }
        double ans = (l + r) / 2;
        printf("%.12f\n", ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值