http://acm.sgu.ru/problem.php?contest=0&problem=435题目大意,每个UFO会使长草的地面变成荒地,使荒地长出草来,作用范围是一个圆,求最后荒地和草地面积各为多少。 圆的离散化,比赛的时候没有想仔细,没有做出来,赛后经haozi一点拨,发现可以做,就拿以前写的一个圆离散化的代码改了改,结果精度不够。重新写了一个,结果打错了一个变量,一直没有发现,WA到崩溃。
 sgu_435 1 #include<iostream> 2 #include<complex> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 using namespace std; 9 10 const int maxn = 120; 11 //const double pi = acos( -1.0 ); 12 const double eps = 1e-8; 13 struct point 14  { 15 double x, y; 16 point( ) { } 17 point( double _x, double _y ) : x( _x ), y( _y ) { } 18 }; 19 20 struct circle 21  { 22 point p; 23 double r; 24 circle( ) { } 25 circle( point _p, double _r ) : p( _p ), r( _r ) { } 26 }; 27 28 struct node 29  { 30 double area; 31 int flag; // 标记圆弧是朝上还是朝下 32 double y, y1, y2; 33 }; 34 35 circle c[maxn]; 36 vector<double> vec; 37 double ans1, ans2; 38 39 //计算 ab 和 ac 的叉积 40 double det(const point& a, const point& b, const point& c) { 41 return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); 42 } 43 44 //计算 ab 和 ac 的点积 45 double dot(point a,point b,point c) { 46 return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); 47 } 48 49 double fix(double x) {return x < -1 ? -1 : ( x > 1 ? 1 : x ); } 50 51 double dis(const point &a, const point &b) { 52 return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); 53 } 54 55 double dis2(const point &a, const point &b) { 56 return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); 57 } 58 59 int dblcmp( double x ) { return ( x < -eps ? -1 : x > eps ); } 60 61 //求直线ab和直线cd的交点 62 point cross(const point &a, const point &b, const point &c, const point &d) 63  { 64 point ret = a; 65 double t = ( ( c.x - a.x ) * ( d.y - c.y ) - ( c.y - a.y ) * ( d.x - c.x ) ) / 66 ( ( b.x - a.x ) * ( d.y - c.y ) - ( b.y - a.y ) * ( d.x - c.x ) ); 67 ret.x += ( b.x - a.x ) * t; 68 ret.y += ( b.y - a.y ) * t; 69 return ret; 70 } 71 72 //计算直线与圆的交点,保证直线与圆有交点 73 void cross( const circle & b, const point &l1, const point &l2, point& p1, point& p2 ) 74  { 75 point p = b.p; 76 double t; 77 p.x += l1.y - l2.y; 78 p.y += l2.x - l1.x; 79 p = cross( p, b.p, l1, l2 ); 80 double tem = b.r * b.r - ( p.x - b.p.x ) * ( p.x - b.p.x ) 81 - ( p.y - b.p.y ) * ( p.y - b.p.y ); 82 if( tem < 0 ) tem = 0; 83 t = sqrt( tem ) / dis( l1, l2 ); 84 p2.x = p.x + ( l2.x - l1.x ) * t; 85 p2.y = p.y + ( l2.y - l1.y ) * t; 86 p1.x = p.x - ( l2.x - l1.x ) * t; 87 p1.y = p.y - ( l2.y - l1.y ) * t; 88 } 89 90 //计算圆与圆的交点,保证圆与圆有交点,圆心不重合 91 92 void cross(const circle & a,const circle & b, point& p1, point& p2) 93  { 94 point u, v; 95 double t = ( 1 + ( a.r * a.r - b.r * b.r ) / dis2( a.p, b.p ) ) / 2; 96 u.x = a.p.x + ( b.p.x - a.p.x ) * t; 97 u.y = a.p.y + ( b.p.y - a.p.y ) * t; 98 v.x = u.x + a.p.y - b.p.y; 99 v.y = u.y - a.p.x + b.p.x; 100 cross( a, u, v, p1, p2 ); 101 } 102 103 104 bool cmp( const node & a, const node & b ) 105  { 106 return a.y > b.y; 107 } 108 109 void solve( double x1, double x2, const int & n ) 110  { 111 point p1, p2; 112 double x = ( x1 + x2 ) / 2, t; 113 vector<node> V; 114 node up, down; // up 朝下, down 朝上 115 for( int i = 1; i <= n; i++ ) 116 { 117 if( dblcmp( c[i].p.x - c[i].r - x2 ) >= 0 )continue; 118 if( dblcmp( c[i].p.x + c[i].r - x1 ) <= 0 )continue; 119 120 up.flag = 2; down.flag = 1; 121 122 cross( c[i], point( x1, 0 ), point( x1, 1 ), p1, p2 ); 123 if( p1.y > p2.y ) swap( p1, p2 ); 124 up.y1 = p2.y, down.y1 = p1.y; 125 126 cross( c[i], point( x2, 0 ), point( x2, 1 ), p1, p2 ); 127 if( p1.y > p2.y ) swap( p1, p2 ); 128 up.y2 = p2.y, down.y2 = p1.y; 129 130 // y 131 cross( c[i], point( x, 0 ), point( x, 1 ), p1, p2 ); 132 if( p1.y > p2.y ) swap( p1, p2 ); 133 up.y = p2.y, down.y = p1.y; 134 135 p1 = point( x1, up.y1 ), p2 = point( x2, up.y2 ); 136 t = acos( fix( dot( c[i].p, p1, p2 ) / c[i].r / c[i].r ) ); 137 up.area = down.area = c[i].r * c[i].r * ( t - sin( t ) ) * 0.5; 138 V.push_back( up ); 139 V.push_back( down ); 140 } 141 142 sort( V.begin( ), V.end( ), cmp ); 143 int cnt = 0; 144 for( int i = 0; i < V.size( ); i++) 145 { 146 double tem = 0; 147 if( V[i].flag == 1 ) 148 { 149 cnt--; 150 tem -= V[i].area; 151 } 152 else 153 { 154 cnt++; 155 tem += V[i].area; 156 } 157 if( cnt > 0 ) 158 { 159 if( V[i+1].flag == 1 ) tem += V[i+1].area; 160 else tem -= V[i+1].area; 161 tem += 0.5 * ( V[i].y1 - V[i+1].y1 + V[i].y2 - V[i+1].y2 ) * ( x2 - x1 ); 162 if( cnt % 2 ) ans1 += tem; 163 else ans2 += tem; 164 } 165 } 166 } 167 168 void lisanhua( int n ) 169  { 170 point p1, p2; 171 vec.clear( ); 172 for( int i = 1; i <= n; i++ ) 173 { 174 vec.push_back( c[i].p.x + c[i].r ); 175 vec.push_back( c[i].p.x - c[i].r ); 176 } 177 for( int i = 1; i <= n; i++ ) 178 { 179 for( int j = i + 1; j <= n; j++ ) 180 { 181 double d = dis( c[i].p, c[j].p ); 182 //if( samecircle( c[i], c[j] ) )continue; 183 if( dblcmp( c[i].r + c[j].r - d ) < 0 || 184 dblcmp( fabs( c[i].r - c[j].r ) - d ) > 0 )continue; 185 cross( c[i], c[j], p1, p2 ); 186 vec.push_back( p1.x ); 187 vec.push_back( p2.x ); 188 } 189 } 190 sort( vec.begin( ), vec.end( ) ); 191 ans1 = ans2 = 0; 192 for( int i = 1; i < vec.size( ); i++ ) 193 { 194 if( dblcmp( vec[i] - vec[i-1] ) == 0 )continue; 195 solve( vec[i-1], vec[i], n ); 196 } 197 printf("%.5lf %.5lf\n",ans1, ans2); 198 //myunique( vec ); 199 } 200 201 int main( ) 202  { 203 int n; 204 //freopen("in.in","r",stdin); 205 //freopen("out.txt","w",stdout); 206 while( scanf("%d",&n) != EOF ) 207 { 208 for( int i = 1; i <= n; i++ ) 209 scanf("%lf %lf %lf",&c[i].p.x,&c[i].p.y,&c[i].r); 210 lisanhua( n ); 211 } 212 return 0; 213 } 214
|