Processing math: 100%

BZOJ 1043: [HAOI2008]下落的圆盘

Description

求几个圆交起来的周长..n103

Solution

计算几何.

圆圆求交..

Code

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**************************************************************
    Problem: 1043
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:520 ms
    Memory:1308 kb
****************************************************************/
  
#include <bits/stdc++.h>
using namespace std;
   
namespace CG {
    typedef double LD;
       
    const LD Pi = M_PI;
    const LD PI = 2 * acos(0.0);
    const LD eps = 1e-12;
    #define sqr(x) ((x)*(x))
       
    int dcmp(LD x) { return fabs(x)<eps?0:(x<0?-1:1); }
       
    struct Point {
        LD x,y;
        Point(LD _x=0,LD _y=0) :x(_x),y(_y) {}
        void out() { cout<<"("<<x<<","<<y<<")"; }
    };
    typedef Point Vector;
       
    int cmpx(const Point &a,const Point &b) { return dcmp(a.x-b.x)==0?a.y<b.y:a.x<b.x; }
       
    Vector operator + (const Vector &a,const Vector &b) { return Vector(a.x+b.x,a.y+b.y); }
    Vector operator - (const Vector &a,const Vector &b) { return Vector(a.x-b.x,a.y-b.y); }
    Vector operator * (const Vector &a,LD b) { return Vector(a.x*b,a.y*b); }
    Vector operator / (const Vector &a,LD b) { return Vector(a.x/b,a.y/b); }
    bool operator == (const Point &a,const Point &b) { return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; }
       
    LD Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; }
    LD Cross(Vector a,Vector b) { return a.x*b.y-b.x*a.y; }
    Vector Rot(Vector a,LD rd) { return Vector(a.x*cos(rd)-a.y*sin(rd),a.x*sin(rd)+a.y*cos(rd)); }
    LD get_l(Vector a) { return sqrt(Dot(a,a)); }
    LD get_d(Point a,Point b) { return sqrt(Dot(a-b,a-b)); }
    LD get_a(Vector a) { return atan2(a.y,a.x); }
    LD get_a(Vector a,Vector b) { return acos(Dot(a,b)/get_l(a)/get_l(b)); }
    LD get_s(Point a,Point b,Point c) { return Cross(b-a,c-a)/2.0; }
       
    struct Line {
        Point p;
        Vector v;
        Line(Point a=Point(),Point b=Point()):p(a),v(b-a) {  }
        LD get_l() { return sqrt(Dot(v,v)); }
        Point get_p(LD t) { return p+v*t; }
        Point get_s() { return p; }
        Point get_t() { return p+v; }
    };
       
    struct Circle {
        Point c;
        LD r;
        Point get_p(LD t) { return c+Point(cos(t)*r,sin(t)*r); }
        LD get_rd(Point a,Point b) { return get_a(a-c,b-c); }
        LD get_l(LD rd) { return r*rd; }
    };
       
    int get_c_l(Line L,Circle C,vector<Point> &res) {
        LD a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y;
        LD e=sqr(a)+sqr(c),f=2.0*(a*b+c*d),g=sqr(b)+sqr(d)-sqr(C.r);
        LD dt=f*f-4*e*g;
        if(dcmp(dt)<0) return 0;
        if(dcmp(dt)==0) return res.push_back(L.get_p(-f/(2.0*e))),1;
        LD x1=(-f-sqrt(dt))/(2.0*e),x2=(-f+sqrt(dt))/(2.0*e);
        if(x1>x2) swap(x1,x2);
        res.push_back(L.get_p(x1)),res.push_back(L.get_p(x2));return 2;
    }
    int get_c_c(Circle A,Circle B,vector<Point> &res) {
        LD d=get_l(A.c-B.c);
        if(dcmp(d)==0) return dcmp(A.r-B.r)==0?-1:0;
        if(dcmp(A.r+B.r-d)<0) return 0;
        if(dcmp(fabs(A.r-B.r)-d)>0) return 0;
           
        LD a=get_a(B.c-A.c);
        LD rd=acos((sqr(A.r)+sqr(d)-sqr(B.r))/(2.0*A.r*d));
           
        Point p1,p2;
        p1=A.get_p(a+rd),p2=A.get_p(a-rd);
           
        res.push_back(p1);
        if(p1==p2) return 1;
        res.push_back(p2);
        return 2;
    }
       
    /*---io---*/ 
    ostream & operator << (ostream &os,const Point &p) { os<<p.x<<" "<<p.y;return os; }
    istream & operator >> (istream &is,Point &p) { is>>p.x>>p.y;return is; }
    ostream & operator << (ostream &os,const Circle &C) { os<<C.c<<" "<<C.r;return os; }
    istream & operator >> (istream &is,Circle &C) { is>>C.c>>C.r;return is; }
};
   
using namespace CG;
  
#define mpr make_pair
   
int n;
LD ans;
vector<Circle> cr;
vector<Line> cl;
vector<Point> ls;
vector<Point> cp;
   
void add_l(vector<Point> &s,LD x,LD y) {
    if(x>y) s.push_back(Point(x,Pi)),s.push_back(Point(-Pi,y));
    else ls.push_back(Point(x,y));
}
int chk(Circle A,Circle B) {
    LD d=get_l(A.c-B.c);
    if(dcmp(B.r-A.r-d)>0) return 1;
    return 0;
}
LD get_ans(Circle c,int id) {
    ls.clear();
    //O-O jiaodian
    for(int i=id+1;i<n;i++) {
        cp.clear();
        if(chk(c,cr[i])) return 0;
        if(get_c_c(c,cr[i],cp)<2) continue;
        LD xx=get_a(cp[0]-c.c),yy=get_a(cp[1]-c.c);
        add_l(ls,yy,xx);
    }
    if(!ls.size()) return c.get_l(2*Pi);
    sort(ls.begin(),ls.end(),cmpx);
//  for(int i=0;i<(int)ls.size();i++) cout<<ls[i].x<<" "<<ls[i].y<<endl;
    LD lx=ls[0].x,ly=lx,res=0;
    for(int i=0;i<(int)ls.size();i++) {
        if(dcmp(ls[i].x-ly)>0) res+=ly-lx,lx=ls[i].x;
        ly=max(ly,ls[i].y);
    }res+=ly-lx;
    return c.get_l(2*Pi-res);
}
void Solve() {
    scanf("%d",&n);
    Circle cc;
    cr.clear(),ls.clear(),cp.clear(),ans=0;
       
    for(int i=1;i<=n;i++) {
        scanf("%lf%lf%lf",&cc.r,&cc.c.x,&cc.c.y);
        cr.push_back(cc);
    }
    for(int i=0;i<n;i++) {
        LD tmp=get_ans(cr[i],i);
        ans+=tmp;
    //  cout<<tmp<<endl;
    }printf("%.3lf\n",ans);
}
   
int main() {
    Solve();
    return 0;
}

  

posted @   北北北北屿  阅读(136)  评论(0编辑  收藏  举报
编辑推荐:
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
阅读排行:
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· 千万级的大表,如何做性能调优?
· .NET周刊【1月第1期 2025-01-05】
点击右上角即可分享
微信分享提示