UVA 10969 Sweet Dream(圆的相交)

来源:互联网 发布:通过mac地址查找设备 编辑:程序博客网 时间:2024/06/11 10:55

Sweet Dream

Are you ready to have a sweet dream? OK! Close your eyes (Hey! Do NOT! I was kidding! How can you read the problem statement with your eyes closed? Umm! Let me think . . . Yes! There is a good solution to this problem. Simply, hand this paper to your teammate and let him read it aloud for you)!

. . . You are standing in the middle of a room and you have a handful of discs of different sizes. They are heavy. You somehow feel uncomfortable. Calm down and don’t worry! I am going to help you feel comfortable again. Simply choose one of the discs in your hand randomly and drop it on the floor. Yes! You feel a little more comfortable. Choose and drop another! Then another one! . . . And continue this process until your hands are empty. Now, you are as light as a feather and you are ready to fly away . . .

 

But don’t be so quick! Before flying away, you should solve a problem. Open your eyes and take a look at the floor. You see the discs you’ve just dropped (To the teammate reading this problem aloud: Show the contents of figure 1 to your teammate who is going to open his eyes now).

Adobe Systems

Figure 1. Discs on the floor viewed from the above


You can see that some discs are partially (or totally) covered by other discs. Your job is to compute the total perimeter of parts of the discs that you can see from the above.

Umm! I think you feel a little bit uncomfortable again. Am I right?

The Input

The first line of input contains a single integer which is the number of test cases. Each test case starts with a single integer , the number of discs originally in your hand followed by lines, the th of which containing three floating-point numbers which are , radius of the th disc and the coordinates of the point on the floor on which the disc has fallen. Two floating-point numbers are assumed to be equal if their absolute difference is less than .


The Output

Output for each test case consists of a line containing a floating-point number which is the total perimeter of part of discs that can be seen from above rounded to 3 decimal digits after the fraction point. The number should have exactly 3 digits after the fraction point.



Sample Input

3
1
10 0 0
2
5 0 0
10 0 0
2
1 0 0
1 1 0

Sample Output

62.832
62.832
10.472


题意:题意相当简单, 依次将N个圆放到平面上,求最后可见的圆弧长度和。

