1043: [HAOI2008]下落的圆盘

Time Limit: 10 Sec  Memory Limit: 162 MB
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

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 }

 

posted @ 2018-07-24 19:56  InWILL  阅读(274)  评论(0编辑  收藏  举报