bzoj 1043[HAOI2008]下落的圆盘 - 贪心 + 几何
1043: [HAOI2008]下落的圆盘
Time Limit: 10 Sec Memory Limit: 162 MBDescription
有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红
色线条的总长度即为所求.
Input
第一行为1个整数n,N<=1000
接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.
Output
最后的周长,保留三位小数
Sample Input
2
1 0 0
1 1 0
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 */