题面:
题意:
给定n个点,对于一个过原点的圆,求出最多能经过多少个点。
官方题解:
我的题解:
两维枚举 i,j ,对于一个固定的 i 来说,看看后面有多少个点是共圆的。
不在一条直线上的三点可以确定一个圆。
( 0 , 0 ),p [ i ] , p [ j ] 即可确定一个圆,只需要记录这个圆的圆心即可(因为(0,0)点已经确定,一个圆心唯一确定一条半径)
剩下的就是板子啦。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=2100;
const int maxm=100100;
const int up=100000;
//浮点型数值是否为0
int sgn(double x)
{
if(abs(x)<eps) return 0;
if(x<0) return -1;
return 1;
}
//返回x的平方
double sqr(double x)
{
return x*x;
}
//二维点
struct Point
{
double x,y;
Point(){}
Point(double xx,double yy)
{
x=xx,y=yy;
}
//输入输出
void input(void)
{
scanf("%lf%lf",&x,&y);
}
void output(void)
{
printf("%.2f %.2f\n",x,y);
}
//重载比较运算符
bool operator == (const Point &b) const
{
return sgn(x-b.x)==0&&sgn(y-b.y)==0;
}
bool operator < (const Point &b) const
{
if(sgn(x-b.x)!=0) return x<b.x;
else return sgn(y-b.y)<0;
}
//重载加减乘除
Point operator + (const Point &b) const
{
return Point(x+b.x,y+b.y);
}
Point operator - (const Point &b) const
{
return Point(x-b.x,y-b.y);
}
Point operator * (const double &k) const
{
return Point(x*k,y*k);
}
Point operator / (const double &k) const
{
return Point(x/k,y/k);
}
//叉乘,叉积
double operator ^ (const Point &b) const
{
return x*b.y-y*b.x;
}
//点乘,点积
double operator * (const Point &b) const
{
return x*b.x+y*b.y;
}
//两点距离
double dis(const Point &b) const
{
return hypot(x-b.x,y-b.y);
}
//逆时针转90
Point turn_left(void)
{
return Point(-y,x);
}
};
//****************************************************************
//****************************************************************
struct Line
{
Point s,e;
Line(){}
//两点
Line(const Point ss,const Point ee)
{
s=ss,e=ee;
}
//点和直线的关系
//1 在左侧 (在s——>e的逆时针侧)
//2 在右侧 (在s——>e的顺时针侧)
//3 在直线上
int relation(const Point &p)
{
int c=sgn((p-s)^(e-s));
if(c<0) return 1;
else if(c>0) return 2;
else return 3;
}
//求两直线的交点
//要保证两直线不平行或重合
Point cross_point(Line v)
{
double a1=(v.e-v.s)^(s-v.s);
double a2=(v.e-v.s)^(e-v.s);
return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
}
};
struct circle
{
Point p;
double r;
circle(){}
circle(double xx,double yy,double rr)
{
p=Point(xx,yy);
r=rr;
}
//三角形外接圆
//利用两条边的中垂线得到圆心
circle(Point a,Point b,Point c)
{
Line u=Line((a+b)/2,((a+b)/2)+((b-a).turn_left()));
Line v=Line((b+c)/2,((b+c)/2)+((c-b).turn_left()));
p=u.cross_point(v);
r=p.dis(a);
}
};
Point p[maxn];
Point zero=Point(0.0,0.0);
map<Point,int>mp;
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
p[i].input();
int ans=1;
circle now;
for(int i=1;i<=n;i++)
{
mp.clear();
for(int j=i+1;j<=n;j++)
{
if(Line(p[i],p[j]).relation(zero)==3) continue;
now=circle(p[i],p[j],zero);
mp[now.p]++;
ans=max(ans,mp[now.p]+1);
}
}
printf("%d\n",ans);
return 0;
}