http://www.spoj.com/problems/SPOINTS/en/
http://poj.org/problem?id=3805
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1298
要想有一条直线分两个凸包,两个凸包不相交,不相切是必要的
在没有模板的情况下,我的代码,过了poj,uva,和spoj的,但是过不了aoj的,和正确代码对拍所发现的情况不太符合事实
方法是:
1.判断每个点是否在凸包里面或者边上
2.判断两凸包每两条线段是否相交
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const double eps=1e-8; const int maxn=205; int dcmp(double d){ if(fabs(d)<eps)return 0; return d>0?1:-1; } struct pnt{ double x,y; pnt():x(0),y(0){} pnt(double tx,double ty):x(tx),y(ty){} pnt operator -(pnt p2){ pnt newp(x-p2.x,y-p2.y); return newp; } pnt operator +(pnt p2){ pnt newp(x+p2.x,y+p2.y); return newp; } pnt operator *(double d){ pnt newp(x*d,y*d); return newp; } pnt operator /(double d){ pnt newp(x/d,y/d); return newp; } double dis(pnt p2){ return sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y)); } bool operator ==(pnt p2){ if(dcmp(x-p2.x)==0&&dcmp(y-p2.y)==0)return true; return false; } }; double cross(pnt p1,pnt p2){ return p1.x*p2.y-p1.y*p2.x; } bool cmpx(pnt p1,pnt p2){ if(p1.x!=p2.x)return p1.x<p2.x; return p1.y<p2.y; } pnt base; bool cmp(pnt p1,pnt p2){ return cross(p1- base,p2-base)<0; } int isPointInConvexPolygon(pnt p1,pnt * p,int n){ for(int i=0;i<n;i++){ pnt A=pnt(p[(i+1)%n].x-p[i].x,p[(i+1)%n].y-p[i].y); pnt B=pnt(p1.x-p[i].x,p1.y-p[i].y); int fl=dcmp(cross(A,B)); if(fl<0)return 0; if(fl==0){ int maxx=max(p[(i+1)%n].x,p[i].x); int minx=min(p[(i+1)%n].x,p[i].x); int maxy=max(p[(i+1)%n].y,p[i].y); int miny=min(p[(i+1)%n].y,p[i].y); if(minx<=p1.x&&maxx>=p1.x&&miny<=p1.y&&maxy>=p1.y)return -1;//on the edge else return 0; } } return 1; } int graham(pnt * p,pnt * h,int n){ int m=0; for(int i=0;i<n;i++){//计算上凸包 while(m>1&&cross((h[m-1]-h[m-2]),(p[i]-h[m-2]))<=0){m--;} h[m++]=p[i]; } int tm=m; for(int i=n-2;i>=0;i--){//计算下凸包 while(m>tm&&cross((h[m-1]-h[m-2]),(p[i]-h[m-2]))<=0){m--;} h[m++]=p[i]; } if(n>1)m--; return m; } bool between(pnt p1,pnt p2,pnt p){ return (p.x<=max(p1.x,p2.x)&&p.x>=min(p1.x,p2.x)) && (p.y<=max(p1.y,p2.y)&&p.y>=min(p1.y,p2.y)); } bool isInsert(pnt p11,pnt p12,pnt p21,pnt p22){ pnt v=p22-p21; pnt w=p12-p11; pnt u=p21-p11; if(cross(v,w)==0){ if(cross(v,u)!=0)return false; if(between(p11,p12,p21))return true; if(between(p11,p12,p22))return true; return false; } double t=cross(w,u)/cross(v,w); double t2=cross(v,u)/cross(v,w); if(t2>1||t2<0)return false; if(t>1||t<0)return false; return true; } pnt bp[maxn],bh[maxn],wp[maxn],wh[maxn]; int bn,wn,btop,wtop; int main(){ while(scanf("%d%d",&bn,&wn)==2&&(bn||wn)){ for(int i=0;i<bn;i++){ scanf("%lf%lf",&bp[i].x,&bp[i].y); } for(int i=0;i<wn;i++){ scanf("%lf%lf",&wp[i].x,&wp[i].y); } bool fl=true; if(bn>1){ sort(bp,bp+bn,cmpx); base =bp[0]; sort(bp+1,bp+bn,cmp); btop=graham(bp,bh,bn); if(fl)for(int i=0;i<wn;i++){ if(isPointInConvexPolygon(wp[i],bh,btop)){ fl=false; break; } } } if(wn>1){ sort(wp,wp+wn,cmpx); base =wp[0]; sort(wp+1,wp+wn,cmp); wtop=graham(wp,wh,wn); if(fl){ for(int i=0;i<bn;i++){ if(isPointInConvexPolygon(bp[i],wh,wtop)){ fl=false; break; } } } } if(fl&&bn>1&&wn>1){ for(int i=0;i<btop;i++){ for(int j=0;j<wtop;j++){ if(isInsert(bh[i],bh[(i+1)%btop],wh[j],wh[(j+1)%wtop])){ fl=false; break; } } } } if(wn==1&&bn==1&&bp[0]==wp[0]){fl=false;} if(fl)puts("YES"); else puts("NO"); } return 0; }
这里的代码都可以过:http://pelkira.hatenablog.jp/
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<map> #include<vector> #include<queue> #include<functional> #include<cstring> #include<cstdlib> #include<complex> using namespace std; typedef long long ll; typedef complex < double > Point; typedef vector < Point > Polygon; namespace std { bool operator < (Point a,Point b) { return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b); } } const double EPS = 1e-8; const double INF = 1e12; struct Line : Polygon{ Line(){}; Line(Point p,Point q){ push_back(p);push_back(q); } }; double cross(Point p,Point q){ return imag(conj(p)*q); } double dot(Point p,Point q){ return real(conj(p)*q); } int ccw(Point a,Point b,Point c){ b-=a,c-=a; if(cross(b,c)>0)return 1; //反時計回り if(cross(b,c)<0)return -1; //時計回り if(dot(b,c)<0)return 2; //直線上に c - a - b if(norm(b)<norm(c))return -2; // 直線上に a - b - c return 0; // 直線上に a - c - b } bool intersectSS(Line s, Line t) { return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0; } bool intersectSP(Line s, Point p) { return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality } Polygon ConvexHull(Polygon ps) {//凸包 int n = ps.size(), k = 0; if(n == 1)return ps; sort(ps.begin(), ps.end()); Polygon ch(2*n); for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; ch.resize(k-1); return ch; } // Point - Vertex enum{OUT, ON, IN}; int IsInnerPointVertex(Polygon ps,Point a){ bool flg = false; for(int i = 0;i < ps.size();i++){ Point p = ps[i] - a,q = ps[(i+1)%ps.size()] - a; if(imag(p)>imag(q))swap(p,q); if(imag(p)<=0&&0<imag(q)){ if(cross(p,q) < 0)flg = !flg; } if(cross(p,q) == 0 && dot(p,q) <= 0)return ON; } return flg ? IN : OUT; } int main(){ int n,m; while(cin>>n>>m,n){ Polygon G,H; for(int i = 0;i < n;i++){ double x,y; cin>>x>>y; G.push_back(Point(x,y)); } for(int i = 0;i < m;i++){ double x,y; cin>>x>>y; H.push_back(Point(x,y)); } G = ConvexHull(G); H = ConvexHull(H); int g = G.size(),h = H.size(); //cout<<g<<" "<<h<<endl; if(g > h)swap(G,H); g = G.size(),h = H.size(); bool flg = true; for(int i = 0;i < g;i++){ if(IsInnerPointVertex(H,G[i]) != OUT){ flg = false; break; } } for(int i = 0;i < h;i++){ if(IsInnerPointVertex(G,H[i]) != OUT){ flg = false; break; } } if(h == 1)flg = true; else if(g == 1 && h == 2){ flg = !(intersectSP(Line(H[0],H[1]),G[0])); } else if(g == 2 && h == 2){ flg = !(intersectSS(Line(G[0],G[1]),Line(H[0],H[1]))); } else if(g == 2){ flg = true; for(int i = 0;i < h;i++){ int j = (i+1)%h; if(intersectSS(Line(G[0],G[1]),Line(H[i],H[j])))flg = false; } } if(flg)cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
时间: 2024-10-10 05:00:43