Description
给定二维平面上的 (n) 个点,求一个过原点的圆,使得圆周经过的给定点的数目最大。(n le 2000)
Solution
标答的做法:
同弧所对的圆周角相等
枚举所有点 (P),设 (OP) 为一条弦,此时若枚举另一点 (A),则可确定一圆
当确定 (OP) 后,圆的唯一自由量可以视作半径,而 (OP) 在同样半径的圆上对应的圆周角相等
因此我们可以对剩下所有点 (A) 计算出圆周角 (angle OAP),取众数即可
考虑到一个角度会有对称的两个 (A) 与其对应,因此我们强行约束 (OA imes OP >0)
其实这样误差可能比较大,标程用了分数类之类的操作,比较麻烦
我们考虑直接用三点共圆坐标公式解决问题,总体思路和上面的方法相同,不过是把角度换成圆心坐标罢了
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005;
struct point
{
double x,y;
double operator * (const point &b)
{
return x*b.y-y*b.x;
}
double len2()
{
return x*x+y*y;
}
bool operator < (const point &b) const
{
return x==b.x?y<b.y:x<b.x;
}
} p[N];
int n,ans;
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y;
for(int i=1;i<=n;i++)
{
map<point,int> mp;
for(int j=i+1;j<=n;j++)
{
double d=p[i]*p[j],d1=p[i].len2(),d2=p[j].len2();
if(fabs(d)<1e-6) continue;
double x=(p[i].y*d2-p[j].y*d1)/d, y=(p[i].x*d2-p[j].x*d1)/d;
ans=max(ans,++mp[{x,y}]);
}
}
cout<<ans+1<<endl;
}