1043: [HAOI2008]下落的圆盘
Submit: 1725 Solved: 743
[Submit][Status][Discuss]
Description
有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
这题让我想到了线段覆盖。。。输错一个double调了我一晚上
利用三角函数求出每个圆盘覆盖先前圆盘弧度的范围,最后统计总共覆盖了多少弧度,计算出没有被覆盖的弧度大小,乘以半径就是周长
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<iterator> 6 #include<vector> 7 using namespace std; 8 9 const int MAXN=1005; 10 const double pi=acos(-1.0); 11 #define sqr(x) (x)*(x) 12 13 struct Line 14 { 15 double l,r; 16 }; 17 double r[MAXN],x[MAXN],y[MAXN]; 18 vector<Line> L[MAXN]; 19 vector<Line>::iterator iter; 20 21 int n; 22 double ans; 23 24 bool cmp(Line a,Line b) 25 { 26 return a.l<b.l; 27 } 28 29 double dist(int a,int b) 30 { 31 return sqrt(sqr(x[a]-x[b])+sqr(y[a]-y[b])); 32 } 33 34 bool conta(int a,int b) 35 { 36 return r[a]-r[b]>=dist(a,b); 37 } 38 39 bool inter(int a,int b) 40 { 41 return r[a]+r[b]>=dist(a,b); 42 } 43 44 void insrad(int a,int b) 45 { 46 double d=dist(a,b); 47 double rad=acos((sqr(r[a])+sqr(d)-sqr(r[b]))/(2*r[a]*d)); 48 double st=atan2(x[a]-x[b],y[a]-y[b]); 49 if(st-rad<-pi) 50 { 51 L[a].push_back((Line){st-rad+2*pi,pi}); 52 L[a].push_back((Line){-pi,st+rad}); 53 return; 54 } 55 if(st+rad>pi) 56 { 57 L[a].push_back((Line){st-rad,pi}); 58 L[a].push_back((Line){-pi,st+rad-2*pi}); 59 return; 60 } 61 L[a].push_back((Line){st-rad,st+rad}); 62 } 63 64 double cal(int x) 65 { 66 for(int i=x+1;i<=n;i++) 67 if(conta(i,x)) return 0; 68 for(int i=x+1;i<=n;i++) 69 if(!conta(x,i)&&inter(x,i)) 70 insrad(x,i); 71 sort(L[x].begin(),L[x].end(),cmp); 72 double t=0,last=-pi; 73 for(iter=L[x].begin();iter!=L[x].end();iter++) 74 if(iter->l>last) 75 { 76 t+=iter->l-last; 77 last=iter->r; 78 } 79 else last=max(last,iter->r); 80 t+=pi-last; 81 return t*r[x]; 82 } 83 84 int main() 85 { 86 scanf("%d",&n); 87 for(int i=1;i<=n;i++) 88 scanf("%lf %lf %lf",&r[i],&x[i],&y[i]); 89 for(int i=1;i<=n;i++) 90 ans+=cal(i); 91 printf("%.3lf\n",ans); 92 return 0; 93 }