#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-6;
const double INF = 1e12;
const double PI = acos(-1.0);
const complex<double> INF_P(INF, INF);
namespace std {
bool operator<(const complex<double>& a, const complex<double>& b) {
  return (real(a) != real(b)) ? real(a) < real(b) : imag(a) < imag(b);
}
}  // namespace std
double dist(complex<double> p1, complex<double> p2) { return abs(p1 - p2); }
bool equal(double a, double b) { return (fabs(a - b) < EPS); }
bool eq_v(complex<double> a, complex<double> b) {
  return (equal(a.real(), b.real()) && equal(a.imag(), b.imag()));
}
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); }
enum { CCW = 1, CW = -1, ON = 0 };
int ccw(const complex<double>& a, complex<double> b, complex<double> c) {
  b -= a, c -= a;
  double rotdir = cross(b, c);
  if (rotdir > EPS) return CCW;
  if (rotdir < -EPS) return CW;
  return ON;
}
double to_deg(double rad) { return rad * 180.0 / PI; }
double to_rad(double deg) { return deg * PI / 180.0; }
complex<double> rot(complex<double> p, double a) {
  double x = p.real() * cos(a) - p.imag() * sin(a);
  double y = p.real() * sin(a) + p.imag() * cos(a);
  return complex<double>(x, y);
}
complex<double> rot2(complex<double> a, complex<double> b, double angle) {
  complex<double> p = b - a;
  return rot(p, angle) + a;
}
struct Segment {
  complex<double> a, b;
  Segment(complex<double> a_, complex<double> b_) {
    a = a_;
    b = b_;
  }
  double distance(complex<double> p) {
    if (dot(b - a, p - a) < EPS) return abs(p - a);
    if (dot(a - b, p - b) < EPS) return abs(p - b);
    return abs(cross(b - a, p - a)) / abs(b - a);
  }
  bool is_intersection(const Segment& s) {
    return (ccw(a, b, s.a) * ccw(a, b, s.b) <= 0 &&
            ccw(s.a, s.b, a) * ccw(s.a, s.b, b) <= 0);
  }
  bool contain(complex<double> p) {
    return (abs(a - p) + abs(p - b) < abs(a - b) + EPS);
  }
  double distance(Segment s) {
    if (is_intersection(s)) return 0.0;
    return min(min(distance(s.a), distance(s.b)),
               min(s.distance(a), s.distance(b)));
  }
  void print() {
    printf("line(%f,%f,%f,%f);\n", a.real(), a.imag(), b.real(), b.imag());
  }
};
bool operator<(const Segment& s1, const Segment& s2) { return s1.a < s2.a; }
double dist_star(vector<Segment> a, vector<Segment> b) {
  double result = INF;
  for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < b.size(); j++) {
      if (equal(a[i].distance(b[j]), 0.0)) continue;
      result = min(result, a[i].distance(b[j]));
    }
  }
  return result;
}
int main() {
  int n, m, l;
  while (scanf("%d %d %d", &n, &m, &l), n || m || l) {
    m--;
    l--;
    vector<vector<Segment> > v;
    for (int i = 0; i < n; i++) {
      int x, y, a, r;
      cin >> x >> y >> a >> r;
      complex<double> p1 = complex<double>(x + r * cos(to_rad(a + 90)),
                                           y + r * sin(to_rad(a + 90)));
      complex<double> p2 = rot2(complex<double>(x, y), p1, to_rad(72));
      complex<double> p3 = rot2(complex<double>(x, y), p2, to_rad(72));
      complex<double> p4 = rot2(complex<double>(x, y), p3, to_rad(72));
      complex<double> p5 = rot2(complex<double>(x, y), p4, to_rad(72));
      vector<Segment> vs;
      vs.push_back(Segment(p1, p3));
      vs.push_back(Segment(p3, p5));
      vs.push_back(Segment(p5, p2));
      vs.push_back(Segment(p2, p4));
      vs.push_back(Segment(p4, p1));
      v.push_back(vs);
    }
    double G[101][101];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        G[i][j] = (i == j) ? 0 : INF;
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        double d = dist_star(v[i], v[j]);
        G[i][j] = G[j][i] = d;
      }
    }
    for (int k = 0; k < n; k++) {
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
          G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
        }
      }
    }
    printf("%.8f\n", G[l][m]);
  }
}
