BZOJ2618 凸多边形 半平面交

大家都很强, 可与之共勉 。

ZZ题……

# include <cmath>
# include <cstdio>
# include <algorithm>

template < class T > inline T min ( T a, T b )  {  return a > b ? b : a ;  }
template < class T > inline T max ( T a, T b )  {  return a > b ? a : b ;  }

const double eps = 1e-8 ;
const double Pi = acos ( -1 ) ;

inline int epssgn ( double x )  {
    return ( x > - eps ) - ( x < eps ) ;
} // x > eps -> 1 ; x < -eps -> -1 ; x == 0 -> 0 ;

struct Vector  {
    double x, y ; // len ;
    Vector ( ) {    }
    Vector ( double x, double y ) : x ( x ), y ( y ) {  /*len = sqrt ( x * x + y * y ) ;*/   }
    inline Vector operator + ( const Vector rhs )  const  {
        return Vector ( x + rhs.x, y + rhs.y ) ;
    }
    inline Vector operator - ( const Vector rhs ) const  {
        return Vector ( x - rhs.x, y - rhs.y ) ;
    }
    inline Vector operator * ( const double k ) const  {
        return Vector ( x * k, y * k ) ;
    }
    inline Vector operator / ( const double k ) const  {
        return Vector ( x / k, y / k ) ;
    }
    inline double operator * ( const Vector rhs ) const  {
        return x * rhs.x + y * rhs.y ;
    } // µã»ý
    inline double operator % ( const Vector rhs ) const  {
        return x * rhs.y - y * rhs.x ;
    } //²æ»ý
} ;

struct Point  {
    double x, y ;
    Point ( ) {    }
    Point ( double x, double y ) : x ( x ), y ( y ) {      }
    inline Vector operator - ( const Point rhs ) const  {
        return Vector ( x - rhs.x, y - rhs.y ) ;
    }
} ;

struct Line  {
    double a, b, c, angle ;
    Point p1, p2 ;
    Line ( )  {      }
    Line ( Point s, Point e ) : p1 ( s ), p2 ( e )  {
        a = s.y - e.y ;
        b = e.x - s.x ;
        c = e.y * s.x - e.x * s.y ;
        angle = atan2 ( e.y - s.y, e.x - s.x ) ; // !!!
    }
    inline bool operator < ( const Line& rhs )  const  {
        return angle < rhs.angle ;
    }
} ;  // ax + by + c = 0 ;

inline bool Parallel ( Line l1, Line l2 )  {
    return epssgn ( l1.a * l2.b - l1.b * l2.a ) == 0 ;
}

inline bool LineEqual ( Line l1, Line l2 )  {
    if ( ! Parallel ( l1, l2 ) )    return 0 ;
    return ( epssgn ( l1.b * l2.a - l2.b * l1.a ) == 0 ) && ( epssgn ( l1.c * l2.a - l2.c * l1.a ) == 0 ) ;
}

inline Point GetIntersect ( Line l1, Line l2 )  {
    return Point ( ( l1.b * l2.c - l2.b * l1.c ) / ( l1.a * l2.b - l2.a * l1.b ), ( l2.a * l1.c - l1.a * l2.c ) / ( l1.a * l2.b - l2.a * l1.b ) ) ;
}

struct Lcmp   {
    inline bool operator ( ) ( const Line& l1, const Line& l2 )  {
        int d = epssgn ( l1.angle - l2.angle ) ;
        if ( ! d )  return ( bool ) ( epssgn ( ( l2.p1 - l1.p1 ) % ( l2.p2 - l1.p1 ) ) > 0 ) ;
        return d < 0 ;
    }
} ;

inline bool IntersectionOutOfHalfPlane ( Line& hpl, Line& l1, Line& l2 )  {
    Point p = GetIntersect ( l1, l2 ) ;
    return ( epssgn ( ( hpl.p1 - p ) % ( hpl.p2 - p ) ) < 0 ) ;  // intersection is on left ;
}

# define N 100010

int HalfPlaneIntersect ( Line* l, int n, Point* p )  {
    static int dq [N] ;
    int top, bot ;
    std :: sort ( l, l + n, Lcmp ( ) ) ;
    int i, j ;
    for ( i = j = 0 ; i < n ; ++ i )
        if ( epssgn ( l [i].angle - l [j].angle ) > 0 )  {
            l [++ j] = l [i] ;
        }
    n = j + 1 ;
    dq [bot = 0] = 0 ;
    dq [top = 1] = 1 ;
    for ( i = 2 ; i < n ; ++ i )  {
        while ( top > bot && IntersectionOutOfHalfPlane ( l [i], l [dq [top]],l [dq [top - 1]] ) ) -- top ;
        while ( top > bot && IntersectionOutOfHalfPlane ( l [i], l [dq [bot]],l [dq [bot + 1]] ) )  ++ bot ;
        dq [++ top] = i ;
    }
    while ( top > bot && IntersectionOutOfHalfPlane ( l [dq [bot]],l [dq [top]],l [dq [top - 1]] ) ) -- top ;
    while ( top > bot && IntersectionOutOfHalfPlane ( l [dq [top]],l [dq [bot]],l [dq [bot + 1]] ) ) ++ bot ;
    dq [++ top] = dq [bot] ;
    int cnt = 0 ;
    for ( i = bot ; i < top ; ++ i ) p [cnt ++] = GetIntersect ( l [dq [i]], l [dq [i + 1]] ) ;
    return cnt ;
}

Line l [N] ;
Point p [N] ;

# undef N

int main ( )  {
    int n ;
    scanf ( "%d", & n ) ;
    int cnt ( 0 ) ;
    while ( n -- )  {
        static int m ;
        scanf ( "%d", & m ) ;
        for ( int i = 0 ; i < m ; ++ i )  scanf ( "%lf%lf", & p [i].x, & p [i].y ) ;
        for ( int i = 0 ; i < m ; ++ i )  {
            l [cnt ++] = Line ( p [i], p [i + 1 >= m ? i + 1 - m : i + 1] ) ;
        }
    }
    int pcnt = HalfPlaneIntersect ( l, cnt, p ) ;
    double ans ( 0 ) ;
    for ( int i = 0 ; i < pcnt ; ++ i )  {
        ans += ( p [i] - p [0] ) % ( p [i + 1 >= pcnt ? i + 1 - pcnt : i + 1] - p [0] ) ;
    }
    return printf ( "%.3lf\n", ans / 2 ), 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值