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;
}