zoukankan      html  css  js  c++  java
  • 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
    ",ans); return 0;
    51 }
  • 相关阅读:
    MySql入门知识(一)
    一起学Android之Handler
    一起学Android之Http访问
    一起学Android之Sqlite
    一起学Android之Storage
    iOS核心动画高级技巧-1
    iOS界面流畅技巧之微博 Demo 性能优化技巧
    IOS 企业版证书($299)In-House方式发布指南
    App Store生存指南
    企业证书发布APP
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8046829.html
Copyright © 2011-2022 走看看