Geometry Problem (基础计算几何+随机化) HDU6242

Geometry Problem

Alice is interesting in computation geometry problem recently. She found a interesting problem and solved it easily. Now she will give this problem to you

You are given N distinct points (Xi,Yi) on the two-dimensional plane. Your task is to find a point P and a real number R, such that for at least ⌈N/2⌉ given points, their distance to point P is equal to R.
N<=1e5
题意: 给你N个点,求出某个圆上至少有一半的点在上面
思路: 因为题面已经保证至少有一半点在某个圆上,我们可以随机取三个点,至少有1/8的概率同时取到三个点就是那一半的点,而三点可以确定一个圆,故一般来说大概8次有1次可以找到那个圆,注意需要注意点数小于4的时候特判掉就行
三点确定一个圆的公式与模板,记得需要限制条件保证三点不在一条直线上
Geometry Problem (基础计算几何+随机化) HDU6242_第1张图片

已知三点求圆心与半径模板
double dis2(int a)
{
    return sqrt((p[a].x-x)*(p[a].x-x)+(p[a].y-y)*(p[a].y-y));
}

void cal(int a,int b,int c)//求外心
{
    double a1 = p[b].x - p[a].x, b1 = p[b].y - p[a].y, c1 = (a1*a1 + b1*b1)/2;
    double a2 = p[c].x - p[a].x, b2 = p[c].y - p[a].y, c2 = (a2*a2 + b2*b2)/2;
    double d = a1 * b2 - a2 * b1;
    x = p[a].x + (c1*b2 - c2*b1)/d,y = p[a].y + (a1*c2 - a2*c1)/d;
    r  = dis2(a);
}
#include
typedef long long ll;
using namespace std;
const int N=1e5+5;
double x,y,r;
int n;
struct node
{
    double x,y;
}p[N];

double dis(int p1,int p2)
{
    return sqrt((p[p1].x-p[p2].x)*(p[p1].x-p[p2].x)+(p[p1].y-p[p2].y)*(p[p1].y-p[p2].y));
}

double dis2(int a)
{
    return sqrt((p[a].x-x)*(p[a].x-x)+(p[a].y-y)*(p[a].y-y));
}

void cal(int a,int b,int c)//求外心
{
    double a1 = p[b].x - p[a].x, b1 = p[b].y - p[a].y, c1 = (a1*a1 + b1*b1)/2;
    double a2 = p[c].x - p[a].x, b2 = p[c].y - p[a].y, c2 = (a2*a2 + b2*b2)/2;
    double d = a1 * b2 - a2 * b1;
    x = p[a].x + (c1*b2 - c2*b1)/d,y = p[a].y + (a1*c2 - a2*c1)/d;
    r  = dis2(a);
}

bool check(int p1,int p2,int p3)
{
    cal(p1,p2,p3);
    int cnt=0;
    for(int i=0;i<n;i++)
    {
        if(fabs(dis2(i)-r)<1e-8)
        {
            cnt++;
        }
    }
    if(2*cnt>=n)
    {
        return 1;
    }
    return 0;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        if(n==1||n==2)
        {
            printf("%.6f %.6f %.6f\n",p[0].x,p[0].y-1,1.0);
            continue;
        }
        else if(n<=4)
        {
            double x1=p[0].x+p[1].x,y1=p[0].y+p[1].y;
            double r=dis(0,1);
            printf("%.6f %.6f %.6f\n",x1/2,y1/2,r/2);
            continue;
        }
        while(1)
        {
            int p1=rand()%n,p2=rand()%n,p3=rand()%n;
            if(p1==p2||p2==p3||p1==p3)
                continue;
            int flag=check(p1,p2,p3);
            if(flag)
            {
                printf("%.6f %.6f %.6f\n",x,y,r);
                break;
            }
        }
    }
    return 0;
}

你可能感兴趣的:(基础计算几何)