POJ 3335 半平面交模板
阿新 • • 發佈:2020-08-05
題意
以順時針或逆時針順序給定一個多邊形,問該多邊形是否有核
解法
半平面交要求邊要按逆時針順序,首先利用叉積判斷給定點順序為逆時針還是順時針,然後按逆時針方向建邊,最後跑半平面交演算法。
程式碼:
#include <map> #include <set> #include <cmath> #include <ctime> #include <queue> #include <stack> #include <string> #include <vector> #include <cctype> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; const int maxn=1e3+5; const double eps = 1e-8; int sgn(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; return 1; } struct Point { double x,y; Point() {} Point(double _x,double _y) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } double operator ^(const Point &b)const { return x*b.y - y*b.x; } double operator *(const Point &b)const { return x*b.x + y*b.y; } Point Rotate(double rad){ //逆時針旋轉 return Point(x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)); } double angle(){ return atan2(y,x); } double len(){ return sqrt(x*x+y*y); } }; double xmult(Point p0,Point p1,Point p2) { //p0p1 X p0p2 return (p1-p0)^(p2-p0); } double getArea(Point a,Point b,Point c){ return fabs(xmult(a,b,c))/2.0; } struct Line { Point s,t; double ang; Line(Point X=Point(),Point Y=Point()) { s=X,t=Y,ang=(Y-X).angle(); } double getangle(){ return ang=(t-s).angle(); } }; Point getIntersectPoint(Line a, Line b) { double a1 = a.s.y - a.t.y, b1 = a.t.x - a.s.x, c1 = a.s.x * a.t.y - a.t.x * a.s.y; double a2 = b.s.y - b.t.y, b2 = b.t.x - b.s.x, c2 = b.s.x * b.t.y - b.t.x * b.s.y; return Point((c1*b2-c2*b1)/(a2*b1-a1*b2), (a2*c1-a1*c2)/(a1*b2-a2*b1)); } Point p[maxn];//存頂點 Line l[maxn];//存逆時針方向的邊 Line que[maxn];//存半平面交 bool judge(int n){//判斷是否是逆時針的 double ans=0; for(int i=1;i<=n-1;i++){ ans+=xmult(p[0],p[i],p[i+1]); } return ans>0; } bool onRight(Line a,Line b,Line c){ Point jiao=getIntersectPoint(b,c); if(xmult(a.s,a.t,jiao)<0){ return 1; } else{ return 0; } } bool cmp(Line a,Line b){ double A=a.getangle(),B=b.getangle(); if(sgn(A-B)==0){//平行的直線將最左邊的放後面,便於去重 return xmult(a.s,a.t,b.t)>=0; } else{ return A<B; } } bool halfPlaneIntersect(int n){ sort(l+1,l+1+n,cmp); int left=1,right=0,cnt=0; for(int i=1;i<n;i++){ if(sgn(l[i].getangle()-l[i+1].getangle())==0){ continue; } l[++cnt]=l[i]; } l[++cnt]=l[n]; for(int i=1;i<=cnt;i++){ while(right-left+1>=2&&onRight(l[i],que[right],que[right-1])) right--; while(right-left+1>=2&&onRight(l[i],que[left],que[left+1])) left++; que[++right]=l[i]; } while(right-left+1>=3&&onRight(que[left],que[right],que[right-1])) right--; while(right-left+1>=3&&onRight(que[right],que[left],que[left+1])) left++; if(right-left+1>=3){ return 1; } else{ return 0; } } int main () { int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf",&p[i].x,&p[i].y); } if(judge(n)){//已經是逆時針 for(int i=1;i<=n;i++){ l[i]=Line(p[i],p[i%n+1]); } } else{//是順時針 for(int i=1;i<=n;i++){ l[i]=Line(p[i%n+1],p[i]); } } if(halfPlaneIntersect(n)){ puts("YES"); } else{ puts("NO"); } } }