POJ 1375 - Intervals
http://poj.org/problem?id=1375
概要
二次元平面上にひとつの光源と N 個の円があり,X 軸に床がある. すべての円は光源より低く,床より高い位置にある.
円は光を通さず,反射もしないとする.
このとき,床の上で円によって光が遮られている区間をすべて答える.
制約
- N < 500
- 円と円が重なっていることはない
- 円の中に光源があることはない
解法
光源から各円への接線を求め,それと床との交点を求めて区間を列挙した後, ソートして被っている区間をマージしながら答える.
poj/1375.cc1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 #include <complex> 5 #include <cmath> 6 using namespace std; 7 typedef complex<double> P; 8 static const double EPS = 1e-6; 9 10 inline double cross(const P& a, const P& b) { return a.real()*b.imag() - b.real()*a.imag(); } 11 12 struct line 13 { 14 P a, b; 15 line() {} 16 line(const P& p, const P& q) : a(p), b(q) {} 17 18 inline P intersection(const line& ln) const 19 { 20 const P x = b - a; 21 const P y = ln.b - ln.a; 22 return a + x*(cross(y, ln.a - a))/cross(y, x); 23 } 24 }; 25 26 struct circle 27 { 28 P o; 29 double r; 30 circle() {} 31 circle(const P& p, double x) : o(p), r(x) {} 32 33 pair<P,P> tangent(const P& p) const 34 { 35 const double L = abs(o - p); 36 const double M = sqrt(L*L - r*r); 37 const double theta = asin(r / L); 38 const P v = (o - p) / L; 39 return make_pair(p + M*(v*polar(1.0, theta)), p + M*(v*polar(1.0, -theta))); 40 } 41 }; 42 43 int main() 44 { 45 int N; 46 while (scanf("%d", &N) != EOF && N != 0) { 47 int bx, by; 48 scanf("%d %d", &bx, &by); 49 const P o(bx, by); 50 const line base(P(0, 0), P(1, 0)); 51 vector<pair<double,double> > intervals(N); 52 for (int i = 0; i < N; i++) { 53 int x, y, r; 54 scanf("%d %d %d", &x, &y, &r); 55 const pair<P,P> ps = circle(P(x, y), r).tangent(o); 56 intervals[i] = make_pair( 57 base.intersection(line(o, ps.first)).real(), 58 base.intersection(line(o, ps.second)).real()); 59 if (intervals[i].first > intervals[i].second) { 60 swap(intervals[i].first, intervals[i].second); 61 } 62 } 63 64 sort(intervals.begin(), intervals.end()); 65 pair<double,double> r = intervals[0]; 66 for (int i = 1; i < N; i++) { 67 if (r.second + EPS > intervals[i].first) { 68 r.second = max(r.second, intervals[i].second); 69 } else { 70 printf("%.2f %.2f\n", r.first, r.second); 71 r = intervals[i]; 72 } 73 } 74 printf("%.2f %.2f\n\n", r.first, r.second); 75 } 76 return 0; 77 }