Luogu-4196 [CQOI2006]凸多边形

凸多边形的面积就相当于半平面交

求几个凸多边形面积交就相当于一堆半平面一起求交

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e3+100;
struct Point{
    double x,y;
    Point(double xx=0,double yy=0){
        x=xx,y=yy;
    }
}a[maxn],p[maxn];
struct Vector{
    double x,y;
    Vector(double xx=0,double yy=0){
        x=xx,y=yy;
    }
};
struct Line{
    Point p;
    Vector v;
    double ang;
    Line(Point a=Point(),Vector b=Vector()){
        p=a,v=b;
        ang=atan2(v.y,v.x);
    }
}q[maxn],b[maxn];
int dcmp(double x){return fabs(x)<1e-9?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Vector operator * (double p,Vector a){return Vector(a.x*p,a.y*p);}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
double operator * (Point a,Point b){return a.x*b.y-a.y*b.x;}
bool operator < (Line x,Line y){return dcmp(x.ang-y.ang)==0?(dcmp(x.v*(y.p-x.p))>0):(x.ang<y.ang);}
Point glt(Line x,Line y){Vector v=x.p-y.p; return x.p+(y.v*v)/(x.v*y.v)*x.v;}
bool onright(Line a,Line b,Line t){Point p=glt(a,b); return dcmp(t.v*(p-t.p))<0;}
void bpm(Line *b,int &n,Point *p){
    sort(b+1,b+n+1);
    int l=0,r=1,tot=0;
    for(int i=1;i<=n;i++){
        if(b[i].ang!=b[i-1].ang) tot++;
        b[tot]=b[i];
    }
    n=tot,q[0]=b[1],q[1]=b[2];
    for(int i=3;i<=n;i++){
        while(l<r&&onright(q[r],q[r-1],b[i])) r--;
        while(l<r&&onright(q[l],q[l+1],b[i])) l++;
        q[++r]=b[i];
    }
    while(l<r&&onright(q[r],q[r-1],q[l])) r--;
    while(l<r&&onright(q[l],q[l+1],q[r])) l++;
    n=0,q[r+1]=q[l];
    for(int i=l;i<=r;i++)
        b[++n]=q[i],p[n]=glt(q[i],q[i+1]);
}
double S(Point *p,int n){
    double ans=0;
    p[n+1]=p[1];
    for(int i=1;i<=n;i++)
        ans+=p[i]*p[i+1];
    return fabs(ans)/2;
}
int t,m,n;
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y);
        a[m+1]=a[1];
        for(int i=1;i<=m;i++)
            b[++n]=Line(a[i],a[i+1]-a[i]);
    }
    bpm(b,n,p);
    printf("%.3lf\n",S(p,n));
    return 0;
}
posted @ 2018-11-24 22:25  nianheng  阅读(116)  评论(0编辑  收藏  举报