码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-02 21:26:48      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:i++   can   sample   ems   转化   define   gpo   枚举   小数   

1043: [HAOI2008]下落的圆盘

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1598  Solved: 676
[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

HINT

 

Source

可以考虑后放的盘子对先放的盘子造成的覆盖影响
枚举每个盘,这个盘贡献的答案就是它的周长减去被后面的盘所覆盖的部分
圆和圆相交部分长度可以转化成线段覆盖问题来计算:算出中轴线的角度x,再计算圆心到2交点的角度y,

圆上被覆盖的弧度区间就是[x-y,x+y]
几个圆与这个圆相交,把相交覆盖的弧转化成圆上的线段,做一个线段覆盖问题就可以解决

 1 #include<bits/stdc++.h>
 2 #define reg register
 3 #define N 1005
 4 using namespace std;
 5 int n,tp;double x[N],y[N],r[N],ans;const double pi=acos(-1);struct node{double l,r;}q[N<<1];
 6 double dis(int i,int j){return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}
 7 bool con(int i,int j){return r[i]>=r[j]+dis(i,j);}
 8 bool cmp(node a,node b){return a.l<b.l;}
 9 void push(int i,int j){
10     double d,k,t,mv;
11     d=dis(i,j);k=atan2(y[j]-y[i],x[j]-x[i]);
12     t=(d*d+r[i]*r[i]-r[j]*r[j])/2/d;
13     mv=acos(t/r[i]);
14     q[++tp]=(node){k-mv,k+mv};
15 }
16 double calc(int p){
17     tp=0;
18     for(reg int i=p+1;i<=n;i++)
19     if(con(i,p))return 0;
20     for(int i=p+1;i<=n;i++){
21         if(con(p,i)||dis(i,p)>r[i]+r[p])continue;
22         push(p,i);
23     }
24     for(reg int i=1;i<=tp;i++){
25         if(q[i].l<0)q[i].l+=2*pi;
26         if(q[i].r<0)q[i].r+=2*pi;
27         if(q[i].l>q[i].r){
28             q[++tp]=(node){0,q[i].r};
29             q[i].r=2*pi;
30         }
31     }
32     sort(q+1,q+1+tp,cmp);
33     double cov=0,mx=q[1].l;
34     for(reg int i=1;i<=tp;i++){
35         mx=max(mx,q[i].l);
36         if(q[i].r<=mx)continue;
37         cov+=q[i].r-mx;mx=q[i].r;
38     }
39     double ret=r[p]*(2*pi-cov);
40     return ret;
41 }
42 
43 int main(){
44     scanf("%d",&n);
45     for(reg int i=1;i<=n;i++)
46     scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
47     for(reg int i=1;i<=n;i++)ans+=calc(i);
48     printf("%.3lf\n",ans);
49     return 0;
50 }

 

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

标签:i++   can   sample   ems   转化   define   gpo   枚举   小数   

原文地址:https://www.cnblogs.com/wsy01/p/8178841.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!