1. 程式人生 > 實用技巧 >牛客多校第二場 B Boundary

牛客多校第二場 B Boundary

牛客多校第二場 B

連結:https://ac.nowcoder.com/acm/contest/5667/B

題目描述

Given \(n\) points in 2D plane. Considering all circles that the origin point \((0, 0)\) is on their boundries, find the one with the maximum given points on its boundry. Print the maximum number of points.

輸入描述:

The first line contains one integer \(n~(1 \leq n \leq 2000)\)

, denoting the number of given points.
Following \(n\) lines each contains two integers \(x, y~(|x|,|y| \leq 10000)\), denoting a given point \((x, y)\).
It's guaranteed that the points are pairwise different and no given point is the origin point.

輸出描述:

Only one line containing one integer, denoting the answer.

輸入

4
1 1
0 2
2 0
2 2

輸出

3

說明

Considering circle \((x-1)^2+(y-1)^2=2\), we can see that the origin point is on its boundry and that there are \(3\) given points \({(0,2),(2,0),(2,2)}\) on its boundry.

題解

題意

在一個二維平面中,給 \(n\) 個點,以 \((x,y)\) 為圓心的圓經過 \((0,0)\) 點,問,這個圓在這 \(n\) 個點中最多能經過多少個點。

思路

對於兩個不同的點 \((a_i,b_i)\)

\((a_j,b_j)\) ,還有額外加的一個 \((0,0)\) 點在三點不共線的條件下,一定可以確定一個圓,並且可以求出圓心,

\[(x-a_i)^2+(y-b_i)^2=x^2+y^2 \\ (x-a_j)^2+(y-b_j)^2=x^2+y^2 \\ (x-a_i)^2+(y-b_i)^2=(x-a_j)^2+(y-b_j)^2 \]

化簡式子,可以得到一個關於 $x,y $ 的方程組

\[y=a_j(a_i^2+b_i^2)-a_i(a_j^2+b_j^2)/(2(b_ia_j-a_ib_j)) \\ y=b_j(a_i^2+b_i^2)-b_i(a_j^2+b_j^2)/(2(b_ia_j-a_ib_j)) \]

之後進行求解儲存資料即可。

注意

  • \(map\) 會卡 \(tle\)
  • 卡精度,能不使用 \(double\) 儘量不要使用 \(double\)
  • 當三點共線時,不進行考慮

程式碼

#pragma GCC optimize(3)
#include <cmath>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e3+55;
const double eps = 1e-7;
struct Point{double x,y;};
bool cmp(Point x,Point y){if(eps>fabs(x.x-y.x))return x.y<y.y;return x.x<y.x;}
struct node{ll a,b;ll aa,bb;}nn[maxn];
vector<Point>v;
int main(){
    int n;
    int maxxx=0;
    scanf("%d",&n);
    if(n==1){printf("1\n");return 0;}
    for(int i=0;i<n;++i){
        v.clear();
        scanf("%lld%lld",&nn[i].a,&nn[i].b);
        nn[i].aa=nn[i].a*nn[i].a;
        nn[i].bb=nn[i].b*nn[i].b;
        for(int j=0;j<i;++j){
            if(nn[i].b*nn[j].a==nn[j].b*nn[i].a)continue;
            ll yx=nn[j].a*(nn[i].aa+nn[i].bb)-nn[i].a*(nn[j].aa+nn[j].bb);
            ll yy=(ll)2*(nn[i].b*nn[j].a-nn[j].b*nn[i].a);
            ll xx=nn[j].b*(nn[i].aa+nn[i].bb)-nn[i].b*(nn[j].aa+nn[j].bb);
            ll xy=-yy;
            v.push_back({(double)xx/xy,(double)yx/yy});
        }
        int maxx=0,ans=1;
        sort(v.begin(),v.end(),cmp);
        for(int j=1;j<(int)v.size();++j){
            if(fabs(v[j].y-v[j-1].y)<eps&&fabs(v[j].x-v[j-1].x)<eps)ans++;
            else ans=1;
            maxx=max(maxx,ans);
        }
        maxxx=max(maxxx,maxx+1);
    }
    printf("%d\n",maxxx);
    return 0;
}