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

n^2枚举圆盘,用两圆圆心的向量的极角+余弦定理求某个圆覆盖了该圆的哪一段区间(用弧度表示),最后求个区间并。

注意……精度……最好再累计区间的时候,把每个区间的长度减去EPS,防止最后覆盖的总区间超过2PI一点点,使答案为负。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define EPS 0.000000001
#define INF 1000000.0
int n;
const double PI=acos(-1.0);
double rs[1001],xs[1001],ys[1001],ans;
struct Seg
{
    double l,r;
    Seg(){}
    Seg(const double &L,const double &R){l=L; r=R;}
}q[10001];
bool cmp(const Seg &a,const Seg &b)
{
    return fabs(a.l-b.l)<EPS ? a.r<b.r : a.l<b.l;
}
double sqr(const double &x)
{
    return x*x;
}
double dis(double x1,double y1,double x2,double y2)
{
    return sqrt(sqr(x1-x2)+sqr(y1-y2));
}
int main()
{
//  freopen("bzoj1043.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      scanf("%lf%lf%lf",&rs[i],&xs[i],&ys[i]);
    for(int i=1;i<=n;++i)
      {
        int e=0;
        double Lef=2.0*PI;
        for(int j=i+1;j<=n;++j)
          {
            double d=dis(xs[i],ys[i],xs[j],ys[j]);
            if(d+rs[i]-rs[j]<EPS)
              {
                Lef=0.0;
                break;
              }
            else if(d+rs[j]-rs[i]<EPS || rs[i]+rs[j]-d<-EPS)
              continue;
//          double see=(sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i];
            double jiao2=acos((sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i]);
            double jiao1=atan2(ys[j]-ys[i],xs[j]-xs[i]);
            if(jiao1<-EPS)
              jiao1+=(2.0*PI);
            if(jiao1-jiao2<-EPS)
              {
                q[++e]=Seg(0.0,jiao1+jiao2);
                q[++e]=Seg(jiao1-jiao2+2.0*PI,2.0*PI);
              }
            else if(jiao1+jiao2-2.0*PI>EPS)
              {
                q[++e]=Seg(jiao1-jiao2,2.0*PI);
                q[++e]=Seg(0.0,jiao1+jiao2-2.0*PI);
              }
            else
              q[++e]=Seg(jiao1-jiao2,jiao1+jiao2);
          }
//      for(int j=e;j;--j)
//        {
//          bool fl=0;
//          for(int k=j-1;k;--k)
//            if(!(q[j].l-q[k].r>EPS||q[k].l-q[j].r>EPS))
//              {
//                q[k].l=min(q[j].l,q[k].l);
//                q[k].r=max(q[j].r,q[k].r);
//                fl=1;
//                break;
//              }
//          if(!fl)
//            Lef-=(q[j].r-q[j].l);
//        }
        Seg now=Seg(INF,INF);
        sort(q+1,q+e+1,cmp);
        for(int j=1;j<=e;++j)
          if(j==e || q[j+1].l-q[j].l>EPS)
            {
              if(fabs(now.l-INF)<EPS) now=q[j];
              else
                {
                  if(q[j].l-now.r<EPS) now.r=max(now.r,q[j].r);
                  else
                    {
                      Lef-=(now.r-now.l);
                      now=q[j];
                    }
                }
            }
        if(fabs(now.l-INF)>=EPS)
          Lef-=(now.r-now.l);
        if(Lef>EPS)
          ans+=(Lef*rs[i]);
      }
    printf("%.3lf\n",ans);
    return 0;
}
posted @   AutSky_JadeK  阅读(170)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト
点击右上角即可分享
微信分享提示