Advertisement
jonathanasdf

ASC 26 Problem I: Shepherd's Problem

Jan 6th, 2013
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.72 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <iomanip>
  4. #include <complex>
  5. #include <vector>
  6. #include <algorithm>
  7. using namespace std;
  8. typedef long double ld;
  9. typedef complex<ld> pt;
  10. const ld PI = acos(-1.L), EPS = 1e-12L;
  11. ld cp(pt a, pt b) { return a.real()*b.imag()-b.real()*a.imag(); }
  12. ld dp(pt a, pt b) { return a.real()*b.real()-a.imag()*b.imag(); }
  13. // p = input points, a and b are global variables for results of intersections
  14. vector<pt> p; pt a, b;
  15. bool cc_inter(pt p1, int r1, pt p2, int r2) { // circle circle
  16.     ld dq=norm(p1-p2), rq=r1*r1-r2*r2;
  17.     ld dt=2*dq*(r1*r1+r2*r2)-dq*dq-rq*rq;
  18.     a=b=(p1+p2)/2.L+(p2-p1)/2.L*rq/dq;
  19.     if(dt<-EPS) return false;
  20.     if(dt<EPS) return true;
  21.     dt=sqrt(dt)/2/dq;
  22.     a=b+(p1-p2)*pt(0,-1)*dt;
  23.     b=b-(p1-p2)*pt(0,-1)*dt;
  24.     return true;
  25. }
  26. bool cl_inter(pt c, int r, pt q1, pt q2) { // circle line
  27.     pt u = q2-q1;
  28.     ld uq=norm(u), d=uq*r*r-cp(u,q1-c)*cp(u,q1-c);
  29.     if(d<-EPS) return false;
  30.     ld s=dp(u, c-q1)/uq;
  31.     a = b = q1+s*u;
  32.     if(d<EPS) return true;
  33.     d=sqrt(d)/uq;
  34.     a = q1 + (s-d)*u, b = q1 + (s+d)*u;
  35.     return true;
  36. }
  37. int main() {
  38.     freopen("shepherd.in", "r", stdin);
  39.     freopen("shepherd.out", "w", stdout);
  40.     int n, d, D; cin >> n >> d >> D;
  41.     for (int i=0; i < n; i++) {
  42.         ld x, y; cin >> x >> y;
  43.         p.push_back(pt(x,y));
  44.     }
  45.  
  46.     // best = smallest angle, bestpt = point with smallest angle
  47.     ld best=4; pt bestpt;
  48.     // Test for every p[i] the candidate points on circle of radius D centered on p[i]
  49.     for (int i=0; i < p.size(); i++) {
  50.         // Endpoints of segment
  51.         vector<ld> v; v.push_back(0); v.push_back(2*PI);
  52.         // for every other point
  53.         for (int j=0; j < p.size(); j++) if (j != i) {
  54.             // small circle intersection
  55.             if (cc_inter(p[i], D, p[j], d))
  56.                 v.push_back(arg(a-p[i])), v.push_back(arg(b-p[i]));
  57.             // big circle intersection
  58.             if (cc_inter(p[i], D, p[j], D))
  59.                 v.push_back(arg(a-p[i])), v.push_back(arg(b-p[i]));
  60.             // line intersection with every pair of points
  61.             for (int k=0; k < p.size(); k++) if (k != j) {
  62.                 if (cl_inter(p[i], D, p[j], p[k]))
  63.                    v.push_back(arg(a-p[i])), v.push_back(arg(b-p[i]));
  64.             }
  65.         }
  66.         // get rid of negative values and sort
  67.         for (int j=0; j < v.size(); j++) if (v[j] < 0) v[j] += 2*PI;
  68.         sort(v.begin(), v.end());
  69.  
  70.         // For each consecutive segment of candidate points
  71.         for (int j=0, k=1; k < v.size(); j=k++) {
  72.             ld lo = v[j], hi = v[k], m = (lo+hi)/2;
  73.             // Either the whole segment is valid, or it's invalid, so just test the midpoint
  74.             pt pp = p[i] + polar(D+0.L, m);
  75.             bool valid = true;
  76.             // For each point
  77.             for (int r = 0; r < p.size(); r++) {
  78.                 // distance is valid?
  79.                 if (abs(pp-p[r]) + EPS < d || abs(pp-p[r]) - EPS > D) valid = false;
  80.                 // for each triangle, is the point contained in the triangle?
  81.                 for (int s = r+1; s < p.size(); s++) for (int t = s+1; t < p.size(); t++) {
  82.                     ld dir = cp(p[s]-p[r], p[t]-p[r]);
  83.                     if (cp(p[s]-p[r], pp-p[r]) * dir > EPS &&
  84.                             cp(p[t]-p[s], pp-p[s]) * dir > EPS &&
  85.                             cp(p[r]-p[t], pp-p[t]) * dir > EPS)
  86.                         valid = false;
  87.                 }
  88.             }
  89.             if (!valid) continue;
  90.  
  91.             // The segment is valid, so ternary search on the segment
  92.             while(true) {
  93.                 ld c1 = (lo*2+hi)/3, c2 = (lo+hi*2)/3;
  94.                 // p1 and p2 are candidate points to test
  95.                 pt p1 = p[i] + polar(D+0.L, c1), p2 = p[i] + polar(D+0.L, c2);
  96.                 ld a1=0, a2=0; // find angles for p1 and p2 (max over all pairs of points)
  97.                 for (int r=0; r < p.size(); r++) for (int s=r+1; s < p.size(); s++) {
  98.                     ld t1 = abs(arg(p[r]-p1)-arg(p[s]-p1));
  99.                     a1 = max(a1, min(t1, 2*PI-t1));
  100.                     ld t2 = abs(arg(p[r]-p2)-arg(p[s]-p2));
  101.                     a2 = max(a2, min(t2, 2*PI-t2));
  102.                 }
  103.                 if (a1 < a2) {
  104.                     hi = c2;
  105.                     if (a1 < best) best = a1, bestpt = p1;
  106.                 }
  107.                 else {
  108.                     lo = c1;
  109.                     if (a2 < best) best = a2, bestpt = p2;
  110.                 }
  111.                 if (hi-lo < EPS) break;
  112.             }
  113.         }
  114.     }
  115.     if (best > PI) cout << "impossible" << endl;
  116.     else cout << fixed << setprecision(10) << bestpt.real() << " " << bestpt.imag() << endl;
  117.     return 0;
  118. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement