您的位置:首页 > 其它

poj 1106 Transmitters

2015-05-29 21:49 253 查看
题意:给定一个点的坐标和一个圆半径,一个整数n,然后n个点坐标,求以给定点所在半圆能包含的最多点的个数;

思路:枚举半圆直径边界,统计该边界一侧的包含点数,更新最大值;

技巧:使用叉积,能方便的判断两向量的夹角是否小于180度;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double epsi=1e-10;
const double pi=acos(-1.0);
const int maxn=50005;
struct point{
double x,y;
point(double xx=0,double yy=0):x(xx),y(yy){}
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;
}
};
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));
}
int n;
point p[maxn],cp;
double r;
int main(){
while(scanf("%lf%lf%lf",&cp.x,&cp.y,&r)&&r>=0){
scanf("%d",&n);
int ans=0;
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],cp)-r)!=1)  //距离小于半径且在边界同一侧
if(sign(mul(cp,p[i],p[j]))!=-1) tmp++;
ans=max(ans,tmp);
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: