Circle and Points POJ - 1981(单位圆覆盖)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leekerian/article/details/89198042

题解

考虑这样的问题以每个点为圆心做半径为1的圆如图ABC,这些圆相交的相交区域如图斜线标出的,在这个区域里面的点到ABC三个点的圆心的距离都是<=1的所以只要在这个区域里面取点做一个半径为1的圆就能把ABC的圆心给圈起来,所以问题就转化成怎么求覆盖的区域,我们用扫描线的思想,B圆与A圆交于点a,a1与C交于点b,b1,我们令方向为逆时针,这个时候每两个交点都有一个入点一个出点,遇到一个入点我们就+1,遇到出点我们就-1,这样就能表示出被覆盖的次数(参考线段树扫描线求矩形面积),连接AB两圆的圆心,连接a,a1,线段aa1垂直平分AB线段,我们就可以用acos求出角度,然后排序就行了,总复杂度n^2logn

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <math.h>

using namespace std;


const double eps=1e-8;
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}

struct point{
    double x,y;
    int fg;
    double at;
    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
    point operator -(const point &b)const
    {
        return point(x-b.x,y-b.y);
    }
    double operator *(const point &b)const 
    {
        return x*b.x+y*b.y;
    }
    double distance(point p){
        return hypot(x - p.x,y - p.y);
    }
    double len(){
        return hypot(x,y);//库函数
    }
    point trunc(double r){
        double l = len();
        if(!sgn(l))return *this;
        r /= l;
        return point(x*r,y*r);
    }
    double operator ^(const point &b)const{
        return x*b.y-y*b.x;
    }
    point operator +(const point &b)const{
        return point(x+b.x,y+b.y);
    }
    point rotleft(){
        return point( - y,x);
    }
    point rotright(){
        return point(y, - x);
    }
};

bool cmp1(point a,point b){
    double p=a.at,q=b.at;
    if(p!=q){
        return p<q;
    }
    return a.fg>b.fg;
}



point p[333];
point p_a[180000];

int main()
{
    int n;
    while(cin>>n&&n)
    {
        for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        int ans1=1;
        for(int i=0;i<n;i++)
        {
            int cont=0;
            for(int j=0;j<n;j++)
            {
                if(p[i].distance(p[j])>2.0) continue;
                if(j==i) continue;
                double at1=acos(p[i].distance(p[j])/2.0);
                double at2=atan2(p[j].y-p[i].y,p[j].x-p[i].x);
                p_a[cont].at=at2-at1;
                p_a[cont++].fg=1;
                p_a[cont].at=at2+at1;
                p_a[cont++].fg=-1;
            }
            sort(p_a,p_a+cont,cmp1);
            int ans2=1;
            for(int j=0;j<cont;j++)
            {
                if(p_a[j].fg==1) ans2++;
                else ans2--;
                ans1=max(ans1,ans2);
            }
        } 
        printf("%d\n",ans1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/leekerian/article/details/89198042