给出平面中的一些点,然后给你一个圆(给出圆心坐标,半径),问若将这个圆划分为半圆,最多能容纳多少点。(点在半圆边上也算)
方法,预处理,将不再圆内的点排除。
对于圆内的点,枚举向量(点到圆心)设为向量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 ;
}
本文介绍了一种解决平面中给定若干点后,通过一个给定圆心和半径的圆划分出的最大半圆能包含多少点的问题。通过预处理排除圆外点,利用向量叉乘判断点的位置,并取最大值。
9854

被折叠的 条评论
为什么被折叠?



