凸多边形(polygon)
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
则相交部分的面积为5.233。
【输入格式】
输入文件polygon.in第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
【输出格式】
输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。
【样例】
polygon.in |
polygon.out |
2 6 -2 0 -1 -2 1 -2 2 0 1 2 -1 2 4 0 -3 1 -1 2 2 -1 0 |
5.233 |
【限制】
50%的数据满足:n=2
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
就是求多个多边形面积交。不知道标准方法是什么。AC了。
我的方法是读入所有的点,枚举每两条边,求交点,把交点也放入原来的点集中,再枚举每一个点,判断是否在每一个多边形内,是则保留
最后以1号节点固定,枚举每一条对边,算三角形面积,求和(重复节点不用管,因为面积为0)。
很重要要注意,我也错了的地方:
1、判断相交(包括非规范),要进行两次操作,a的两端点是否在b两侧且b的两端点是否在a两侧。我只进行了其一。
2、极角排序的时候,必须用qsort,且要有第二关键字为模长。(这样才会把相同的放在一起)
3、求交点要用叉乘,如果用解析几何的方法,要忽略斜率为0的情况。即用四边形和三角形面积比来算长度之比,算出向量,再求点坐标。(但是如果是共线呢?还没搞清楚)
4、最后要保留的点必须是在所有的多边形内部,我当成了在任意一个多边形内部。
感觉代码长了,不过还是比较工整个人认为。
#include
#include
#include
#include
long n;
long m[12];
struct node
{
double x;
double y;
};
node Point[12][52];
node P[502];
long L[502];
long I[502];
long countP = 0;
node P2[502];
const double eps = 1e-8;
inline int getint()
{
int res = 0; char tmp; bool sgn = 1;
do tmp = getchar();
while (!isdigit(tmp) && tmp != '-');
if (tmp == '-')
{
sgn = 0;
tmp = getchar();
}
do res = (res << 1) + (res << 3) + tmp - '0';
while (isdigit(tmp = getchar()));
return sgn ? res : -res;
}
double Cross_Product(const node& n1,const node& n2,const node& nn)
{
node vector1;
vector1.x = n2.x-n1.x;
vector1.y = n2.y-n1.y;
node vector2;
vector2.x = nn.x-n2.x;
vector2.y = nn.y-n2.y;
return vector1.x*vector2.y-vector2.x*vector1.y;
}
double Cross_Product(const node& vector1,const node& vector2)
{
return vector1.x*vector2.y-vector2.x*vector1.y;
}
void Calc(const node& n1,const node& n2,const node& n3,const node& n4,double& x,double& y)
{
node AB;
AB.x = n2.x-n1.x;
AB.y = n2.y-n1.y;
node CD;
CD.x = n4.x-n3.x;
CD.y = n4.y-n3.y;
node AC;
AC.x = n3.x-n1.x;
AC.y = n3.y-n1.y;
node AD;
AD.x = n4.x-n1.x;
AD.y = n4.y-n1.y;
double cpc = fabs((Cross_Product(AC,AD))/Cross_Product(AB,CD));
node AO;
AO.x = AB.x * cpc;
AO.y = AB.y * cpc;
x = n1.x + AO.x;
y = n1.y + AO.y;
}
double S(const node& n1,const node& n2,const node& n3)
{
return fabs(Cross_Product(n1,n2,n3)/2.0);
}
int bigger(const void* a,const void* b)
{
node aa = *(node*)a;
node bb = *(node*)b;
aa.x -= P2[1].x;
aa.y -= P2[1].y;
bb.x -= P2[1].x;
bb.y -= P2[1].y;
double cpc = Cross_Product(aa,bb);
if (cpc > eps) return -1;
if (cpc < -eps) return 1;
if (aa.x*aa.x+aa.y*aa.y < bb.x*bb.x+bb.y*bb.y)
return -1;
if (aa.x*aa.x+aa.y*aa.y > bb.x*bb.x+bb.y*bb.y)
return 1;
return 0;
}
int main()
{
freopen("polygon.in","r",stdin);
freopen("polygon.out","w",stdout);
scanf("%ld",&n);
for (long l=1;l m[g]) j = 1;
for (long h=g+1;h m[h]) q = 1;
if (Cross_Product(Point[g][i],Point[g][j],Point[h][p])*Cross_Product(Point[g][i],Point[g][j],Point[h][q]) < -eps
&& Cross_Product(Point[h][p],Point[h][q],Point[g][i])*Cross_Product(Point[h][p],Point[h][q],Point[g][j]) < -eps)
{
double x;double y;
Calc(Point[g][i],Point[g][j],Point[h][p],Point[h][q],x,y);
++_cntP;
P[_cntP].x = x;
P[_cntP].y = y;
}
}
}
}
}
countP = _cntP;
_cntP = 0;
for (long i=1;i-eps;
for (long k=2;k-eps)!=multi)
{
OK = false;
break;
}
}
if ((Cross_Product(Point[j][m[j]],Point[j][1],P[i])>-eps)!=multi)
{
OK = false;
break;
}
if (!OK) break;
}
if ( OK )
{
++_cntP;
P2[_cntP].x = P[i].x;
P2[_cntP].y = P[i].y;
}
}
countP = _cntP;
double sumS = 0;
if (countP > 0)
{
qsort(P2+2,countP-1,sizeof(P2[1]),bigger);
///
/*
for (long i=1;i