zoukankan      html  css  js  c++  java
  • [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
    枚举每一个圆,看它有多少没有被覆盖。
    每一个圆的极角可以拉直成一个长为2×pi的线段
    然后套用数学公式,算出一个圆覆盖的范围
    要注意讨论极角小于0的情况
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 struct ZYYS
     8 {
     9   double l,r;
    10 }a[5001];
    11 double pi=acos(-1.0);
    12 int n;
    13 double x[1001],y[1001],r[1001],ans;
    14 bool cmp(ZYYS a,ZYYS b)
    15 {
    16   return a.l<b.l;
    17 }
    18 double dist(int i,int j)
    19 {
    20   return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
    21 }
    22 bool contain(int i,int j)
    23 {
    24   if (r[i]-r[j]>=dist(i,j)) return 1;
    25   return 0;
    26 }
    27 double cal(int o)
    28 {int i;
    29   int cnt=0;
    30   for (i=o+1;i<=n;i++)
    31     if (contain(i,o)) return 0;
    32   for (i=o+1;i<=n;i++)
    33     {
    34       if (contain(o,i)||dist(o,i)>=r[i]+r[o]) continue;
    35       double d=dist(o,i);
    36       double xt=acos((-r[i]*r[i]+r[o]*r[o]+d*d)/(2.0*d*r[o]));
    37       double aef=atan2(y[i]-y[o],x[i]-x[o]);
    38       a[++cnt]=(ZYYS){aef-xt,aef+xt};
    39       if (a[cnt].l<0) a[cnt].l+=2*pi;
    40       if (a[cnt].r<0) a[cnt].r+=2*pi;
    41       if (a[cnt].l>a[cnt].r)
    42     {
    43       double p=a[cnt].l;                                                                                          
    44       a[cnt].l=0;
    45       a[++cnt].l=p;a[cnt].r=2*pi;
    46     }
    47     }
    48   sort(a+1,a+cnt+1,cmp);
    49   double res=0,now=0;
    50   for (i=1;i<=cnt;i++)
    51     {
    52       if (a[i].l>now) res+=a[i].l-now,now=a[i].r;
    53       now=max(now,a[i].r);
    54     }
    55   res+=2*pi-now;
    56   return res*r[o];
    57 }
    58 int main()
    59 {int i;
    60   cin>>n;
    61   for (i=1;i<=n;i++)
    62     {
    63       scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
    64     }
    65   for (i=1;i<=n-1;i++)
    66     ans+=cal(i);
    67   ans+=2*pi*r[n];
    68   printf("%.3lf
    ",ans);
    69 }
  • 相关阅读:
    PHP版根据经纬度和半径计算出经纬度的范围
    使用GPS经纬度定位附近地点(某一点范围内查询)
    sql语句查询经纬度范围
    Android检测是否安装了指定应用
    Android 定时器实现的几种方式和removeCallbacks失效问题详解
    Android Service与Activity之间通信的几种方式
    Android操作系统11种传感器介绍
    Android录音--AudioRecord、MediaRecorder
    Android广播接收者应用(电话拦截器)
    收藏夹
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8268963.html
Copyright © 2011-2022 走看看