#include <bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
const double PI = acos(-1);
int T, n;
struct Point
{
double x, y;
Point(double x = 0, double y = 0): x(x), y(y) {}
};
typedef Point Vector;
typedef vector<Point> Polygon;
Vector operator +(Vector A, Vector B)//
{
return Vector(A.x + B.x, A.y + B.y);
}
Vector operator -(Point A, Point B)//
{
return Vector(A.x - B.x , A.y - B.y);
}
Vector operator *(Vector A, double p)//
{
return Vector(A.x * p, A.y * p);
}
Vector operator /(Vector A, double p)//
{
return Vector(A.x / p, A.y / p);
}
bool operator <(const Point &a, const Point &b)//
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
const double eps = 1e-10;
int dcmp(double x)//
{
if (fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
bool operator ==(const Point &a, const Point &b)//
{
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
struct Circle
{
Point c;
double r;
Circle(Point c, double r): c(c), r(r) {}
Circle() {}
Point point(double a)
{
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};
double Dot(Vector A, Vector B)//
{
return A.x * B.x + A.y * B.y;
}
double Length(Vector A)//
{
return sqrt(Dot(A, A));
}
double normal(double rad)
{
return rad - 2.0 * PI * floor(rad / 2 / PI);
}
double angle(Vector v) {return atan2(v.y, v.x);}
int getCircleCircleIntersection(Circle C1, Circle C2, vector<double>& sol)
{
double d = Length(C1.c - C2.c);
if (dcmp(d) == 0)
{
if (dcmp(C1.r - C2.r) == 0) return -1; // 重合,无穷多交点
return 0;
}
if (dcmp(C1.r + C2.r - d) < 0) return 0;
if (dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;
double a = angle(C2.c - C1.c);
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));
//Point p1 = C1.point(a - da), p2 = C1.point(a + da);
double k1 = normal(a - da), k2 = normal(a + da);
sol.push_back(k1);
if (k1 == k2) return 1;
sol.push_back(k2);
return 2;
}
void read_circle(Circle &p)
{
double X, Y, R;
scanf("%lf%lf%lf", &R, &X, &Y);
p = Circle(Point(X, Y), R);
}
Circle cir[maxn];
bool judge(int cur, Point p)
{
for (int i = n - 1; i > cur; i--)
if (dcmp(Length(cir[i].c - p) - cir[i].r) <= 0) return false;
return true;
}
int main(int argc, char const *argv[])
{
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
read_circle(cir[i]);
double ans = 0;
for (int i = n - 1; i >= 0; i--)
{
vector<double>v;
v.push_back(0), v.push_back(2 * PI);
for (int j = n - 1; j > i; j--)
getCircleCircleIntersection(cir[i], cir[j], v);
sort(v.begin(), v.end());
double tmp = 0;
for (int j = 0; j < v.size() - 1; j++)
{
double mid = (v[j] + v[j + 1]) / 2.0;
if (judge(i, cir[i].point(mid))) tmp += v[j + 1] - v[j];
}
ans += tmp * cir[i].r;
}
printf("%.3lf\n", ans);
}
return 0;
}
题意:平面上依次放置n个圆,后放的覆盖先放的,按顺序给出每个圆的半径和圆心坐标,问最后图形的可见圆弧长之和。
题解:因为是后放的覆盖先放的,所以逆序枚举,每个圆只考虑之前放过的圆和自己的交点,把所有交点排序后可以得到每两个相邻的交点之间的圆弧,找到圆弧中点,如果这个点在之前放过的圆内,说明这个圆弧不能要,否则加到答案里。注意弧度要规范到0~2π。
题解来自:http://blog.csdn.net/hyczms/article/details/47266881