给出平面中的一些点,然后给你一个圆(给出圆心坐标,半径),问若将这个圆划分为半圆,最多能容纳多少点。(点在半圆边上也算)
方法,预处理,将不再圆内的点排除。
对于圆内的点,枚举向量(点到圆心)设为向量a,然后枚举其他的点与圆心的向量,设为向量b,如果 a b 的叉乘大于0,说明在这条线的左边,如果小于0则在右边。如果差乘等于0,说明既可以在左边,也可以在右边,然后取最大值即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include <algorithm>
#include<vector>
using namespace std;
const double eps = 1e-10;
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){}
bool operator <(const Point& b)const{
return x < b.x || (x == b.x && y < b.y);
}
bool operator == (const Point &b)const {
return dcmp(x - b.x) == 0&& dcmp(y - b.y) == 0;
}
};
typedef Point Vector ;
// 求向量 (x,y)的极角,atan2(y,x); -- C标准库
Vector operator + (Vector A,Vector B){
return Vector(A.x + B.x , A.y + B.y);
}
Vector operator - (Vector A,Vector B){
return Vector(A.x - B.x , A.y - B.y);
}
Vector operator * (Vector A,double p){
return Vector(A.x*p , A.y*p);
}
Vector operator / (Vector A,double p){
return Vector(A.x/p , A.y/p);
}
/*
bool operator < (const Point&a , const Point&b){
}
*/
double Dot(Point A,Point B) {return A.x*B.x+A.y*B.y;} //点积
double Cross(Point A,Point B) {return A.x*B.y-A.y*B.x;} //叉积
double Length(Vector A){ return sqrt(Dot(A,A));} //求向量长度
double Angle(Vector A,Vector B){ return acos(Dot(A,B) / Length(A) / Length(B)); } //求出cos ,再用acos求出角度、
double Area2(Point A,Point B,Point C){ return Cross(B-A,C-A);}
//向量旋转 公式 x' = x * cosa - y * sina, y' = x * sina + y * cosa;
Vector Rotate(Vector A,double rad){ return Vector(A.x * cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y * cos(rad));}
//计算向量的 单位 法线。
Vector Normal(Vector A){double L = Length(A); return Vector(-A.y / L , A.x /L); }
//计算交点, 调用前确保 Cross(v,w) 非0
//设 直线分别为 P + tv 和 Q + tw;
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){
Vector u = P-Q;
double t = Cross( w , u) / Cross( v , w );
return P + v * t;
}
//点到直线距离
double DistanceToLine(Point P, Point A,Point B){ //叉积 除以 底
Vector v1 = B - A, v2 = P - A;
return fabs(Cross(v1,v2)) / Length(v1); //不取绝对值,则为有向距离
}
//点到线段的距离
double DistanceToSegment(Point P, Point A, Point B){
if(A == B) return Length(P - A) ; // AB重合,成点对点长度
Vector v1 = B - A, v2 = P - A, v3 = P - B;
if(dcmp(Dot(v1,v2)) < 0) return Length(v2); // == 0 的时候是垂直的,小于零在二三象限; 即离A近;
else if(dcmp(Dot(v1,v2)) > 0) return Length(v3); //大于零 一四象限。
else return fabs(Cross(v1,v2)) / Length(v1); // 垂直的情况,直接用叉积来求了。
}
Point GetLineProjection(Point P,Point A,Point B){ //获得P在线段AB上投影的节点。
// AB向量 A + tv , Q 即投影点 A + t0v ,
// PQ 垂直于AB ,Dot()应该为0. 所以 Dot(v , P - (A + t0v))'
// 分配率 Dot(v , P - A) - t0 * Dot(v,v) = 0;
Vector v = B - A;
return A + v * (Dot(v , P - A) / Dot(v,v));
}
//判断线段相交
// 规范相交 : 两线段恰好有一个公共点。且不在端点。
// 充要条件: 每条线段两个端点都在另一条线段的两侧。(叉积符号不同)
bool SegmentProperIntersection(Point a1, Point a2,Point b1,Point b2){
double c1 = Cross(a2-a1 , b1 -a1) , c2 = Cross(a2-a1 , b2 -a1) ;
double c3 = Cross(b2-b1 , a1 -b1) , c4 = Cross(b2-b1 , a2 -b1) ;
return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0 ;
}
//判断一个点是否在线段上(不包括端点)
bool OnSegment(Point p , Point a1, Point a2){ //不算端点
//前一个判断是否共线,如果共线且点积相反,说明在线段上
return dcmp(Cross(a1 - p , a2 - p)) == 0 && dcmp(Dot(a1 - p,a2 - p)) < 0 ;
}
Point getD(Point A, Point B, Point C){ // A B C 逆时针给出
Vector v1 = C - B;
double a1 = Angle(A - B , v1);
v1 = Rotate(v1, a1 / 3);
Vector v2 = B - C;
double a2 = Angle(A-C,v2);
v2 = Rotate(v2 , -a2 / 3);
return GetLineIntersection(B,v1,C,v2);
}
Point read_Point(){
Point tmp;
scanf("%lf%lf",&tmp.x,&tmp.y);
return tmp;
}
vector<Point> G;
int main(){
Point po[1010];
Point middle ;double r;
while(scanf("%lf%lf%lf",&middle.x,&middle.y,&r)!=EOF ){
if(r < 0) break;
int n;scanf("%d",&n);
int l = 0;
for(int i=0;i<n;i++){ //预处理
Point tmp = read_Point();
if(Length(tmp - middle) > r ) continue;
else
po[l++] = tmp;
}
int maxx = 0;
for(int i=0;i<l;i++){
int ansl = 0;
int ansr = 0;
for(int j=0;j<l;j++){
if(i == j) continue;
int tmp = dcmp(Cross(middle - po[i],middle - po[j]));
if( tmp > 0)
ansl++;
else if(tmp < 0)
ansr++;
else{
ansl ++; ansr++;
}
}
ansl++; ansr++; //算上本身
maxx = max(max(ansl,ansr),maxx);
}
printf("%d\n",maxx);
}
return 0 ;
}