• 【2018牛客多校round3 J】Distance to Work


    题意

    给一个简单多边形,多边形内有一个点A,要求另外一个点B,在至少有P/Q(P<Q) 个点距离大于点B到点A的距离的前提下,点B到点A的距离最大,求这个距离

    分析

    以A点为圆心AB距离为半径画圆,圆外的点距离A都比B距离A大
    二分圆的半径,求圆和多边形面积的交,这些点都是比B到A距离小的,找到恰好面积为多边形面积(Q-P)/P倍的半径,得到最后的答案

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const double eps = 1e-9;            //浮点数精度控制
    #define Vector point
    #define Point point
    const double PI = acos(-1);
    struct Point{
        double x,y;
        Point(double x=0,double y=0) :x(x),y(y){}
        friend Vector operator + (Vector A,Vector B){ return Vector(A.x + B.x , A.y + B.y);}
        friend Vector operator - (Point A,Point B){ return Vector(A.x - B.x , A.y - B.y);}
        friend Vector operator * (Vector A,double p) {return Vector(A.x*p , A.y*p);}
        friend Vector operator / (Vector A,double p) {return Vector(A.x/p,A.y/p);}
        friend bool operator < (const Point &a,const Point &b){
        return a.x< b.x || ( a.x == b.x && a.y < b.y);
        }
    };
    int dcmp(double k){
        return k < -eps ?-1:k>eps?1:0;
    }
    double sqr(double k){return k*k;}
    double mysqrt(double n){ return sqrt(max(0.0,n));}
    double cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
    double dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}
    double abs(Point o){return sqrt(dot(o,o));}
    point _a[205],o;
    int P,Q;
    int n;
    double r;
    double ALL;
    void circle_cross_line(Point a,Point b,Point o,double r,Point ret[],int &num){
        double x0 = o.x,y0 = o.y;
        double x1 = a.x,y1 = a.y;
        double x2 = b.x,y2 = b.y;
        double dx = x2 - x1,dy = y2-y1;
        double A = dx*dx +dy*dy;
        double B = 2*dx*(x1-x0)+2*dy*(y1-y0);
        double C = sqr(x1-x0)+sqr(y1-y0)-sqr(r);
        double delta = B*B - 4*A*C;
        num = 0;
        if(dcmp(delta)>=0){
    	double t1 = (-B-mysqrt(delta))/(2*A);
    	double t2 = (-B+mysqrt(delta))/(2*A);
    	if(dcmp(t1-1)<=0 && dcmp(t1)>=0){
    	    ret[num++] = Point(x1+t1*dx , y1 + t1*dy);
    	}
    	if(dcmp(t2-1)<=0 && dcmp(t2)>=0){
    	    ret[num++] = Point(x1 + t2*dx,y1+t2*dy);
    	}
        }
    
    }
    double sector_area(point a,point b){
        double theta = atan2(a.y,a.x) - atan2(b.y,b.x);
        while(theta <=0) theta+=2*PI;
        while(theta > 2*PI) theta -= 2*PI;
        theta = min (theta,2*PI - theta);
        return r*r *theta / 2;
    }
    double calc(Point a,Point b){
        Point p[2];
        int num = 0;
        int ina = dcmp(abs(a)-r)<0;
        int inb = dcmp(abs(b)-r)<0;
        if(ina){
    	if(inb){
    	    return fabs(cross(a,b))/2.0;
    	}else{
    	    circle_cross_line(a,b,Point(0,0),r,p,num);
    	    return sector_area(b,p[0])+fabs(cross(a,p[0]))/2.0;
    	}
        }else{
    	if(inb) {
    	    circle_cross_line(a,b,Point(0,0),r,p,num);
    	    return sector_area(p[0],a)+fabs(cross(p[0],b))/2.0;
    	}else{
    	    circle_cross_line(a,b,Point(0,0),r,p,num);
    	    if(num == 2){
    		return sector_area(a,p[0]) + sector_area(p[1],b)
    		    + fabs(cross(p[0],p[1]))/2.0;
    	    }else {
    		return sector_area(a,b);
    	    }
    
    	}
        }
    }
    double area(){
        double ret = 0;
        for(int i = 1;i<=n;i++){
    	int sgn = dcmp(cross(_a[i],_a[i+1]));
    	if(sgn!=0) ret+=sgn * calc(_a[i],_a[i+1]);
        }
        return abs(ret);
    }
    bool check()
    {
        double are = area();
        if(dcmp(are - ALL)<0) return false;
        return true;
    }
    Point __a[206];
    double PolygonArea(){
        double area = 0;
        for(int i = 2;i<n;i++)
        {
    	area+=cross(__a[i] - __a[1],__a[i+1] - __a[1]);
        }	
        return fabs(area*0.5);
    }
    int main()
    {
        cin>>n;
        for(int i = 1;i<=n;i++) cin>>__a[i].x>>__a[i].y;
        __a[n+1] = __a[1];
        n++;
        int m;cin>>m;
        double all = PolygonArea();
        while(m--)
        {
             cin>>o.x>>o.y>>P>>Q;
            for(int i = 1;i<=n;i++) _a[i] = __a[i] - o;
            P = Q-P;
            ALL = P*all/Q;
            double L = 0,R = 5000000;
            while(dcmp(L-R)!=0)
            {
                r =(L+R)/2.0;
                if(check()) R = r;
                else L = r;
            }
            printf("%.10f
    ",L);
        }
    }
    
  • 相关阅读:
    Row size too large. The maximum row size for the used table type 解决
    pandas Series介绍
    Scala核心编程_第08章 面向对象编程(中高级部分)
    mysql增删改字段,重命名替换字段
    python报错ValueError: cannot reindex from a duplicate axis
    pandas DataFrame 数据筛选
    Scala核心编程_第07章 面向对象编程(中级部分)
    Scala核心编程_第06章 面向对象编程(基础部分)
    《The Rise and Fall of Scala》scala兴衰读后感
    信贷业务(Ali)
  • 原文地址:https://www.cnblogs.com/greenty1208/p/9379477.html
Copyright © 2020-2023  润新知