luogu4196 [CQOI2006]凸多边形 半平面交

据说pkusc出了好几年半平面交了,我也来水一发
ref

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, cnt, tot;
const double eps=1e-7;
struct Point{
    double x, y;
    Point(double u=0.0, double v=0.0){
        x = u; y = v;
    }
    Point operator+(const Point &u)const{
        return Point(x+u.x, y+u.y);
    }
    Point operator-(const Point &u)const{
        return Point(x-u.x, y-u.y);
    }
    double crs(Point u){
        return x*u.y-y*u.x;
    }
}pt[55], a[1005];
struct Line{
    Point x, y;
    double ang;
    Line(){}
    Line(Point u, Point v){
        x = u; y = v;
        ang = atan2(v.y-u.y, v.x-u.x);
    }
}l[1005], d[1005];
Point operator*(double x, Point u){
    return Point(x*u.x, x*u.y);
}
bool cmp(Line u, Line v){
    if(fabs(u.ang-v.ang)>=eps)  return u.ang<v.ang;
    return (u.y-u.x).crs(v.y-u.x)>eps;
}
Point inter(Line u, Line v){
    double t=(v.x-u.x).crs(v.y-u.x)/((v.x-u.x).crs(v.y-u.x)+(v.y-u.y).crs(v.x-u.y));
    return u.x+t*(u.y-u.x);
}
bool isLeft(Point u, Line v){
    return (v.y-v.x).crs(u-v.x)>eps;
}
void halfPlaneIntersection(){
    sort(l+1, l+1+cnt, cmp);
    for(int i=1; i<=cnt; i++){
        if(i==1 || fabs(l[i].ang-l[i-1].ang)>=eps)  tot++;
        l[tot] = l[i];
    }
    cnt = tot; tot = 0;
    int ll=1, rr=0;
    d[++rr] = l[1]; d[++rr] = l[2];
    for(int i=3; i<=cnt; i++){
        while(ll<rr && !isLeft(inter(d[rr-1], d[rr]), l[i]))    rr--;
        while(ll<rr && !isLeft(inter(d[ll+1], d[ll]), l[i]))    ll++;
        d[++rr] = l[i];
    }
    while(ll<rr && !isLeft(inter(d[rr-1], d[rr]), d[ll]))   rr--;
    while(ll<rr && !isLeft(inter(d[ll+1], d[ll]), d[rr]))   ll++;
    d[rr+1] = d[ll];
    for(int i=ll; i<=rr; i++)
        a[++tot] = inter(d[i], d[i+1]);
}
double ans(){
    if(tot<3)   return 0.0;
    a[tot+1] = a[1];
    double re=0;
    for(int i=1; i<=tot; i++)
        re += a[i].crs(a[i+1]);
    return re/2;
}
int main(){
    cin>>n;
    while(n--){
        int mi;
        scanf("%d", &mi);
        for(int i=1; i<=mi; i++)
            scanf("%lf %lf", &pt[i].x, &pt[i].y);
        pt[mi+1] = pt[1];
        for(int i=1; i<=mi; i++)
            l[++cnt] = (Line){pt[i], pt[i+1]};
    }
    halfPlaneIntersection();
    printf("%.3f\n", ans());
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/poorpool/p/9098464.html