思路:对于每个圆,处理出它与比他后放的圆的交点(比它先放的圆不可能遮住他)。然后将交点极角排序,交点间的每一段弧只有可能都被覆盖或者都没被覆盖。只要对每个圆的每段弧进行判断是否被覆盖,就可以求出答案。要判断这段弧是否被覆盖,只需要判断这段圆弧的中点是否被之后放置的圆覆盖。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <ctime>#include <bitset>#include <algorithm>#include <set>#include <string>#include <vector>#include <list>#include <stack>#include <queue>#include <deque>using namespace std;#define LL long longconst double eps = 1e-10;const double pi = acos(-1.0);int cmp(double x) {    if(fabs(x) < eps) return 0;    if(x > 0)return 1;    return -1;}inline double sqr(double x) {    return x * x;}struct point {    double x, y;    point(){}    point(double a, double b): x(a), y(b) {}    void input(){        scanf("%lf%lf",&x,&y);    }    friend point operator + (const point &a, const point &b) {        return point(a.x + b.x, a.y + b.y);    }    friend point operator - (const point &a, const point &b) {        return point(a.x - b.x, a.y - b.y);    }    friend bool operator == (const point &a, const point &b) {        return cmp(a.x - b.x) == 0 && cmp(a.y - b.y) == 0;    }    friend bool operator < (const point &a, const point& b) {    return cmp(a.x - b.x) < 0 || cmp(a.x - b.x) == 0 && cmp (a.y - b.y) < 0;    }    friend point operator * (const point &a, const double &b) {        return point(a.x * b, a.y * b);    }    friend point operator * (const double &a, const point &b) {        return point(a * b.x, a * b.y);    }    friend point operator / (const point &a, const double &b) {        return point(a.x / b, a.y / b);    }    double norm(){        return sqrt(sqr(x) + sqr(y));    }};double det(const point &a, const point &b) {    return a.x * b.y - a.y * b.x;}double dot(const point &a, const point &b) {    return a.x * b.x + a.y * b.y;}double dist(const point &a, const point &b) {    return (a - b).norm();}double Angle(point a, point b) {    if(cmp(dot(a, b) - a.norm() * b.norm()) == 0) return 0;    if(cmp(dot(a, b) + a.norm() * b.norm()) == 0) return pi;    return acos(dot(a,b) / a.norm() / b.norm()); }double angle(point p) {return atan2(p.y, p.x);}point rotate_point(const point &p, double A){    double tx = p.x, ty = p.y;    return point(tx * cos(A) - ty * sin(A), tx * sin(A) + ty * cos(A));}point rotate_point(const point &p, double sint, double cost) {double tx = p.x, ty = p.y;return point(tx * cost - ty * sint, tx * sint + ty * cost);}struct line {    point a, b;    line(){}    line(point x, point y):a(x),b(y){}    void input() {        a.input();        b.input();    }};void point_pro_line(const point p, const point s, const point t, point &cp) {      double r = dot(t - s, p - s) / dot (t - s, t - s);    cp = s + r * (t - s);}bool point_pro_segment(const point p, const point s, const point t, point &cp) {    if(cmp(dot(p - s, t - s))<0) {    cp = s;    return 0;    }    if(cmp(dot(p - t, s - t))<0) {    cp = t;    return 0;    }    double r = dot(t - s, p - s) / dot (t - s, t - s);    cp = s + r * (t - s);    return 1;}bool point_on_segment(point p, point s, point t) {    return cmp(det(p - s, t - s))== 0 && cmp(dot(p - s, p - t)) <= 0;}bool parallel(line a, line b) {    return !cmp(det(a.a - a.b, b.a - b.b));}bool line_cross_line(line a, line b, point &res){    if(parallel(a, b)) return false;    double s1 = det(a.a - b.a, b.b - b.a);    double s2 = det(a.b - b.a, b.b - b.a);    res = (s1 * a.b - s2 * a.a) / (s1 - s2);    return true;}int segment_cross_segment(const point& a1,const point& a2,const point& b1,const point& b2, point& res) {    double c1 = det(a2 - a1, b1 - a1);    double c2 = det(a2 - a1, b2 - a1);    double c3 = det(b2 - b1, a1 - b1);    double c4 = det(b2 - b1, a2 - b1);    if (cmp(c1) * cmp(c2) < 0 && cmp(c3) * cmp(c4) < 0) {        res.x = (b1.x * c2 - b2.x * c1) / (c2 - c1);        res.y = (b1.y * c2 - b2.y * c1) / (c2 - c1);        return 1;    }    if(point_on_segment(a1, b1, b2)) {        res = a1;        return 2;    }    if(point_on_segment(a2, b1, b2)) {        res = a2;        return 2;    }    if(point_on_segment(b1, a1, a2)) {        res = b1;        return 2;    }    if(point_on_segment(b2, a1, a2)) {        res = b2;        return 2;    }    return 0;}int segment_cross_segment(const line& l1, const line& l2, point& res) {    point a1 = l1.a, a2 = l1.b, b1 = l2.a, b2 = l2.b;    double c1 = det(a2 - a1, b1 - a1);    double c2 = det(a2 - a1, b2 - a1);    double c3 = det(b2 - b1, a1 - b1);    double c4 = det(b2 - b1, a2 - b1);    if (cmp(c1) * cmp(c2) < 0 && cmp(c3) * cmp(c4) < 0) {        res.x = (b1.x * c2 - b2.x * c1) / (c2 - c1);        res.y = (b1.y * c2 - b2.y * c1) / (c2 - c1);        return 1;    }    if(point_on_segment(a1, b1, b2)) {        res = a1;        return 2;    }    if(point_on_segment(a2, b1, b2)) {        res = a2;        return 2;    }    if(point_on_segment(b1, a1, a2)) {        res = b1;        return 2;    }    if(point_on_segment(b2, a1, a2)) {        res = b2;        return 2;    }    return 0;}struct circle {point c;double r;circle() {}circle(point _c, double _r): c(_c), r(_r) {}void input() {c.input();scanf("%lf", &r);}    double perimeter() {        return 2 * pi * r;    }    double area() {        return sqr(r) * pi;    }};bool point_on_circle(const point& p, const circle& c) {    return cmp((p - c.c).norm() - c.r) == 0;}bool point_in_circle(const point& p, const circle& c) {    return cmp((p - c.c).norm() - c.r) < 0;}int circle_cross_line(line l, circle C, double &t1, double &t2, point res[]) {double a = l.b.x - l.a.x;double b = l.a.x - C.c.x;double c = l.b.y - l.a.y;double d = l.a.y - C.c.y;double e = sqr(a) + sqr(c);double f = 2 * (a * b + c * d);double g = sqr(b) + sqr(d) - sqr(C.r);double delta = f * f - 4 * e * g;    if(cmp(delta) < 0) return 0;if(cmp(delta) == 0) {t1 = t2 = -f / (2 * e);res[0] = point(l.a.x + t1 * a, l.a.y + t1 * c);return 1;}t1 = (-f - sqrt(delta)) / (2 * e);t2 = (-f + sqrt(delta)) / (2 * e);res[0] = point(l.a.x + t1 * a, l.a.y + t1 * c);res[1] = point(l.a.x + t2 * a, l.a.y + t2 * c);return 2;}int circle_cross_circle(circle C1, circle C2, point res[]) {double d = (C1.c - C2.c).norm();if(cmp(C1.r + C2.r - d) < 0 || cmp(fabs(C1.r - C2.r) - d) > 0) return 0;if(cmp(C1.r + C2.r - d) == 0 || cmp(fabs(C1.r - C2.r) - d) == 0) {        if(cmp(C2.r - C1.r) > 0) swap(C1, C2);res[0] = (C2.c - C1.c) / d * C1.r + C1.c;return 1;}double cost = (sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2 * C1.r * d);double sint = sqrt(1.0 - sqr(cost));point p = (C2.c - C1.c) / d * C1.r;res[0] = C1.c + rotate_point(p, -sint, cost);res[1] = C1.c + rotate_point(p, sint, cost);return 2;}circle now;circle cir[111];set<point> hash;vector<point> v;vector<double> rad;int n;bool cmp1(const point& a, const point& b) {return cmp(det(a - now.c, b - now.c)) > 0;}double gao(double x) {if(cmp(x - pi - pi) >= 0) return x - pi - pi;if(cmp(x) < 0) return x + pi + pi;return x;}int main() {int _;scanf("%d", &_);while(_--) {hash.clear();scanf("%d", &n);for(int i = 0; i < n; i++) {scanf("%lf", &cir[i].r);cir[i].c.input();}point p1, p2, p3;double ans = 0;for(int i = 0; i < n; i++) {rad.clear();rad.push_back(0);rad.push_back(pi + pi);for(int j = i + 1; j < n; j++) if(i != j){point p[2];if(circle_cross_circle(cir[i], cir[j], p) == 2) {double A1 = gao(angle(p[0] - cir[i].c));double A2 = gao(angle(p[1] - cir[i].c));rad.push_back(A1);rad.push_back(A2);}}sort(rad.begin(), rad.end());rad.erase(unique(rad.begin(), rad.end()), rad.end());for(int j = 1; j < rad.size(); j++) {double A = (rad[j - 1] + rad[j]) / 2;bool flag = 1;point p = point(cir[i].c.x + cir[i].r * cos(A), cir[i].c.y + cir[i].r * sin(A));for(int k = i + 1; k < n; k++) {if(point_in_circle(p, cir[k])) {flag = 0;break;}if(point_on_circle(p,cir[k]) && point_in_circle(cir[i].c, cir[k])){flag = 0;break;}}if(flag)ans += cir[i].r * (rad[j] - rad[j - 1]);}}printf("%.3f\n", ans);}return 0;}


0 0