【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 ",getarea()); return 0; }//8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0