# BZOJ 1043 下落的圆盘

## Input

n ri xi y1 ... rn xn yn

2
1 0 0
1 1 0

10.472

## HINT

n<=1000

  1 #include<iostream>
2 #include<cmath>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstdlib>
6 using namespace std;
7
8 #define pi (3.1415926535)
9 #define esp (1e-6)
10 #define maxn 2010
11 int n; double ans;
12
13 inline bool equal(double a,double b) { return fabs(a - b) < esp; }
14
15 inline double qua(double a) { return a * a; }
16
17 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; } //>=
18
19 inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; } //<=
20
21 struct NODE{ double x,y; };
22 struct angle
23 {
24     double a1,a2;
25     friend inline bool operator < (angle a,angle b)
26     {
27         if (!equal(a.a1,b.a1)) return xd(a.a1,b.a1);
28         return xd(a.a2,b.a2);
29     }
30 }bac[maxn];
31 struct CIR
32 {
33     double r,x,y;
34     inline void read() { scanf("%lf %lf %lf",&r,&x,&y); }
35     inline NODE mid() { return (NODE) {x,y}; }
36     inline double calc(NODE p) { return atan2(p.y-y,p.x-x); }
37     inline double C() { return 2*pi*r; }
38 }cir[maxn];
39 struct LINE
40 {
41     double a,b,c;
42     inline double dis(NODE p) { return fabs(a*p.x+b*p.y+c)/sqrt(qua(a)+qua(b)); }
43     inline double key(NODE p) { return p.x*a+p.y*b+c; }
44 };
45
46 inline double dis(NODE a,NODE b) { return sqrt(qua(a.x-b.x) + qua(a.y-b.y)); }
47
48 inline bool have(CIR c1,CIR c2) { return dis(c1.mid(),c2.mid())<c1.r+c2.r; }
49
50 inline bool cat(CIR c1,CIR c2) { return xd(dis(c1.mid(),c2.mid()),fabs(c1.r-c2.r)); }
51
52 inline LINE cross(CIR c1,CIR c2) { return (LINE) {2*(c2.x-c1.x),2*(c2.y-c1.y),(qua(c2.r)-qua(c2.x)-qua(c2.y))-(qua(c1.r)-qua(c1.x)-qua(c1.y))}; }
53
54 inline void work()
55 {
56     int tot,i,j; double rest,p,q,a,b,now; LINE l;
57     for (i = n;i;--i)
58     {
59         tot = 0; rest = 0; now = 0;
60         for (j = i+1;j <= n;++j)
61         {
62             if (cat(cir[i],cir[j]))
63             {
64                 if (cir[i].r > cir[j].r) continue;
65                 else break;
66             }
67             if (have(cir[i],cir[j]))
68             {
69                 p = cir[i].calc(cir[j].mid()) + pi;
70                 l = cross(cir[i],cir[j]);
71                 q = l.dis(cir[i].mid());
72                 q = acos(q/cir[i].r);
73                 if (cir[i].r < cir[j].r&&l.key(cir[i].mid())*l.key(cir[j].mid()) > 0)
74                     q = pi - q;
75                 a = p - q; b = p + q;
76                 if (dd(a,0) && xd(b,2*pi))
77                     bac[++tot] = (angle) {a,b};
78                 else if (a < 0)
79                 {
80                     bac[++tot] = (angle) {a+2*pi,2*pi};
81                     bac[++tot] = (angle) {0,b};
82                 }
83                 else
84                 {
85                     bac[++tot] = (angle) {a,2*pi};
86                     bac[++tot] = (angle) {0,b-2*pi};
87                 }
88             }
89         }
90         if (j != n+1) continue;
91         sort(bac+1,bac+tot+1);
92         for (int j = 1;j <= tot;++j)
93         {
94             if (bac[j].a1 > now)
95             {
96                 rest += bac[j].a1 - now;
97                 now = bac[j].a2;
98             }
99             else now = max(now,bac[j].a2);
100         }
101         rest += 2*pi - now;
102         ans += rest/(2*pi) * cir[i].C();
103     }
104 }
105
106 int main()
107 {
108     freopen("1043.in","r",stdin);
109     freopen("1043.out","w",stdout);
110     scanf("%d",&n);
111     for (int i = 1;i <= n;++i) cir[i].read();
112     work();
113     printf("%.3lf",ans);
114     fclose(stdin); fclose(stdout);
115     return 0;
116 }
View Code

posted @ 2015-02-09 23:06  lmxyy  阅读(256)  评论(0编辑  收藏  举报