POJ 3449 Geometric Shapes(判断多边形相交情况)
http://poj.org/problem?id=3449
题意:
给你n个多边形,这些多边形包括线段,三角形,矩形,正方形,和其他多边形. 然后要你输出他们之间相交的情况. 且多边形自己的边不会相交,且三角形不会退化成线段.
分析:
本题不难,但是需要注意程序实现的各种细节才行.
当给你矩形时,你得到的是(x1,y1) (x2,y2) 和(x3,y3)3个点.你需要求出(x4,y4). 分析可得(x4,y4)=(x3+x1-x2,y3+y1-y2).
当给你正方形时,你得到的是对角线的端点(x1,y1)和(x3,y3).你需要计算出(x2,y2)和(x4,y4).
接下来就两两判断是否相交即可.判断两个图形是否相交,只需要判断他们中的任意两条边是否有交点即可(线段相交判定).
AC代码:
</pre><pre name="code" class="cpp">#include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> using namespace std; const int maxn=30+5; const double eps=1e-10; int dcmp(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} }; typedef Point Vector; Vector operator-(Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); } double Dot(Vector A,Vector B) { return A.x*B.x+A.y*B.y; } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } bool InSegment(Point P,Point a1,Point a2) { return dcmp(Cross(a1-P,a2-P))==0 && dcmp(Dot(a1-P,a2-P))<=0; } bool SegmentIntersection(Point a1,Point a2,Point b1,Point b2) { double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1); double c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1); if(dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0) return true; if(dcmp(c1)==0 && InSegment(b1,a1,a2) ) return true; if(dcmp(c2)==0 && InSegment(b2,a1,a2) ) return true; if(dcmp(c3)==0 && InSegment(a1,b1,b2) ) return true; if(dcmp(c4)==0 && InSegment(a2,b1,b2) ) return true; return false; } /***以上为刘汝佳模板***/ struct Graph { char type; //该图形的字母标记 int n; //点数 Point p[maxn];//图形的每个顶点 bool operator<(const Graph &rhs)const { return type<rhs.type; } }G[maxn]; int main() { while(scanf(" %c",&G[0].type)==1 && G[0].type!='.') { int n=0;//图形个数 while(G[n].type!='-') { char str[100]; scanf("%s",str); if(str[0]=='l') { for(int i=0;i<2;++i) scanf(" (%lf,%lf)",&G[n].p[i].x,&G[n].p[i].y); G[n].p[2]=G[n].p[0]; G[n].n=2; ++n; } else if(str[0]=='t') { for(int i=0;i<3;++i) scanf(" (%lf,%lf)",&G[n].p[i].x,&G[n].p[i].y); G[n].p[3]=G[n].p[0]; G[n].n=3; ++n; } else if(str[0]=='r') { for(int i=0;i<3;++i) scanf(" (%lf,%lf)",&G[n].p[i].x,&G[n].p[i].y); G[n].p[3].x= G[n].p[0].x+G[n].p[2].x-G[n].p[1].x; G[n].p[3].y= G[n].p[0].y+G[n].p[2].y-G[n].p[1].y; G[n].p[4]=G[n].p[0]; G[n].n=4; ++n; } else if(str[0]=='s') { for(int i=0;i<3;i+=2)//注意i+=2 scanf(" (%lf,%lf)",&G[n].p[i].x,&G[n].p[i].y); G[n].p[1].x = (G[n].p[0].x+G[n].p[2].x-G[n].p[2].y+G[n].p[0].y)/2 ; G[n].p[1].y = (-G[n].p[0].x+G[n].p[2].x+G[n].p[2].y+G[n].p[0].y)/2 ; G[n].p[3].x = (G[n].p[0].x+G[n].p[2].x+G[n].p[2].y-G[n].p[0].y)/2 ; G[n].p[3].y = ( G[n].p[0].x-G[n].p[2].x+G[n].p[2].y+G[n].p[0].y)/2 ; G[n].p[4]=G[n].p[0]; G[n].n=4; ++n; } else if(str[0]=='p') { scanf("%d",&G[n].n); for(int i=0;i<G[n].n;++i)//错误1,这里i<n scanf(" (%lf,%lf)",&G[n].p[i].x,&G[n].p[i].y); G[n].p[G[n].n]=G[n].p[0];//错误2,漏写了这句且G[n].p[G[n].n]写成了G[n].p[n] ++n; } scanf(" %c",&G[n].type); } sort(G,G+n); vector<int> vc[maxn];//vc[i]记录第i个多边形与哪几个多边形相交 for(int i=0;i<n;++i) for(int j=i+1;j<n;++j) { for(int k=0;k<G[i].n;++k) { int h; for(h=0;h<G[j].n;++h) { if(SegmentIntersection(G[i].p[k],G[i].p[k+1], G[j].p[h],G[j].p[h+1] ) ) { vc[i].push_back(j),vc[j].push_back(i); break; } } if(h<G[j].n) break; } } //打印结果 for(int i=0;i<n;++i) { if(vc[i].size()==0) printf("%c has no intersections\n",G[i].type); else if(vc[i].size()==1) printf("%c intersects with %c\n",G[i].type,G[vc[i][0]].type); else if(vc[i].size()==2) printf("%c intersects with %c and %c\n",G[i].type,G[vc[i][0]].type,G[vc[i][1]].type); else { printf("%c intersects with ",G[i].type); for(int j=0;j<vc[i].size()-1;++j) printf("%c, ",G[vc[i][j]].type); printf("and %c\n",G[vc[i][vc[i].size()-1]].type ); } } printf("\n"); } return 0; }