http://acm.sgu.ru/problem.php?contest=0&problem=435
题目大意,每个UFO会使长草的地面变成荒地,使荒地长出草来,作用范围是一个圆,求最后荒地和草地面积各为多少。
圆的离散化,比赛的时候没有想仔细,没有做出来,赛后经haozi一点拨,发现可以做,就拿以前写的一个圆离散化的代码改了改,结果精度不够。重新写了一个,结果打错了一个变量,一直没有发现,WA到崩溃。
题目大意,每个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>
8using namespace std;
9
10const int maxn = 120;
11//const double pi = acos( -1.0 );
12const double eps = 1e-8;
13struct point
14{
15 double x, y;
16 point( ) { }
17 point( double _x, double _y ) : x( _x ), y( _y ) { }
18};
19
20struct circle
21{
22 point p;
23 double r;
24 circle( ){ }
25 circle( point _p, double _r ) : p( _p ), r( _r ) { }
26};
27
28struct node
29{
30 double area;
31 int flag; // 标记圆弧是朝上还是朝下
32 double y, y1, y2;
33};
34
35circle c[maxn];
36vector<double> vec;
37double ans1, ans2;
38
39//计算 ab 和 ac 的叉积
40double 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 的点积
45double 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
49double fix(double x){return x < -1 ? -1 : ( x > 1 ? 1 : x ); }
50
51double 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
55double 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
59int dblcmp( double x ) { return ( x < -eps ? -1 : x > eps ); }
60
61//求直线ab和直线cd的交点
62point 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//计算直线与圆的交点,保证直线与圆有交点
73void 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
92void 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
104bool cmp( const node & a, const node & b )
105{
106 return a.y > b.y;
107}
108
109void 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
168void 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
201int 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
1#include<iostream>
2#include<complex>
3#include<cstring>
4#include<cstdio>
5#include<cmath>
6#include<algorithm>
7#include<vector>
8using namespace std;
9
10const int maxn = 120;
11//const double pi = acos( -1.0 );
12const double eps = 1e-8;
13struct point
14{
15 double x, y;
16 point( ) { }
17 point( double _x, double _y ) : x( _x ), y( _y ) { }
18};
19
20struct circle
21{
22 point p;
23 double r;
24 circle( ){ }
25 circle( point _p, double _r ) : p( _p ), r( _r ) { }
26};
27
28struct node
29{
30 double area;
31 int flag; // 标记圆弧是朝上还是朝下
32 double y, y1, y2;
33};
34
35circle c[maxn];
36vector<double> vec;
37double ans1, ans2;
38
39//计算 ab 和 ac 的叉积
40double 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 的点积
45double 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
49double fix(double x){return x < -1 ? -1 : ( x > 1 ? 1 : x ); }
50
51double 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
55double 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
59int dblcmp( double x ) { return ( x < -eps ? -1 : x > eps ); }
60
61//求直线ab和直线cd的交点
62point 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//计算直线与圆的交点,保证直线与圆有交点
73void 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
92void 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
104bool cmp( const node & a, const node & b )
105{
106 return a.y > b.y;
107}
108
109void 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
168void 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
201int 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