zoukankan      html  css  js  c++  java
  • BZOJ 1043 下落的圆盘

    Description

    有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红色线条的总长度即为所求. 

    Input

    n ri xi y1 ... rn xn yn

    Output

    最后的周长,保留三位小数

    Sample Input

    2
    1 0 0
    1 1 0

    Sample Output

    10.472

    HINT

    数据规模

    n<=1000

    这道题目很好嘴巴,但是写起来有点儿蛋疼。
    首先求出每个圆盘被他上面的圆盘覆盖的圆心角的度数α,用(2π-α)*c/2π即每个圆盘的周长答案,最后累加一遍答案即可。
    那么圆心角要怎么求呢???
    算出两个圆的交点肯定是没戏的(我推了很久的公式,还是退错了),后面想想,好像不用去求交点,可以直接用圆心角来计算区间。
    如图若两圆C1,C2有交点(C2覆盖C1),则我们可以算出射线C1C2的极角θ。C1被C2所覆盖的圆心角的区间为[θ-α,θ+α]。但是注意,区间可能有越界的情况,比如说我们的区间是(-π,π]他的被覆盖的极角区间就是许多区间的并,但他可能和有[-1.2π,-0.7π],这时我们需要将区间拆开进行处理。比如此例中,我们拆成[-π,-0.7π]与[0.8π,π]。
    还有一种情况就是C1的圆心在C2中,α的值为其补角。(自己画画图)。
      1 #include<iostream>
      2 #include<cmath>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<cstdlib>
      6 using namespace std;
      7 
      8 #define pi (3.1415926535)
      9 #define esp (1e-6)
     10 #define maxn 2010
     11 int n; double ans;
     12 
     13 inline bool equal(double a,double b) { return fabs(a - b) < esp; }
     14 
     15 inline double qua(double a) { return a * a; } 
     16 
     17 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; } //>=
     18 
     19 inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; } //<=
     20 
     21 struct NODE{ double x,y; };
     22 struct angle
     23 {
     24     double a1,a2;
     25     friend inline bool operator < (angle a,angle b)
     26     {
     27         if (!equal(a.a1,b.a1)) return xd(a.a1,b.a1);
     28         return xd(a.a2,b.a2);
     29     }
     30 }bac[maxn];
     31 struct CIR
     32 {
     33     double r,x,y;
     34     inline void read() { scanf("%lf %lf %lf",&r,&x,&y); }
     35     inline NODE mid() { return (NODE) {x,y}; }
     36     inline double calc(NODE p) { return atan2(p.y-y,p.x-x); }
     37     inline double C() { return 2*pi*r; }
     38 }cir[maxn];
     39 struct LINE
     40 {
     41     double a,b,c;
     42     inline double dis(NODE p) { return fabs(a*p.x+b*p.y+c)/sqrt(qua(a)+qua(b)); }
     43     inline double key(NODE p) { return p.x*a+p.y*b+c; }
     44 };
     45 
     46 inline double dis(NODE a,NODE b) { return sqrt(qua(a.x-b.x) + qua(a.y-b.y)); }
     47 
     48 inline bool have(CIR c1,CIR c2) { return dis(c1.mid(),c2.mid())<c1.r+c2.r; }
     49 
     50 inline bool cat(CIR c1,CIR c2) { return xd(dis(c1.mid(),c2.mid()),fabs(c1.r-c2.r)); }
     51 
     52 inline LINE cross(CIR c1,CIR c2) { return (LINE) {2*(c2.x-c1.x),2*(c2.y-c1.y),(qua(c2.r)-qua(c2.x)-qua(c2.y))-(qua(c1.r)-qua(c1.x)-qua(c1.y))}; }
     53 
     54 inline void work()
     55 {
     56     int tot,i,j; double rest,p,q,a,b,now; LINE l;
     57     for (i = n;i;--i)
     58     {
     59         tot = 0; rest = 0; now = 0;
     60         for (j = i+1;j <= n;++j)
     61         {
     62             if (cat(cir[i],cir[j]))
     63             {
     64                 if (cir[i].r > cir[j].r) continue;
     65                 else break;
     66             }
     67             if (have(cir[i],cir[j]))
     68             {
     69                 p = cir[i].calc(cir[j].mid()) + pi;
     70                 l = cross(cir[i],cir[j]);
     71                 q = l.dis(cir[i].mid());
     72                 q = acos(q/cir[i].r);
     73                 if (cir[i].r < cir[j].r&&l.key(cir[i].mid())*l.key(cir[j].mid()) > 0)
     74                     q = pi - q;
     75                 a = p - q; b = p + q;
     76                 if (dd(a,0) && xd(b,2*pi))
     77                     bac[++tot] = (angle) {a,b};
     78                 else if (a < 0)
     79                 {
     80                     bac[++tot] = (angle) {a+2*pi,2*pi};
     81                     bac[++tot] = (angle) {0,b};
     82                 }
     83                 else
     84                 {
     85                     bac[++tot] = (angle) {a,2*pi};
     86                     bac[++tot] = (angle) {0,b-2*pi};
     87                 }
     88             }
     89         }
     90         if (j != n+1) continue;
     91         sort(bac+1,bac+tot+1);
     92         for (int j = 1;j <= tot;++j)
     93         {
     94             if (bac[j].a1 > now)
     95             {
     96                 rest += bac[j].a1 - now;
     97                 now = bac[j].a2;
     98             }
     99             else now = max(now,bac[j].a2);
    100         }
    101         rest += 2*pi - now;
    102         ans += rest/(2*pi) * cir[i].C();
    103     }
    104 }
    105 
    106 int main()
    107 {
    108     freopen("1043.in","r",stdin);
    109     freopen("1043.out","w",stdout);
    110     scanf("%d",&n);
    111     for (int i = 1;i <= n;++i) cir[i].read();
    112     work();
    113     printf("%.3lf",ans);
    114     fclose(stdin); fclose(stdout);
    115     return 0;
    116 }
    View Code
  • 相关阅读:
    centos 用户管理
    rsync 实验
    文件共享和传输
    PAT 1109 Group Photo
    PAT 1108 Finding Average
    PAT 1107 Social Clusters
    PAT 1106 Lowest Price in Supply Chain
    PAT 1105 Spiral Matrix
    PAT 1104 Sum of Number Segments
    PAT 1103 Integer Factorization
  • 原文地址:https://www.cnblogs.com/mmlz/p/4281333.html
Copyright © 2011-2022 走看看