1298:Separate Points
n個の黒い点とm個の白い点が与えられる。
黒い点と白い点を1本の直線でわけることが
できるかどうかを判定する問題。
黒い点と白い点をそれぞれを凸包してから
2つの多角形が交差するかどうか判定した。
#include<cmath> #include<algorithm> #include<iostream> #include<vector> #include<climits> #include<cfloat> #define next(P, i) P[(i+1) % P.size()] using namespace std; double EPS = 1e-10; double add(double a, double b){ if(abs(a+b) < EPS * (abs(a)+abs(b)))return 0; return a+b; } struct point{ double x, y; point(){} point(double x,double y) : x(x) , y(y){} point operator - (point p){ return point(add(x,-p.x), add(y,-p.y)); } }; bool cmp_x(const point& p, const point& q){ if(p.x != q.x)return p.x<q.x; return p.y < q.y; } 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); } int is_point_on_line(point a, point b, point c) { return cross(b-a, c-a)==0.0 && (dot(b-a, c-a) > -EPS) && (dot(a-b, c-b) > -EPS); } int is_intersected_ls(point a1, point a2, point b1, point b2) { if(cross(a1-a2,b1-b2)==0){ return is_point_on_line(a1,a2,b1) || is_point_on_line(a1,a2,b2) || is_point_on_line(b1,b2,a1) || is_point_on_line(b1,b2,a2); } else { return ( cross(a2-a1, b1-a1) * cross(a2-a1, b2-a1) < EPS ) && ( cross(b2-b1, a1-b1) * cross(b2-b1, a2-b1) < EPS ); } } int contain(point p, vector<point> ps){ point a(p.x,p.y),b(1000000,p.y); double ymx=-DBL_MAX,ymn=DBL_MAX; for(int i=0;i<ps.size();i++){ ymx=max(ymx,ps[i].y); ymn=min(ymn,ps[i].y); } if(a.y<=ymn||a.y>=ymx)return 0; int cnt1=0; for(int i=0;i<ps.size();i++) if(is_point_on_line(a,b,ps[i]))cnt1++; int cnt=0; for(int i=0;i<ps.size();i++) if(is_intersected_ls(ps[i],next(ps,i),a,b))cnt++; return (cnt-cnt1)%2; } int crossPol(vector<point> pol1, vector<point> pol2){ for(int i=0;i<pol1.size();i++) if(contain(pol1[i],pol2))return 1; for(int i=0;i<pol2.size();i++) if(contain(pol2[i],pol1))return 1; for(int i=0;i<pol1.size();i++) for(int j=0;j<pol2.size();j++) if(is_intersected_ls(pol1[i],next(pol1,i),pol2[j],next(pol2,j)))return 1; return 0; } vector<point>convex_hull(point* ps, int n){ sort(ps,ps+n,cmp_x); int k=0; vector<point>qs(n*2); for(int i=0;i<n;i++){ while(k>1&&cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<=0)k--; qs[k++]=ps[i]; } for(int i=n-2,t=k;i>=0;i--){ while(k>t&&cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<=0)k--; qs[k++]=ps[i]; } qs.resize(k-1); return qs; } int main(void){ int n,m; point black[100],white[100]; while(cin >> n >> m,n|m){ for(int i=0;i<n;i++) cin >> black[i].x >> black[i].y; for(int i=0;i<m;i++) cin >> white[i].x >> white[i].y; if(n<2||m<2){ if(n<2 && m<2)cout << "YES" << endl; else { bool fg=false; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(is_intersected_ls(black[i],black[(i+1)%n],white[j],white[(j+1)%n]))fg=true; } } if(fg)cout <<"NO"<<endl; else cout << "YES" << endl; } continue; } vector<point>Black,White; Black=convex_hull(black,n); White=convex_hull(white,m); if(crossPol(Black,White))cout << "NO" << endl; else cout << "YES" << endl; } return 0; }