给出一些点坐标,问有一个半径为1的圆,一次最多能圈多小个点。
应该很容易想的到,枚举任意两个点,把圆心确定下来(本题关键!!),然后遍历所有点,统计在该圆内的点的个数。其中最大值就是答案。。。。。
const double eps = 1e-8 ;
double sig(double x){
if(fabs(x) < eps) return 0 ;
return x > 0 ? 1 : -1 ;
}
double add(double x , double y){
if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;
return x + y ;
}
struct Point{
double x , y ;
Point(){}
Point(double _x , double _y):x(_x),y(_y){}
Point operator + (Point o){
return Point(add(x , o.x) , add(y , o.y)) ;
}
Point operator - (Point o){
return Point(add(x , -o.x) , add(y , -o.y)) ;
}
Point operator * (double o){
return Point(x*o , y*o) ;
}
double operator ^(Point o){
return add(x*o.y , -y*o.x) ;
}
double dist(Point o){
return sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y)) ;
}
double dist2(Point o){
return (x-o.x)*(x-o.x) + (y-o.y)*(y-o.y) ;
}
void read(){
scanf("%lf%lf" ,&x , &y) ;
}
};
//过a ,b2点确定单位圆圆心
Point centerpoint(Point a , Point b){
Point ox = (a + b) * 0.5 ;
double dy = b.y - a.y ;
double dx = b.x - a.x ;
double r = ox.dist2(a) ;
r = sqrt(1.0 - r) ;
if(fabs(dy) < 1e-6){
ox.y += r ;
}
else{
double k = -dx / dy ;
double sita = atan(k) ;
ox.x += r * cos(sita) ;
ox.y += r * sin(sita) ;
}
return ox ;
}
Point po[308] ;
int main(){
int i , j , t , n , s , k , sum ;
cin>>t ;
while(t--){
cin>>n ;
for(i = 1 ; i <= n ; i++) po[i].read() ;
s = 1 ;
for(i = 1 ; i <= n ; i++){
for(j = 1 ; j < i ; j++){
double d = po[i].dist2(po[j]) ;
if(d > 4.0) continue ;
Point cent = centerpoint(po[i] , po[j]) ;
sum = 0 ;
for(k = 1 ; k <= n ; k++){
double r = cent.dist(po[k]) ;
if(r <= 1.0001) sum++ ;
}
s = max(s , sum) ;
}
}
printf("%d\n" , s) ;
}
return 0 ;
}