【凸包+判断直线是否与凸包相交】 POJ 1912

你~需要我的帮助吗

【题目大意】给出平面上的 n 个点,对于 m 条直线,依次判断这 n 个点是否在每条直线的同一侧。(n,m≤1e5)

【思路】首先对于n个点,求出凸包。然后对于一个直线l,判断它是否与凸包香蕉:作两条与l平行的直线,把凸包卡住。看两个切点的连线是否与直线有交点。没有交点就符合要求,有交点就不行。我们只需要判一下这两个切点是否在这条直线的同一侧就行了。大概就是取直线上的一个顶点A,把A到两个切点的向量搞出来,再叉积一下,看结果是否大于0,若大于0,在同侧,否则在异侧。

【自己写的时候发现的错误】:

puts后面不要加\n。。。。。。

中间输出变量忘注释了,一直Output Limit Exceeded。。。

n=1的时候凸包居然炸了【不知道为什么。。。】

特判一下,n<=1时跳过求凸包过程输出GOOD就行了【应该不会有点在直线上吧?】
 

【凸包+判断直线是否与凸包相交】 POJ 1912_第1张图片左图为香蕉的情况。

 

【凸包+判断直线是否与凸包相交】 POJ 1912_第2张图片左图为相离的情况。

 

由于凸包上的线段,它们的斜率是单调的,所以可以二分。

只要找到第一个与正向直线夹角大于0的线段和第一个与反向直线夹角大于0的线段。

atan2返回的是弧度【注意一下参数前面是y后面是x】。

保证角度的单调性,凸包第一个点设成y最大的点。

可以用  ×180/pi  转成角度,然后输出一下中间的参数来辅助理解或检查程序。

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn=5e5;
const double eps=1e-8;
const double pi=3.14159265358979323846;
struct point{
	double x,y;
	point(double _x=0,double _y=0){
		x=_x;
		y=_y;
	}
	friend inline point operator +(const point &a,const point &b){
		return point(a.x+b.x,a.y+b.y);
	}
	friend inline point operator -(const point &a,const point &b){
		return point(a.x-b.x,a.y-b.y);
	}
	friend inline double operator *(const point &a,const point &b){
		return a.x*b.y-a.y*b.x;
	}
}st[maxn],p[maxn],A,B;
int top=0,n,id=1;
double ang[maxn];
double dist(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(const point &a,const point &b){
	double K=(a-p[1])*(b-p[1]);
	return (K==0)?(dist(a,p[1])<=dist(b,p[1])):K>0;  //极角按逆时针排序 
}

//求凸包的板子。
void Graham(){
	sort(p+2,p+n+1,cmp);
	st[++top]=p[1];
	for(int i=2;i<=n;++i){
		while(top>=3&&((p[i]-st[top-1])*(st[top]-st[top-1])>=0))
			top--;
		st[++top]=p[i];
	}
	st[top+1]=st[1];
}

void solve(){
	swap(p[id],p[1]);
        Graham();
	for(int i=1;i<=top;++i){
//		cout<p[id].y)||((p[i].y==p[id].y)&&(p[i].x1) solve();
	while(scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y)!=EOF){
		if(n==1){
			printf("GOOD\n");
			continue;
		}
		double ANG1=atan2(A.y-B.y,A.x-B.x);//*180/pi;
		double ANG2=atan2(B.y-A.y,B.x-A.x);//*180/pi;
        //取两次角度分别对应卡住凸包的两条平行线的角度。【一条正着一条反着】
//		cout<

 

你可能感兴趣的:(【凸包+判断直线是否与凸包相交】 POJ 1912)