【BZOJ2618】[Cqoi2006]凸多边形
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
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]内的整数
题解:半平面交板子题,刷板子~
注意先弹t后弹h。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=510;
const double eps=1e-9;
struct point
{
double x,y;
point() {}
point(double a,double b) {x=a,y=b;}
point operator + (const point &a) const {return point(x+a.x,y+a.y);}
point operator - (const point &a) const {return point(x-a.x,y-a.y);}
double operator * (const point &a) const {return x*a.y-y*a.x;}
point operator * (const double &a) const {return point(a*x,a*y);}
}p[maxn];
int m,n,h,t,np,q[maxn];
struct line
{
point p,v;
double a;
line() {}
line(point x,point y) {p=x,v=y,a=atan2(v.y,v.x);}
}l[maxn];
point getp(line l1,line l2)
{
point u=l1.p-l2.p;
double temp=(l2.v*u)/(l1.v*l2.v);
return l1.p+l1.v*temp;
}
bool onlft(line a,point b)
{
return a.v*(b-a.p)>eps;
}
bool cmp(line a,line b)
{
if(fabs(a.a-b.a)<eps) return onlft(a,b.p);
return a.a<b.a;
}
void HPI()
{
sort(l+1,l+n+1,cmp);
int i,j;
for(i=2,j=1;i<=n;i++) if(fabs(l[i].a-l[j].a)>eps) l[++j]=l[i];
n=j,h=t=q[1]=1;
for(i=2;i<=n;i++)
{
while(h<t&&onlft(l[i],getp(l[q[t]],l[q[t-1]]))) t--;
while(h<t&&onlft(l[i],getp(l[q[h]],l[q[h+1]]))) h++;
q[++t]=i;
}
while(h<t&&onlft(l[q[h]],getp(l[q[t]],l[q[t-1]]))) t--;
while(h<t&&onlft(l[q[t]],getp(l[q[h]],l[q[h+1]]))) h++;
q[++t]=q[h];
for(i=h,np=0;i<t;i++) p[++np]=getp(l[q[i]],l[q[i+1]]);
}
double getarea()
{
if(np<3) return 0;
double ret=0;
for(int i=2;i<=np;i++) ret+=p[i-1]*p[i];
ret+=p[np]*p[1];
return fabs(ret/2);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
int i,j,a;
m=rd();
for(i=1;i<=m;i++)
{
a=rd();
for(j=1;j<=a;j++) p[j].x=rd(),p[j].y=rd();
for(j=1;j<=a;j++) l[++n]=line(p[j],p[j]-p[j%a+1]);
}
HPI();
printf("%.3lf\n",getarea());
return 0;
}//8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0