# BZOJ 1043 HAOI 2008 下落的圆盘 计算几何

∠EAC就是我们要求的角。由于我们知道|AE|和|EC|分别是两个圆的半径，|AC|是圆心的距离，边都知道了就可以用余弦定理来求解任意一个角了。知道了这个角的大小，用向量(A->C)的极角加上∠EAC就是E点所代表的位置，减去∠EAC就是F点所代表的位置。这样就可以表示出两圆相交的区间了。

CODE：

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define PI acos(-1.0)
#define MAX 1010
using namespace std;

struct Point{
double x,y;

Point(double _ = .0,double __ = .0):x(_),y(__) {}
Point operator -(const Point &a)const {
return Point(x - a.x,y - a.y);
}
scanf("%lf%lf",&x,&y);
}
};
struct Circle{
Point o;
double r;

scanf("%lf",&r);
}
}circle[MAX];

struct Interval{
double st,ed;

Interval(double _ = .0,double __ = .0):st(_),ed(__) {}
bool operator <(const Interval &a)const {
if(st == a.st)	return ed < a.ed;
return st < a.st;
}
}interval[MAX];

int circles,cnt;
double ans;

inline double Calc(const Point &p1,const Point &p2)
{
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

inline void InsertInterval(const Circle &a,const Circle &b)
{
double dis = Calc(a.o,b.o);
if(dis > a.r + b.r)	return ;
if(dis < a.r - b.r)	return ;
if(dis < b.r - a.r) {
interval[++cnt] = Interval(.0,2.0 * PI);
return ;
}
Point u = b.o - a.o;
double alpha = atan2(u.y,u.x) + PI;
double detla = acos((a.r * a.r + dis * dis - b.r * b.r) / (2.0 * a.r * dis));
if(alpha - detla < 0) {
interval[++cnt] = Interval(alpha - detla + 2.0 * PI,2.0 * PI);
interval[++cnt] = Interval(0,alpha + detla);
}
else if(alpha + detla > 2.0 * PI) {
interval[++cnt] = Interval(alpha - detla,2.0 * PI);
interval[++cnt] = Interval(0,alpha + detla - 2.0 * PI);
}
else
interval[++cnt] = Interval(alpha - detla,alpha + detla);
}

int main()
{
cin >> circles;
for(int i = 1; i <= circles; ++i)
for(int i = circles; i; --i) {
cnt = 0;
for(int j = i + 1; j <= circles; ++j)
InsertInterval(circle[i],circle[j]);
sort(interval + 1,interval + cnt + 1);
double start = .0,end = .0;
double length = .0;
for(int j = 1; j <= cnt; ++j)
if(interval[j].st > end)
length += end - start,start = interval[j].st,end = interval[j].ed;
else
end = max(end,interval[j].ed);
length += end - start;
length = PI * 2.0 - length;
ans += length * circle[i].r;
}
cout << fixed << setprecision(3) << ans << endl;
return 0;
}

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客