bzoj 1043[HAOI2008]下落的圆盘 - 贪心 + 几何

1043: [HAOI2008]下落的圆盘

Time Limit: 10 Sec  Memory Limit: 162 MB

Description

  有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红
色线条的总长度即为所求. 

Input

  第一行为1个整数n,N<=1000
接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.

Output

  最后的周长,保留三位小数

Sample Input

2
1 0 0
1 1 0

Sample Output

10.472
 
 
对于任意两个圆,我们可以求出它的两个交点对应的圆心角,这两个角度对应了一个(或两个)线段, 我们把所有的线段算出来后
就能用贪心求出总的覆盖长度,然后就算出来了。
 
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define LL long long
  7 #define pi acos(-1.0)
  8 using namespace std;
  9 
 10 const int MAXN = 1e3 + 10;
 11 LL N;
 12 double ans;
 13 struct circle {
 14     double x, y;
 15     double r;
 16 } c[MAXN];
 17 
 18 struct seg {
 19     double l, r;
 20 } s[MAXN * 5];
 21 double thita1, thita2;
 22 inline LL read()
 23 {
 24     LL x = 0, w = 1; char ch = 0;
 25     while(ch < '0' || ch > '9') {
 26         if(ch == '-') {
 27             w = -1;
 28         }
 29         ch = getchar();
 30     }
 31     while(ch >= '0' && ch <= '9') {
 32         x = x * 10 + ch - '0';
 33         ch = getchar();
 34     }
 35     return x * w;
 36 }
 37 
 38 double dis(int i, int j)
 39 {
 40     return sqrt((c[i].y - c[j].y) * (c[i].y - c[j].y) + (c[i].x - c[j].x) * (c[i].x - c[j].x)); 
 41 }
 42 
 43 bool con(int i, int j, double d)
 44 {
 45     if(d + c[i].r <= c[j].r) {
 46         return true;
 47     }
 48     return false;
 49 }
 50 
 51 bool cmp(seg a, seg b)
 52 {
 53     if(a.l == b.l) {
 54         return a.r >= b.r;
 55     }
 56     return a.l < b.l;
 57 }
 58 
 59 void cal(int i)
 60 {
 61     int tot = 0;
 62     for(int j = i + 1; j <= N; j++) {
 63         double d = dis(i, j);
 64         if(con(i, j, d)) {
 65             return;
 66         }
 67         double l, r;
 68 //        cout<<d<<endl;
 69         if(d <= c[i].r + c[j].r && !con(j, i, d)) {
 70             thita1 = atan2(c[j].y - c[i].y, c[j].x - c[i].x);
 71             thita2 = acos((d * d + c[i].r * c[i].r - c[j].r * c[j].r) / (2 * d * c[i].r)); 
 72     //    cout<<thita1<<" "<<thita2<<endl;
 73             l = thita1 - thita2, r = thita1 + thita2;
 74         //    printf("%.3lf %.3lf\n", l, r); 
 75             if(l < 0) {
 76                 l = l + 2 * pi;
 77             }
 78             if(r < 0) {
 79                 r = r + 2 * pi;
 80             }
 81             if(l > r) {
 82                 s[tot].l = l;
 83                 s[tot++].r = 2 * pi;
 84                 s[tot].l = 0;
 85                 s[tot++].r = r;
 86             } else {
 87                 s[tot].l = l;
 88                 s[tot++].r = r;
 89             }
 90         }
 91     }
 92     sort(s, s + tot, cmp);
 93     double len = 0, cnt = 0;
 94     for(int j = 0; j < tot; j++) {
 95 //        cout<<s[j].l<<" "<<s[j].r<<endl;
 96         if(s[j].l > cnt) {
 97             len += s[j].l - cnt;
 98         }
 99         cnt = max(cnt, s[j].r);
100     }
101     len += 2 * pi - cnt;
102     ans += len * c[i].r;
103     //cout<<len<<endl;
104 }
105 int main()
106 {
107     N = read();
108     for(int i = 1; i <= N; i++) {
109         scanf("%lf%lf%lf", &c[i].r, &c[i].x, &c[i].y); 
110     }
111     for(int i = 1; i <= N; i++) {
112         cal(i);
113     }
114     printf("%.3lf\n", ans);
115     return 0;
116 }
117 
118 /*
119 
120 2
121 
122 1 0 0
123 
124 1 1 0
125 */
View Code

 

posted @ 2018-03-14 22:05  大财主  阅读(274)  评论(0编辑  收藏  举报