URAL 1464 Light

来源:互联网 发布:mac hosts文件位置 编辑:程序博客网 时间:2024/06/05 19:48

在一个简单多边形内有一个灯泡,问灯泡能够照到的面积。我是看了封尘记忆的blog的,大概理解了。


主要看这个图,然后和代码结合起来看。。多边形是ABCDE,因为EA边跨过了x轴负半轴,所以多添加一个在负半轴上的点M。扫描线扫过去阴影部分面积答案加起来就好了。

扫描线有一条入点和一个出点,point里面有重载小于号,是保证入点的极角小于出点的极角。seg重载小于号,新插入的线段必须得跟已经插入的线段,按照到原点的距离排序。然后就是用multiset。。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <set>#include <vector>using namespace std;#define LL long long#define eps 1e-8#define inf 0x3f3f3f3f#define Pi acos( -1.0 )#define pb push_back#define mnx 60100#define mxn 200int dcmp( double x ){    if( fabs( x ) < eps ) return 0;    return x < 0 ? -1 : 1;}struct point{    double x, y, ang;    point( double x = 0, double y = 0 ) : x(x), y(y) {        ang = atan2( y, x );    }    point operator + ( const point &b ) const{        return point( x + b.x, y + b.y );    }    point operator - ( const point &b ) const{        return point( x - b.x, y - b.y );    }    point operator * ( const double &k ) const{        return point( x * k, y * k );    }    point operator / ( const double &k ) const{        return point( x / k, y / k );    }    bool operator < ( const point &b ) const{        return ang > b.ang;    }    bool operator == ( const point &b ) const{        return dcmp( x - b.x ) == 0 && dcmp( y - b.y ) == 0;    }    double len(){        return sqrt( x * x + y * y );    }};typedef point Vector;double dot( Vector a, Vector b ){    return a.x * b.x + a.y * b.y;}double cross( Vector a, Vector b ){    return a.x * b.y - a.y * b.x;}point get_intersection( point au, point av, point bu, point bv ){    Vector u = au - bu, aV = av - au, bV = bv - bu;    double t = cross( bV, u ) / cross( aV, bV );    return au + aV * t;}const point o = point( 0, 0 );point base;struct Seg{    point u, v;    int id, in;    double ang;    Seg(){}    Seg( point u, point v, int in, int id, double ang ) : u(u), v(v), in(in), id(id), ang(ang) {}    bool operator < ( const Seg &b ) const {        if( u == b.u ){            return cross( v - u, b.v - u ) < 0;        }        point aa = get_intersection( u, v, o, base );        point bb = get_intersection( b.u, b.v, o, base );        return aa.len() < bb.len();    }}L[mnx<<1];bool cmp( const Seg &a, const Seg &b ){    return a.ang < b.ang || ( a.ang == b.ang && a.in > b.in );}int n, all;point p[mnx];void add( point a, point b, int kk ){    if( a < b ) swap( a, b );    L[all++] = Seg( a, b, 1, kk, a.ang );    L[all++] = Seg( b, a, 0, kk, b.ang );}double cal( const Seg &seg, double pre, double now ){    point aa = get_intersection( seg.u, seg.v, o, point( cos(pre), sin(pre) ) );    point bb = get_intersection( seg.u, seg.v, o, point( cos(now), sin(now) ) );    return fabs( 0.5 * cross( aa, bb ) );}multiset<Seg> S;multiset<Seg>::iterator itArr[mnx<<1];void solve(){    S.clear();    double ans = 0, pre = -Pi;    for( int i = 0; i < all; ++i ){        double nowAng = L[i].ang;        base = L[i].u;        if( L[i].in ){            if( !S.empty() )                ans += cal( *S.begin(), pre, nowAng );            itArr[L[i].id] = S.insert( L[i] );        }        else{            ans += cal( *S.begin(), pre, nowAng );            S.erase( itArr[L[i].id] );        }        pre = nowAng;    }    printf( "%.10lf\n", ans );}int main(){    //freopen( "out.txt", "w", stdout );    point c;    while( scanf( "%lf%lf", &c.x, &c.y ) != EOF ){        scanf( "%d", &n );        for( int i = 0; i < n; ++i ){            scanf( "%lf%lf", &p[i].x, &p[i].y );            p[i] = p[i] - c, p[i].ang = atan2( p[i].y, p[i].x );        }        p[n] = p[0];        all = 0;        for( int i = 0, k = 0; i < n; ++i ){            double d = fabs( p[i+1].ang - p[i].ang );            if( d < Pi )                add( p[i], p[i+1], k++ );            else{                point tmp = get_intersection( p[i], p[i+1], o, point( -1.0, 0 ) );                tmp.ang = Pi * dcmp( p[i].ang );                add( p[i], tmp, k++ );                tmp.ang = Pi * dcmp( p[i+1].ang );                add( tmp, p[i+1], k++ );            }        }        sort( L, L + all, cmp );        solve();    }    return 0;}


0 0
原创粉丝点击