极角排序,扫描线。
以每个点为圆心,画半径为r的圆,求最多覆盖的区间。
注意三角函数atan2很慢,尽量不要使用
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-12
#define Pi acos(-1.0)
#define N 10050
#define M 200020
#define PB push_back
#define MP make_pair
#define fi first
#define se second
int dcmp(double x){
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct point{
double x, y;
point(double x = 0, double y = 0) : x(x), y(y) {}
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);
}
bool operator == (const point &b) const {
return dcmp(x - b.x) == 0 && dcmp(y - b.y) == 0;
}
double ang(){
return atan2(y, x);
}
double len(){
return sqrt(x * x + y * y);
}
};
struct node{
int in;
double ang;
node(double ang = 0, int in = 0) : ang(ang), in(in) {}
bool operator < (const node &b) const {
return dcmp(ang - b.ang) < 0 || (dcmp(ang - b.ang) == 0 && in > b.in);
}
};
int circle_cross(point a, double ra, point b, double rb, double &ang1, double &ang2){
double d = (a - b).len();
if(dcmp(d - ra - rb) > 0) return 0; //xiangli
if(dcmp(fabs(ra - rb) - d) >= 0){
if(dcmp(ra - rb) >= 0) return 0;
else return -1;
}
double da = (ra * ra + d * d - rb * rb) / (2 * ra * d);
double aa = atan2((b - a).y, (b - a).x);
double rad = acos(da);
ang1 = aa - rad, ang2 = aa + rad;
return 1;
}
bool point_in_circle(point p, point o, double r){
double d = (p - o).len();
return dcmp(d - r) <= 0;
}
point p[N];
int n, cnt;
double r;
node t[N];
int main(){
scanf("%d%lf", &n, &r);
for(int i = 1; i <= n; ++i){
scanf("%lf%lf", &p[i].x, &p[i].y);
}
int ans = 1;
for(int i = 1; i <= n; ++i){
cnt = 0;
int tot = 1;
for(int j = 1; j <= n; ++j){
if(i == j) continue;
if(p[i] == p[j]){
++tot; continue;
}
double ang1, ang2;
int ok = circle_cross(p[i], r, p[j], r, ang1, ang2);
if(ok == 1){
if(ang1 > ang2) swap(ang1, ang2);
double md = (ang1 + ang2) / 2;
point tmp = p[i] + point(r * cos(md), r * sin(md));
if(point_in_circle(tmp, p[j], r)){
t[cnt++] = node(ang1, 1);
t[cnt++] = node(ang2, -1);
}
else{
t[cnt++] = node(-Pi, 1);
t[cnt++] = node(ang1, -1);
t[cnt++] = node(ang2, 1);
t[cnt++] = node(Pi, -1);
}
}
}
sort(t, t + cnt);
int cur = 0, mx = tot;
for(int i = 0; i < cnt; ++i){
cur += t[i].in;
mx = max(mx, cur + tot);
}
ans = max(ans, mx);
}
printf("%d\n", ans);
return 0;
}