1. 程式人生 > >HDU 5130 Signal Interference(圓與多邊形交的面積)

HDU 5130 Signal Interference(圓與多邊形交的面積)

題意:

A國與B國是敵國,A國有一個訊號塔,B國有一個訊號塔,A國領土是一個凸多邊形,當一個位置距B國訊號塔的距離是距A國訊號塔距離k倍以內的時候,訊息將被幹擾。
求A國領土上訊息被幹擾的面積。

思路:

寫出方程發現是個圓方程,所以這就是個圓與凸多邊形面積交的裸題。。測試下模板。

程式碼:

#include<bits/stdc++.h>
using namespace std;

const double eps = 1e-12 ;
const double PI = acos( -1.0 ) ;
inline double sqr( double x ){ return
x * x ; } inline int sgn( double x ){ if ( fabs(x) < eps ) return 0 ; return x > 0? 1 : -1 ; } struct Point{ double x , y ; Point(){} Point( double _x , double _y ): x(_x) , y(_y) {} void input() { scanf( "%lf%lf" ,&x ,&y ); } double norm() { return sqrt( s
qr(x) + sqr(y) ); } friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; } friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; } friend Point operator * ( const Point &a , const double &b ) { return
Point( a.x * b , a.y * b ) ; } friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; } friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; } friend bool operator == ( const Point &a , const Point &b ) { return sgn( a.x - b.x ) == 0 && sgn( a.y - b.y ) == 0 ; } bool operator < ( const Point &a )const{ return ( sgn( x - a.x ) < 0 ) || ( sgn( x - a.x ) == 0 && sgn( y - a.y ) < 0 ) ; } }; double dot( Point a , Point b ) { return a.x * b.x + a.y * b.y ; } double det( Point a , Point b ) { return a.x * b.y - a.y * b.x ; } double dist( Point a , Point b ) { return ( a - b ).norm() ; } int n ; double k ; Point A,B ; Point p[505] ; Point o ; double r ; int CircleInterLine( Point a, Point b, Point o, double r, Point *p ) { Point p1 = a - o ; Point d = b - a ; double A = dot( d, d ) ; double B = 2 * dot( d, p1 ) ; double C = dot( p1, p1 ) - sqr(r) ; double delta = sqr(B) - 4*A*C ; if ( sgn(delta) < 0 ) return 0 ;//相離 if ( sgn(delta) == 0 ) { //相切 double t = -B / (2*A) ; // 0 <= t <= 1說明交點線上段上 if ( sgn( t - 1 ) <= 0 && sgn( t ) >= 0 ) { p[0] = a + t * d ; return 1 ; } } if ( sgn(delta) > 0 ) { //相交 double t1 = ( -B - sqrt(delta) ) / (2*A) ; double t2 = ( -B + sqrt(delta) ) / (2*A) ; //0 <= t1, t2 <= 1說明交點線上段上 int k = 0 ; if ( sgn( t1 - 1 ) <= 0 && sgn( t1 ) >= 0 ) p[k++] = a + t1 * d ; if ( sgn( t2 - 1 ) <= 0 && sgn( t2 ) >= 0 ) p[k++] = a + t2 * d ; return k ; } } double Triangle_area( Point a, Point b ) { return fabs( det( a , b ) ) / 2.0 ; } double Sector_area( Point a, Point b ) { double ang = atan2( a.y , a.x ) - atan2( b.y, b.x ) ; while ( ang <= 0 ) ang += 2 * PI ; while ( ang > 2 * PI ) ang -= 2 * PI ; ang = min( ang, 2*PI - ang ) ; return sqr(r) * ang/2 ; } double calc( Point a , Point b , double r ) { Point pi[2] ; if ( sgn( a.norm() - r ) < 0 ) { if ( sgn( b.norm() - r ) < 0 ) { return Triangle_area( a, b ) ; } else { CircleInterLine( a, b, Point(0,0), r, pi) ; return Sector_area( b, pi[0] ) + Triangle_area( a, pi[0] ) ; } } else { int cnt = CircleInterLine( a, b, Point(0,0), r, pi ) ; if ( sgn( b.norm() - r ) < 0 ) { return Sector_area( a, pi[0] ) + Triangle_area( b, pi[0] ) ; } else { if ( cnt == 2 ) return Sector_area( a, pi[0] ) + Sector_area( b, pi[1] ) + Triangle_area( pi[0], pi[1] ) ; else return Sector_area( a, b ) ; } } } double area_CircleAndPolygon( Point *p , int n , Point o , double r ) { double res = 0 ; p[n] = p[0] ; for ( int i = 0 ; i < n ; i++ ) { int tmp = sgn( det( p[i] - o , p[i+1] - o ) ) ; if ( tmp ) res += tmp * calc( p[i] - o , p[i+1] - o , r ) ; } return fabs( res ) ; } void init() { double tmp = 1.0 - sqr(k) ; o.x = ( B.x - sqr(k)*A.x ) / tmp ; o.y = ( B.y - sqr(k)*A.y ) / tmp ; r = sqr(B.x) - sqr(k*A.x) + sqr(B.y) - sqr(k*A.y); r /= tmp ; r = sqr(o.x) + sqr(o.y) - r ; r = sqrt( r ) ; } int main() { int kase = 1 ; while ( cin >> n >> k ) { for ( int i = 0 ; i < n ; i++ ) p[i].input() ; A.input() ; B.input() ; init() ; printf( "Case %d: %.12f\n", kase++, area_CircleAndPolygon( p, n, o, r ) ) ; } return 0; }