牛客网多校3 Distance to Work (圆与多边形面积交)

题目:给你一个多变形,再给你几个圆心点,问每个圆心点的半径为多少时,圆的面积为多边形面积的(1-p/q);

思路:二分,注意精度,拼凑模板

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
int sgn(double x){
    if(fabs(x) < eps)return 0;
    if(x < 0)return-1;
    else return 1;
}
inline double sqr(double x){return x*x;}

struct Point{
    double x,y;
Point(){}
    Point(double _x,double _y){
        x = _x;
        y = _y;
    }
    bool operator == (Point b)const{
        return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
    }
    bool operator < (Point b)const{
        return sgn(x-b.x)== 0-sgn(y-b.y)?0:x<b.x;
    }
    Point operator-(const Point &b)const{
        return Point(x-b.x,y-b.y);
    }
    double operator ^(const Point &b)const{
        return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const{
        return x*b.x + y*b.y;
    }
    double len(){
        return hypot(x,y);
    }
    double len2(){
        return x*x + y*y;
    }
    double distance(Point p){
        return hypot(x-p.x,y-p.y);
    }
    Point operator +(const Point &b)const{
        return Point(x+b.x,y+b.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 rad(Point a,Point b){
        Point p = *this;
        return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
    }
    Point trunc(double r){
        double l = len();
        if(!sgn(l))return *this;
        r /= l;
        return Point(x*r,y*r);
    }

};
struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e){
        s = _s;
        e = _e;
    }
    double length(){
        return s.distance(e);
    }
    double dispointtoline(Point p){
        return fabs((p-s)^(e-s))/length();
    }
    Point lineprog(Point p){
        return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
    }
    Point symmetrypoint(Point p){
        Point q = lineprog(p);
        return Point(2*q.x-p.x,2*q.y-p.y);
    }
};
struct circle{
    Point p;
    double r;
circle(){}

    bool operator == (circle v){
        return (p==v.p) && sgn(r-v.r)==0;
    }
    bool operator < (circle v)const{
        return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
    }
    int relation(Point b){
        double dst = b.distance(p);
        if(sgn(dst-r) < 0)return 2;
        else if(sgn(dst-r)==0)return 1;
        return 0;
    }
    int relationline(Line v){
        double dst = v.dispointtoline(p);
        if(sgn(dst-r) < 0)return 2;
        else if(sgn(dst-r) == 0)return 1;
        return 0;
    }
     int pointcrossline(Line v,Point &p1,Point &p2){
        if(!(*this).relationline(v))return 0;
        Point a = v.lineprog(p);
        double d = v.dispointtoline(p);
        d = sqrt(r*r-d*d);
        if(sgn(d) == 0){
            p1 = a;
            p2 = a;
            return 1;
        }
        p1 = a + (v.e-v.s).trunc(d);
        p2 = a-(v.e-v.s).trunc(d);
        return 2;
    }
    double areatriangle(Point a,Point b){
        if(sgn((p-a)^(p-b)) == 0)return 0.0;
        Point q[5];
        int len = 0;
        q[len++] = a;
        Line l(a,b);
        Point p1,p2;
        if(pointcrossline(l,q[1],q[2])==2){
            if(sgn((a-q[1])*(b-q[1]))<0)q[len++] = q[1];
            if(sgn((a-q[2])*(b-q[2]))<0)q[len++] = q[2];
        }
        q[len++] = b;
        if(len == 4 && sgn((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])==0||relation(q[i+1])==0){
                double arg = p.rad(q[i],q[i+1]);
                res += r*r*arg/2.0;
            }
            else{
                res += fabs((q[i]-p)^(q[i+1]-p))/2.0;
            }
        }
        return res;
    }
};

struct polygon{
    int n;
    Point p[maxp];
    Line l[maxp];
    void add(Point q){
        p[n++] = q;
    }
    double getarea(){
        double sum = 0;
        for(int i = 0;i < n;i++){
            sum += (p[i]^p[(i+1)%n]);
        }
        return fabs(sum)/2;
    }
    double areacircle(circle c){
        double ans = 0;
        for(int i = 0;i < n;i++){
            int j = (i+1)%n;
            if(sgn( (p[j]-c.p)^(p[i]-c.p) ) >= 0)
            ans += c.areatriangle(p[i],p[j]);
            else ans-= c.areatriangle(p[i],p[j]);
        }
        return fabs(ans);
    }
};
polygon a;
circle c;
double P,Q;
#define Eps 1e-6
bool check(double r)
{
    c.r=r;
    double tmp1=a.areacircle(c);
    double tmp2=a.getarea();
    tmp1=tmp2-tmp1;
    if(tmp1*Q+Eps<=tmp2*P)
        return true;
    return false;
}
int main()
{
    scanf("%d",&a.n);
    for(int i=0;i<a.n;i++)
        scanf("%lf%lf",&a.p[i].x,&a.p[i].y);
    int t=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf",&c.p.x,&c.p.y);
        scanf("%lf%lf",&P,&Q);
        double l=0.0,r=1e6;
        while(r-l>Eps)
        {
            double mid=(l+r)/2.0;
            if(check(mid))
                r=mid;
            else
                l=mid;
        }
        printf("%.10lf\n",l);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dllpxfire/article/details/81254139