P4196 [CQOI2006]凸多边形(半平面交)

P4196 [CQOI2006]凸多边形

半平面交板子。

#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;
}

 

posted @ 2019-08-01 21:53  kafuuchino  阅读(189)  评论(0编辑  收藏  举报