zoukankan      html  css  js  c++  java
  • Bzoj1313 [HAOI2008]下落的圆盘

    有 n 个圆盘从天而降,后面落下的可以盖住前面的。最后按掉下的顺序,在平面上依次测得每个圆盘的圆心和半径,问下落完成后从上往下看,整个图形的周长是多少,即你可以看到的圆盘的轮廓的圆盘的轮廓总长.例如下图的黑色线条的总长度即为所求。

    【输入格式】

    第一行为1个整数n

    接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.

    【输出格式】

    仅一个实数,表示所求的总周长,答案保留3位小数.

    【样例输入】

    2
    1 0 0
    1 1 0
    

    【样例输出】

    10.472

    【提示】

    30%的数据,n<=10

    100%的数据,n<=1000

    数学问题 计算几何

    用余弦定理和三角函数可以计算出两圆相交部分的弧长。

    对于每个圆,计算它和在它之后落下的所有圆的角。记录相交部分的弧对应的圆心角范围。将“圆心角”区间离散到0~2pi的数轴上,做线段覆盖。

    知道了未被覆盖的角总共有多大,就能算出该圆未被覆盖的弧有多长。

    注意如果求出的覆盖部分圆心角范围超出了0~2pi,要变换到0~2pi范围内

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<vector>
     7 using namespace std;
     8 const double pi=acos(-1.0);
     9 const double eps=1e-7;
    10 const int mxn=1010;
    11 struct point{
    12     double x,y;
    13     point operator + (point b){return (point){x+b.x,y+b.y};}
    14     point operator - (point b){return (point){x-b.x,y-b.y};}
    15     double operator * (point b){return x*b.x+y*b.y;}
    16 };
    17 inline double Cross(point a,point b){
    18     return a.x*b.y-a.y*b.x;
    19 }
    20 inline double dist(point a,point b){
    21     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    22 }
    23 inline double Len(point a){return sqrt(a*a);}
    24 struct cir{
    25     double x,y;
    26     double r;
    27     point operator + (cir b){return (point){x+b.x,y+b.y};}
    28     point operator - (cir b){return (point){x-b.x,y-b.y};}
    29 }c[mxn];
    30 inline bool cover(cir a,cir b){
    31     return (a.r>=b.r+Len(a-b));
    32 }
    33 struct line{
    34     double l,r;
    35     bool operator < (line b)const{
    36         return (l<b.l)|| (l==b.l && r<b.r);
    37     }
    38 };
    39 line CX(cir a,cir b){
    40     double dis=Len(b-a);
    41     double angle=acos((a.r*a.r+dis*dis-b.r*b.r)/(2*a.r*dis));
    42     double deg=atan2(a.x-b.x,a.y-b.y);//统一旋转pi角度,保证在-2pi~2pi范围内
    43     return (line){deg-angle,deg+angle};
    44 /*    double t=(a.r*a.r+dis*dis-b.r*b.r)/(2*dis);
    45     double st=atan2(a.x-b.x,a.y-b.y);
    46     double l=acos(t/a.r);
    47     return (line){st-l,st+l};*/
    48 }
    49 vector<line>ve;
    50 int n;
    51 double ans=0;
    52 void calc(int x){
    53     for(int i=x+1;i<=n;i++){if(cover(c[i],c[x]))return;}//被完全覆盖 
    54     ve.clear();
    55     for(int i=x+1;i<=n;i++){
    56         if(cover(c[x],c[i]))continue;//完全覆盖
    57         line tmp;
    58         if(c[x].r+c[i].r>Len(c[i]-c[x])) tmp=CX(c[x],c[i]);
    59         else continue;
    60         if(tmp.l<0) tmp.l+=2*pi;
    61         if(tmp.r<0) tmp.r+=2*pi;
    62         if(tmp.l>tmp.r){//拆分 
    63             ve.push_back((line){0,tmp.r});
    64             ve.push_back((line){tmp.l,2*pi});
    65         }
    66         else ve.push_back(tmp);
    67     }
    68     sort(ve.begin(),ve.end());
    69 //    printf("mid
    ");
    70     double now=0,ran=0;
    71     for(int i=0;i<ve.size();i++){//线段覆盖 
    72         line tmp=ve[i];
    73 //        printf("i:%d %.3f %.3f
    ",i,tmp.l,tmp.r);
    74         if(tmp.l>now){ran+=tmp.l-now;now=tmp.r;}
    75         else now=max(now,tmp.r);
    76     }
    77     ran+=2*pi-now;
    78     ans+=c[x].r*ran;//累加半径 
    79     return;
    80 }
    81 int main(){
    82     freopen("disc.in","r",stdin);
    83     freopen("disc.out","w",stdout);
    84     int i,j;
    85     scanf("%d",&n);
    86     for(i=1;i<=n;i++){
    87         scanf("%lf%lf%lf",&c[i].r,&c[i].x,&c[i].y);
    88     }
    89     for(i=n;i>=1;i--){
    90         calc(i);
    91 //        printf("ans:%.3f
    ",ans);
    92     }
    93     printf("%.3f
    ",ans);
    94     return 0;
    95 }
  • 相关阅读:
    51nod 1067 Bash游戏 V2
    洛谷 P1454 圣诞夜的极光 == codevs 1293 送给圣诞夜的极光
    bzoj4754: [Jsoi2016]独特的树叶
    bzoj 4241: 历史研究
    bzoj 1266 [AHOI2006] 上学路线
    bzoj4571: [Scoi2016]美味
    bzoj4570: [Scoi2016]妖怪
    51nod 1238 最小公倍数之和 V3
    一个康托展开的板子
    poweroj1745: 餐巾计划问题
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6676170.html
Copyright © 2011-2022 走看看