半平面交板子。
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const double eps=1e-5; int dcmp(double x) {return fabs(x)<eps?0:(x<0?-1:1);} struct Poi{ Poi(){} double x,y; Poi(double A,double B):x(A),y(B){} Poi operator + (Poi G){return Poi(x+G.x,y+G.y);} Poi operator - (Poi G){return Poi(x-G.x,y-G.y);} Poi operator * (double G){return Poi(x*G,y*G);} }a[755]; double Cross(Poi A,Poi B){return A.x*B.y-B.x*A.y;} struct Line{ Line(){} Poi p,v; double ang; Line(Poi A,Poi B):p(A),v(B){ang=atan2(v.y,v.x);} bool Right(Poi G){return Cross(G-p,v)>0;} }c[755],h[755]; bool cmp(Line A,Line B){return dcmp(A.ang-B.ang)!=0?A.ang<B.ang:B.Right(A.p);}//极角相同选截距大的(半平面为直线左边) Poi Inter(Line A,Line B){ Poi u=A.p-B.p,v=A.v,w=B.v; double t=Cross(w,u)/Cross(v,w); return A.p+A.v*t; } int n,m,T,L=1,R=0; double Area(){ double re=0; for(int i=2;i<n;++i) re+=Cross(a[i]-a[1],a[i+1]-a[1]); return re/2.0; } void Half(){ for(int i=1;i<=m;++i){ while(L<R&&c[i].Right(Inter(h[R],h[R-1]))) --R; while(L<R&&c[i].Right(Inter(h[L],h[L+1]))) ++L; h[++R]=c[i]; } while(L<R&&h[L].Right(Inter(h[R],h[R-1]))) --R; while(L<R&&h[R].Right(Inter(h[L],h[L+1]))) ++L; n=0; h[R+1]=h[L]; for(int i=L;i<=R;++i) a[++n]=Inter(h[i],h[i+1]); } int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); for(int i=1;i<=n;++i) c[++m]=Line(a[i],a[i%n+1]-a[i]); }sort(c+1,c+m+1,cmp); n=m; m=0; for(int i=1;i<=n;++i) if(dcmp(c[i].ang-c[i+1].ang)!=0) c[++m]=c[i]; Half(); printf("%.3f",Area()); return 0; }