bzoj1043 [HAOI2008]下落的圆盘

Posted wfj_2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1043 [HAOI2008]下落的圆盘相关的知识,希望对你有一定的参考价值。

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 <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define N (2005)
 6 
 7 using namespace std;
 8 
 9 const double pi=acos(-1.0);
10 
11 struct point{ double r,x,y; }p[N];
12 struct data{ double l,r; }st[N];
13 
14 double ans;
15 int n,top;
16 
17 il int cmp(const data &a,const data &b){ return a.l<b.l; }
18 
19 il double dis(RG int i,RG int j){
20   return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
21 }
22 
23 il int contain(RG int i,RG int j){ return p[j].r-p[i].r>=dis(i,j); }
24 
25 il double calc(RG int id){
26   for (RG int i=id+1;i<=n;++i) if (contain(id,i)) return 0;
27   for (RG int i=id+1;i<=n;++i){
28     RG double d=dis(i,id); if (contain(i,id) || p[i].r+p[id].r<=d) continue;
29     RG double t=acos((d*d+p[id].r*p[id].r-p[i].r*p[i].r)/(2*d*p[id].r));
30     RG double base=atan2(p[i].y-p[id].y,p[i].x-p[id].x);
31     st[++top]=(data){base-t,base+t};
32     if (st[top].l<0) st[top].l+=2*pi; if (st[top].r<0) st[top].r+=2*pi;
33     if (st[top].l>st[top].r) st[top+1]=(data){0,st[top].r},st[top++].r=2*pi;
34   }
35   sort(st+1,st+top+1,cmp); RG double now=0,res=0;
36   for (RG int i=1;i<=top;++i){
37     if (now<st[i].l) res+=st[i].l-now,now=st[i].r;
38     else now=max(now,st[i].r);
39   }
40   res+=2*pi-now,top=0; return res*p[id].r;
41 }
42 
43 int main(){
44 #ifndef ONLINE_JUDGE
45   freopen("circle.in","r",stdin);
46   freopen("circle.out","w",stdout);
47 #endif
48   cin>>n;
49   for (RG int i=1;i<=n;++i) scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
50   for (RG int i=1;i<=n;++i) ans+=calc(i); printf("%0.3lf\n",ans); return 0;
51 }

 

以上是关于bzoj1043 [HAOI2008]下落的圆盘的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1043: [HAOI2008]下落的圆盘

BZOJ1043:[HAOI2008]下落的圆盘——题解

bzoj1043 [HAOI2008]下落的圆盘

BZOJ 1043 HAOI2008 下落的圆盘 计算几何

bzoj1043[HAOI2008]下落的圆盘 计算几何

BZOJ 1043HNOI 2008下落的圆盘 判断圆相交+线段覆盖