叉積求點在直線的一側 poj 1106

傳送門

題目大意,讓我們從源點,半徑爲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;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章