POJ - 3335 旋轉計分板nlog n

http://poj.org/problem?id=3335

判斷一個多邊形內核是否存在。


先搞一下順時針和逆時針,統統改爲逆時針,然後求一下半平面交,這裏onleft要用《=,我調了很久也沒看出個所以然,然而不用《=就掛了。

跪求路過的神犇解釋一下~


#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
#define eps 1e-10
using namespace std;
const int maxn=111;
int dcmp(double x)
{
	if(fabs(x)<eps)return 0;
	else return x<0?-1:1;
}
struct point
{
	double x,y;
	point(){}
	point(double _x,double _y){x=_x;y=_y;}
	point operator +(const point &b){return point(x+b.x,y+b.y);}
	point operator -(const point &b){return point(x-b.x,y-b.y);}
	point operator *(const double &b){return point(x*b,y*b);}
};
struct line
{
	point p,v;
	double ang;
	line(){}
	line(point _p,point _v){p=_p;v=_v;ang=atan2(v.y,v.x);}
	bool operator <(const line &l)const
	{
		return ang<l.ang;
	}
};
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;}
bool onleft(line l,point p){return dcmp(cross(l.v,p-l.p))>=0;}
point getsec(point p1,point v1,point p2,point v2)
{
	double x=cross(p2-p1,v2)/cross(v1,v2);
	return v1*x+p1;
}
bool sec(point a,point b,point c,point d)
{
	if(min(a.x,b.x)<=max(c.x,d.x)&&min(c.x,d.x)<=max(a.x,b.x)&&min(a.y,b.y)<=max(c.y,d.y)&&min(c.y,d.y)<=max(a.y,b.y))
	{
		double c1=cross(b-a,c-a),c2=cross(b-a,d-a);
		double c3=cross(d-c,a-c),c4=cross(d-c,b-c);
		return dcmp(c1)*dcmp(c2)<=0&&dcmp(c3)*dcmp(c4)<=0;
	}
}
int hp(line *L,int n)
{
	sort(L+1,L+n+1);
	point *p=new point[n];
	line *q=new line[n];
	int first,last;
	q[first=last=0]=L[1];
	for(int i=2;i<=n;i++)
	{
		while(first<last&&!onleft(L[i],p[last-1]))last--;
		while(first<last&&!onleft(L[i],p[first]))first++;
		q[++last]=L[i];
		if(dcmp(cross(q[last].v,q[last-1].v))==0)
		{
			last--;
			if(onleft(q[last],L[i].p))q[last]=L[i];
		}
		if(first<last)p[last-1]=getsec(q[last].p,q[last].v,q[last-1].p,q[last-1].v);
	}
	while(first<last&&!onleft(q[first],p[last-1]))last--;
	if(last-first<=1)return 0;
	p[last]=getsec(q[first].p,q[first].v,q[last].p,q[last].v);
	int m=0;
	for(int i=first;i<=last;i++)m++;
	return m;
}
int n;
point t[maxn];
line l[maxn];
void init()
{
	double sum=0;
	t[n+1]=t[1];
	for(int i=1;i<=n;i++)sum+=cross(t[i]-t[1],t[i+1]-t[1]);
	if(sum>0)
	{
	    for(int i=1;i<=n;i++)l[i]=line(t[i],t[i+1]-t[i]);
	}
	else
	{
		for(int i=1;i<=n;i++)l[i]=line(t[i],t[i]-t[i+1]);
	}
}
int main()
{
    int T;	
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%lf%lf",&t[i].x,&t[i].y);
		init();	
		if(hp(l,n))printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}


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