POJ - 3335 旋转计分板nlog n

来源:互联网 发布:阿里云身份证识别api 编辑:程序博客网 时间:2024/05/10 06:51

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

判断一个多边形内核是否存在。


先搞一下顺时针和逆时针,统统改为逆时针,然后求一下半平面交,这里onleft要用《=,我调了很久也没看出个所以然,然而不用《=就挂了。

跪求路过的神犇解释一下~


#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>#define eps 1e-10using 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;}


0 0