Description
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
则相交部分的面积为5.233。
![](https://i-blog.csdnimg.cn/blog_migrate/8bbb4d560d68440755765238549c4283.gif)
则相交部分的面积为5.233。
Input
第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
【限制】
50%的数据满足:n=2
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
【限制】
50%的数据满足:n=2
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
Output
仅包含一个实数,表示相交部分的面积,保留三位小数。
Sample Input
26-2 0-1 -21 -22 01 2-1 240 -31 -12 2-1 0
Sample Output
5.233
学习半平面交是时的水题。
练练手
首先介绍定比分点公式:
利用面积工具:
P分割DC的比值和面积的关系:
接下来就是定比分点求坐标了:
注意:上面的面积都取了绝对值,也可以根据有向面积的特点,不取绝对值,由于按照方向,其叉积面积为一正一负,则作减法即可。
例程求线段AB与CD的交点:
//OP1与OP2的叉积
double cross(point&O,point&p1,point&p2){
return(p1.x-O.x)*(p2.y-O.y)-(p2.x-O.x)*(p1.y-O.y);
}
接下来就是定比分点求坐标了:
注意:上面的面积都取了绝对值,也可以根据有向面积的特点,不取绝对值,由于按照方向,其叉积面积为一正一负,则作减法即可。
例程求线段AB与CD的交点:
//OP1与OP2的叉积
doublecross(point&O,point&p1,point&p2){
return(p1.x-O.x)*(p2.y-O.y)-(p2.x-O.x)*(p1.y-O.y);
}
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; struct Point { double x,y; }P[100005],last,cur,first; int n,m,T; double Cross(Point a,Point b,Point c){ return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y); } Point Get_NewPoint(Point a,Point b,Point l,Point r){ Point Temp; double x=abs(Cross(a,l,r)); double y=abs(Cross(b,l,r)); Temp.x=(a.x*y+b.x*x)/(x+y); Temp.y=(a.y*y+b.y*x)/(x+y); return Temp; } void Cut(Point x,Point y){ Point Temp[50]; int top=0; P[n+1]=P[1]; double l=Cross(y,P[1],x); for(int i=2;i<=n+1;i++){ double r=Cross(y,P[i],x); if(l>=0){ Temp[++top]=P[i-1]; if(r<0)Temp[++top]=Get_NewPoint(P[i-1],P[i],x,y); } else if(r>0)Temp[++top]=Get_NewPoint(P[i-1],P[i],x,y); l=r; } for(int i=1;i<=top;i++)P[i]=Temp[i]; n=top; } void Get_Ans(){ P[n+1]=P[1]; double Ans=0.0; for(int i=2;i<=n+1;i++){ Ans+=(P[i-1].x-P[i].x)*(P[i-1].y+P[i].y)/2.0; } printf("%.3lf",abs(Ans)); } int main(){ scanf("%d",&T); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%lf%lf",&P[i].x,&P[i].y); } n=m; for(int i=2;i<=T;i++){ scanf("%d",&m); scanf("%lf%lf",&first.x,&first.y); last=first; for(int i=2;i<=m;i++){ scanf("%lf%lf",&cur.x,&cur.y); Cut(last,cur); last=cur; } Cut(last,first); } Get_Ans(); return 0; }