Topic Link: UVA 1308-viva confetti
Enumerate the two circles, process all arcs, and then determine whether the midpoint of each arc is visible, the circle where the arc is visible, and the circle below the arc is also visible.
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm >using namespace Std;const Double pi = 4 * atan (1); const double EPS = 1e-14;inline int dcmp (double x) {if (Fabs (x) &L T EPS) return 0; else return x < 0? -1:1; }inline double getdistance (double x, double y) {return sqrt (x * x + y * y);} struct point {double x, y; Point (Double x = 0, double y = 0): x (x), Y (y) {}void read () {scanf ("%lf%lf", &x, &y);} void Write () {printf ("%lf%lf", x, y);} BOOL operator = = (CONST point& u) Const {return dcmp (x-u.x) = = 0 && dcmp (y-u.y) = = 0;} BOOL operator! = (const point& u) Const {return! ( *this = = u); }bool operator < (const point& u) Const {return x < u.x | | (x = = u.x && y < u.y); }bool operator > (const point& u) Const {return u < *this;} BOOL operator <= (const point& u) Const {return *this < u | | *this = u;} BOOL operator >= (const point&u) Const {return *this > U | | *this = = u;} Point operator + (const point& u) {return point (x + u.x, y + u.y);} Point operator-(const point& u) {return point (x-u.x, y-u.y);} Point operator * (const double u) {return point (x * u, y * u);} Point operator/(const double u) {return point (x/u, y/u);}}; typedef point VECTOR;STRUCT Line {Double A, B, C; Line (Double A = 0, double b = 0, double c = 0): A (a), B (b), C (c) {}};struct Circle {point o;double R; Circle () {}circle (Point O, double r = 0): O (O), R (r) {}point point (double rad) {return point (o.x + cos (rad) *r, O.y + si N (RAD) *r); }void Read () {scanf ("%lf%lf%lf", &o.x, &o.y, &r);}}; Namespace punctual {Double getdistance (point A, point B) {double x=a.x-b.x, y=a.y-b.y; return sqrt (x*x + y*y);}}; namespace Vectorial {/* dot product: The product of two vector lengths multiplied by the cosine of their angle, the angle is greater than 90 degrees the product is negative */double Getdot (vector A, vector b) {return a.x * b.x + A.Y * B.Y; }/* Cross product: The cross product is equal to two vectors consisting of a triangle with a direction area of twice times, crosses (V, w) =-cross (W, v) */double Getcross (VecTor A, Vector b) {return a.x * b.y-a.y * b.x;} Double GetLength (Vector a) {return sqrt (Getdot (A, a)); Double Getangle (Vector u) {return atan2 (u.y, u.x);} Double Getangle (vector A, vector b) {return ACOs (Getdot (A, B)/GetLength (a)/GetLength (b));} Vector Rotate (vector A, double rad) {return vector (A.x*cos (RAD)-a.y*sin (RAD), A.x*sin (RAD) +a.y*cos (RAD));} /* unit normal */vector Getnormal (Vector a) {double L = getlength (a); return Vector (-a.y/l, a.x/l);}}; Namespace Linear {using namespace vectorial; Line GetLine (double x1, double y1, double x2, double y2) {return line (y2-y1, x1-x2, y1* (x2-x1)-x1* (y2-y1));} Line GetLine (double A, double b, point u) {return line (A, B, u.y * b-u.x * a);} BOOL Getintersection (line p, line Q, point& o) {if (Fabs (P.A * q.b-q.a * p.b) < EPS) return false;o.x = (Q.C * p. B-P.C * q.b)/(P.A * q.b-q.a * p.b); o.y = (Q.C * p.a-p.c * q.a)/(P.B * q.a-q.b * p.a); return true;} /* Intersection of linear PV and line QW */bool getintersection (point P, Vector V, PoiNT Q, Vector W, point& o) {if (dcmp (Getcross (V, w)) = = 0) return false; Vector u = p-q;double k = Getcross (w, u)/Getcross (V, w); o = p + v * K;return true;} /* points P to line ab distance */double getdistancetoline (point P, dot a, bit b) {return fabs (Getcross (b-a, p-a)/GetLength (B-A));} Double getdistancetosegment (point P, point A, point B) {if (a = = b) return getlength (P-A); Vector v1 = b-a, v2 = p-a, V3 = p-b;if (dcmp (Getdot, V1) < 0) return v2 (getlength); else if (V2 (dcmp (Getdot, V 3)) > 0) return GetLength (V3), Else return fabs (Getcross (v1, v2)/GetLength (v1));} /* point P on the line ab projection */point getpointtoline (points P, a, point B) {Vector v = b-a; return a+v* (Getdot (V, p-a)/Getdot (V, v)); }/* to determine if a segment has an intersection */bool haveintersection (Point A1, Point A2, point B1, point B2) {double C1=getcross (a2-a1, b1-a1), c2=getc Ross (A2-A1, B2-A1), C3=getcross (B2-B1, A1-B1), C4=getcross (B2-B1,A2-B1), return dcmp (C1) *dcmp (C2) < 0 && dcmp (C3) *dcmp (C4) < 0;} /* Determine if the point is */bool on the segment OnsegmenT (point P, point A, point B) {return dcmp (Getcross (A-p, b-p)) = = 0 && dcmp (Getdot (A-p, b-p)) < 0;}} Namespace triangular {using namespace vectorial;double getangle (double A, double b, double c) {return ACOs ((a*a+b*b-c*c) /(2*a*b)); }double Getarea (Double A, double b, double c) {double s = (a+b+c)/2; return sqrt (s* (s-a) * (s-b) * (S-C));} Double Getarea (Double A, double h) {return a * H/2;} Double Getarea (Point A, point B, point C) {return fabs (Getcross (b-a, c-a))/2;}}; Namespace polygonal {using namespace vectorial;double Getarea (point* p, int n) {double ret = 0;for (int i = 1; i < n-1 ; i++) ret + = Getcross (P[i]-p[0], p[i+1]-p[0]); return fabs (ret)/2;}}; Namespace Circular {using namespace vectorial;using namespace linear;/* line and original intersection */int getlinecircleintersection (Point P, Point Q, Circle O, double& t1, double& T2, vector<point>& sol) {vector v = q-p;/* need to empty Sol *///sol.c before use Lear ();d ouble a = v.x, B = p.x-o.o.x, c = v.y, d = P.y-o.o.y;double e = a*a+c*c, F = a*b+c*d, G = b*b+d*d-o.r*o.r;double Delta = f*f-4*e*g;if (dcmp (Delta) < 0) return 0;if (dcmp (delta) = = 0) {T1 = t2 =-F/(2 * e); Sol.push_back (P + v * t1); return 1;} T1 = (-f-sqrt (delta))/(2 * e); Sol.push_back (p + v * t1); t2 = (-f + sqrt (delta))/(2 * e); Sol.push_back (p + v * T2); return 2;} /* Circle intersection */int getcirclecircleintersection (Circle O1, Circle O2, vector<point>& sol) {Double d = getlength (O1. O-O2.O); if (dcmp (d) = = 0) {if (dcmp (O1.R-O2.R) = = 0) Return-1;return 0;} if (dcmp (O1.R + o2.r-d) < 0) return 0;if (DCMP (fabs)-D) > 0) return O1.R-O2.R a = 0;double (Getangle) ;d ouble da = ACOs ((O1.R*O1.R + D*D-O2.R*O2.R)/(2*o1.r*d)); Point P1 = O1.point (a-da), p2 = O1.point (A+da), Sol.push_back (p1), if (P1 = = p2) return 1;sol.push_back (P2); return 2;} /* tangents */int gettangents (point P, Circle O, vector* v) {Vector U = o.o-p;double d = getlength (u); if (d < O.R) R Eturn 0;else if (dcmp (D-O.R) = = 0) {V[0] = rotate(U, PI/2); return 1;} else {Double ang = asin (O.R/D); v[0] = rotate (u,-ang); v[1] = rotate (U, ANG); return 2;}} /* A[i] and b[i] are the tangency points of the section I tangent on O1 and O2 respectively */int gettangents (Circle O1, Circle O2, point* A, point* b) {int cnt = 0;IF (O1.R < O2.R) {swap (O1, O2); swap (A, b);} Double D2 = GetLength (O1.O-O2.O); D2 = D2 * d2;double rdif = O1.R-O2.R, rsum = O1.R + o2.r;if (D2 < RDIF * Rdif) return 0;if (dcmp (d2) = = 0 && DCMP (O1.R-O2.R) = = 0) return-1;double base = Getangle (O2.O-O1.O); if (dcmp (D2-RDIF * rdif) = = 0) {a[cnt] = O1.point ( Base); B[CNT] = O2.point (base); Cnt++;return CNT;} Double ang = ACOs ((O1.R-O2.R)/sqrt (D2)); a[cnt] = O1.point (Base+ang); B[CNT] = O2.point (Base+ang); CNT++;A[CNT] = O1.point (Base-ang); B[CNT] = O2.point (Base-ang); Cnt++;if (dcmp (d2-rsum * rsum) = = 0) {a[cnt] = O1.point (base); b[cnt] = O2.point (base); cnt++;} else if (D2 > Rsum * rsum) {Double ang = ACOs ((O1.R + O2.R)/sqrt (D2)); a[cnt] = O1.point (Base+ang); b[cnt] = O2.point (Base+ang);CNT++;A[CNT] = O1.point (Base-ang); B[CNT] = O2.point (Base-ang); cnt++;} return CNT;} /* Three points to determine the tangent circle */circle circumscribedcircle (Point P1, Spot, point P3) {Double Bx = p2.x-p1.x, by = P2.Y-P1.Y; Double Cx = p3.x-p1.x, Cy = p3.y-p1.y; Double D = 2 * (Bx * cy-by * Cx); Double CX = (Cy * (BX * bx + by *) – by * (CX * CX + cy * cy))/D + p1.x; Double cy = (BX * (CX * CX + cy * CY)-CX * (BX * bx + by *))/D + p1.y; Point P = Point (CX, CY); Return Circle (P, GetLength (p1-p)); }/* three to determine inscribed circle */circle inscribedcircle (Point P1, points P2, dot p3) {Double A = GetLength (P2-P3); Double b = getlength (P3-P1); Double c = getlength (P1-P2); Point P = (P1 * A + P2 * b + p3 * c)/(A + B + c); Return Circle (P, Getdistancetoline (P, p1, p2)); }};using namespace vectorial;using namespace Circular;const int maxn = 105;int N, VIS[MAXN]; Circle o[maxn];vector<double> Rad[maxn];int Main () {while (scanf ("%d", &n) = = 1 && N) {memset (Vis, 0, s Izeof (Vis)); foR (int i = 1; I <= N; i++) O[i].read (); for (int i = 1; I <= N; i++) {vector<point> sol;for (int j = 1; J <= N J + +) Getcirclecircleintersection (O[i], o[j], sol); Rad[i].clear (); rad[i].push_back (0); for (int j = 0; J < Sol.size (); j + +) Rad[i].push_back (Getangle (Sol[j]-O[I].O)), if (rad[i].size () = = 0) rad[i].push_back (2*PI); sort (Rad[i].begin (), Rad[i].end ());} for (int i = 1; I <= N, i++) {for (int j = 0, J < rad[i].size (); + j) {point u;if (j) u = O[i].point ((rad[i][j] + rad I [J-1]) /2); Elseu = O[i].point ((Rad[i][j] + rad[i][rad[i].size ()-1])/2 + pi), BOOL flag = true;for (int k = i + 1; k <= N; +) {if (dcmp (GetLength (U-O[K].O)-O[K].R) <= 0) {flag = false; break;}} if (flag) {Vis[i] = 1;for (int k = i-1; k >= 0; k--) {if (dcmp (getlength)-U-O[K].O) O[K].R 0) {<=] = 1; br Eak;}}}} int ans = 0;for (int i = 1; I <= N; i++) if (Vis[i]) ans++;p rintf ("%d\n", ans);} return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
UVA 1308-viva Confetti (geometry)