题目大意,让我们从源点,半径为r,可任意旋转的半圆中最多能包含多少个点。
发射台为p0,以p0为轴心,可向任意方向旋转,所以我们将任一点pi与p0间的直线都作为半圆的下边界,再枚举所有点,则位于半圆区域内的点pj满足以下两个条件。
1:pj实以p0pi为下边界半圆的一侧,即p0pi^p0pj >=0;
2: pj与p0的距离不大于半径
给出ac代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
const double epsi = 1e-10;
const double pi = acos(-1.0);
const int maxn = 50005;
struct point{
double x,y;
point(){};
point(double x,double y) :x(x),y(y){};
// point(double x=0,double y=0): x(x),y(y){}
point operator - (const point &op2) const{
return point(x-op2.x,y-op2.y);
}
double operator ^ (const point &op2)const{ //叉积
return x*op2.y - y*op2.x;
}
}p[maxn];
inline int sign(const double &x){ //判断符号
if(x>epsi) return 1;
if(x < -epsi) return -1;
return 0;
}
inline double sqr(const double &x){
return x*x;
}
inline double mul(const point &p0,const point &p1,const point &p2){ //求 p0p1与p0p2的叉积
return (p1-p0) ^ (p2-p0);
}
inline double dis2(const point &p0,const point &p1){// |p0p1|的平方
return sqr(p0.x-p1.x)+sqr(p0.y-p1.y);
}
inline double dis(const point &p0,const point &p1){// |p0p1|
return sqrt(dis2(p0,p1));
}
point s;
double r;
int n;
int main(){
while(~scanf("%lf%lf%lf",&s.x,&s.y,&r) && r >= 0){
scanf("%d",&n);
int ans = -1e9;
for(int i = 0;i < n;i ++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for(int i=0;i < n;i ++){
int tmp = 0;
for(int j = 0; j < n; j++){
if(sign(dis(p[j],s)-r)!=1)
if(sign(mul(s,p[i],p[j]))!=-1) tmp++;
}
ans = std::max(ans,tmp);
}
printf("%d\n",ans);
}
return 0;
}