#include <bits/stdc++.h>
using namespace std;
bool operator<(const complex<double>& a, const complex<double>& b) {
  return abs(a) < abs(b);
}
int N, M, L;
double dot(complex<double> a, complex<double> b) { return real(conj(a) * b); }
double cross(complex<double> a, complex<double> b) { return imag(conj(a) * b); }
int ccw(complex<double> a, complex<double> b, complex<double> c) {
  b -= a;
  c -= a;
  if (cross(b, c) > DBL_EPSILON) return 1;
  if (cross(b, c) < -DBL_EPSILON) return -1;
  if (dot(b, c) < -DBL_EPSILON) return 2;
  if (norm(b) < norm(c) - DBL_EPSILON) return 2;
  return 0;
}
bool isIntersectSS(complex<double> a1, complex<double> a2, complex<double> b1,
                   complex<double> b2) {
  return ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
         ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0;
}
double DistanceSP(complex<double> a, complex<double> b, complex<double> c) {
  if (dot(b - a, c - a) < DBL_EPSILON) return abs(c - a);
  if (dot(a - b, c - b) < DBL_EPSILON) return abs(c - b);
  return abs(cross(b - a, c - a));
}
double DistaiceSS(complex<double> a, complex<double> b, complex<double> c,
                  complex<double> d) {
  if (isIntersectSS(a, b, c, d)) {
    return 0.0;
  }
  return min(min(DistanceSP(a, b, c), DistanceSP(a, b, d)),
             min(DistanceSP(c, d, a), DistanceSP(c, d, b)));
}
vector<vector<double> > links;
struct Star {
  complex<double> p;
  int a;
  int r;
  Star(complex<double> p, int a, int r) : p(p), a(a), r(r) { initVertex(); }
  vector<complex<double> > vertex;

 private:
  void initVertex() {
    for (int i = 0; i < 5; i++) {
      double theta = M_PI / 2 + 2 * i * M_PI / 5 + a * M_PI / 180;
      vertex.push_back(complex<double>(p.real() + r * cos(theta),
                                       p.imag() + r * sin(theta)));
    }
  }
};
double getLength(Star p1, Star p2) {
  double m = DBL_MAX;
  for (__typeof((p1.vertex).begin()) a1 = (p1.vertex).begin();
       a1 != (p1.vertex).end(); ++a1)
    for (__typeof((p1.vertex).begin()) a2 = (p1.vertex).begin();
         a2 != (p1.vertex).end(); ++a2) {
      if (isIntersectSS(p1.p, p2.p, *a1, *a2)) {
        for (__typeof((p2.vertex).begin()) b1 = (p2.vertex).begin();
             b1 != (p2.vertex).end(); ++b1)
          for (__typeof((p2.vertex).begin()) b2 = (p2.vertex).begin();
               b2 != (p2.vertex).end(); ++b2) {
            m = min(m, DistaiceSS(*a1, *a2, *b1, *b2));
          }
      }
    }
  return m;
}
int x, y, a, r;
double dijk(int start, int goal) {
  vector<double> memo(N, DBL_MAX);
  priority_queue<pair<double, int> > up;
  up.push(make_pair(0, start));
  memo[start] = 0;
  while (!up.empty()) {
    double cost = -up.top().first;
    int pos = up.top().second;
    up.pop();
    if (memo[pos] < cost) continue;
    if (pos == goal) return cost;
    for (int next = 0; next < N; next++) {
      if (links[pos][next] >= 0) {
        double ncost = cost + links[pos][next];
        if (memo[next] > ncost) {
          memo[next] = ncost;
          up.push(make_pair(-ncost, next));
        }
      }
    }
  }
  return -1;
}
int main() {
  while (true) {
    cin >> N >> M >> L;
    if (N == 0 && M == 0 && L == 0) {
      break;
    }
    links.clear();
    vector<Star> stars;
    for (int i = 0; i < N; i++) {
      cin >> x >> y >> a >> r;
      stars.push_back(Star(complex<double>(x, y), a, r));
    }
    for (int i = 0; i < N; i++) {
      vector<double> ld;
      for (int j = 0; j < N; j++) {
        ld.push_back(getLength(stars[i], stars[j]));
      }
      links.push_back(ld);
    }
    cout << dijk(M - 1, L - 1) << endl;
  }
}
