Description
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
则相交部分的面积为5.233。
Input
第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
Output
输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。
Sample Input
2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
Sample Output
5.233
HINT
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
Source
拆出边半平面交一下然后做凸包求面积.
我并不知道别的做法要怎么做…但是感觉似乎有
看数据范围半平面交不写排序增量暴力就能过
说不定当时重庆考场上就是给的暴力
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXDBL 1e20
#define eps 1e-9
#define MAXN 1010
using namespace std;
int n,m,cnt,num;
double ans;
struct Point
{
double x,y;
}s[MAXN],Hull[MAXN];
Point operator -(Point a,Point b)
{
return (Point){a.x-b.x,a.y-b.y};
}
double operator *(Point a,Point b)
{
return a.x*b.y-a.y*b.x;
}
struct line
{
Point a,b;
double k;
bool operator <(const line& A)const
{
if (k!=A.k) return k<A.k;
return (b-a)*(A.b-a)>0;
}
}que[MAXN],l[MAXN];
int head=1,tail;
Point get_inter(line A,line B)
{
double tmp1=(B.b-A.a)*(A.b-A.a),tmp2=(A.b-A.a)*(B.a-A.a);
double t=tmp1/(tmp1+tmp2);
return (Point){B.b.x+t*(B.a.x-B.b.x),B.b.y+t*(B.a.y-B.b.y)};
}
bool check(line A,line B,line C)//On_right
{
Point Inter=get_inter(A,B);
return (C.b-C.a)*(Inter-C.a)<0;
}
void Calc()
{
if (cnt<3) return;
for (int i=1;i<=cnt;i++) ans+=Hull[i]*Hull[i+1];
ans=fabs(ans)/2;
}
int main()
{
scanf("%d",&n);
while (n--)
{
scanf("%d",&m);
for (int i=1;i<=m;i++) scanf("%lf%lf",&s[i].x,&s[i].y);s[m+1]=s[1];
for (int i=1;i<=m;i++) l[++cnt].a=s[i],l[cnt].b=s[i+1];
}
for (int i=1;i<=cnt;i++) l[i].k=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
sort(l+1,l+cnt+1);
for(int i=1;i<=cnt;i++)
{
if(l[i].k!=l[i-1].k) num++;
l[num]=l[i];
}
que[++tail]=l[1];que[++tail]=l[2];
for (int i=3;i<=num;i++)
{
while (head<tail&&check(que[tail-1],que[tail],l[i])) tail--;
while (head<tail&&check(que[head+1],que[head],l[i])) head++;
que[++tail]=l[i];
}
while (head<tail&&check(que[tail-1],que[tail],que[head])) tail--;
while (head<tail&&check(que[head+1],que[head],que[tail])) head++;
que[tail+1]=que[head];cnt=0;
for (int i=head;i<=tail;i++) Hull[++cnt]=get_inter(que[i],que[i+1]);
Hull[cnt+1]=Hull[1];
Calc();
printf("%.3f",ans);
}