#include <bits/stdc++.h>
using namespace std;
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  for (__typeof((t).begin()) it = (t).begin(); it != (t).end(); it++) {
    if (it != t.begin()) os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  for (__typeof((t).begin()) it = (t).begin(); it != (t).end(); it++) {
    if (it != t.begin()) os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
const double INF = 1e8;
const double EPS = 1e-8;
const double PI = 3.1415926535897932384626;
inline int sig(const double &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline int less(const double &x, const double &y) {
  return sig(x - y) ? x < y : BORDER;
}
istream &operator>>(istream &is, complex<double> &p) {
  double x, y;
  is >> x >> y;
  p = complex<double>(x, y);
  return is;
}
inline double norm(const complex<double> &p) {
  return p.real() * p.real() + p.imag() * p.imag();
}
inline double inp(const complex<double> &a, const complex<double> &b) {
  return (conj(a) * b).real();
}
inline double outp(const complex<double> &a, const complex<double> &b) {
  return (conj(a) * b).imag();
}
inline complex<double> unit(const complex<double> &p) { return p / abs(p); }
inline complex<double> proj(const complex<double> &s,
                            const complex<double> &t) {
  return t * inp(s, t) / norm(t);
}
inline int ccw(const complex<double> &s, const complex<double> &t,
               const complex<double> &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv) return res;
  if (sig(inp(t - s, p - s)) < 0) return -2;
  if (sig(inp(s - t, p - t)) < 0) return 2;
  return 0;
}
struct L : public vector<complex<double>> {
  L(const complex<double> &p1, const complex<double> &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  complex<double> dir() const { return ((*this)[1]) - ((*this)[0]); }
  friend istream &operator>>(istream &is, L &l) {
    complex<double> p1, p2;
    is >> p1 >> p2;
    l = L(p1, p2);
    return is;
  }
  friend inline complex<double> proj(const complex<double> &s, const L &t) {
    return t[0] + proj(s - t[0], t[1] - t[0]);
  }
  int online(const complex<double> &p) const {
    return !sig(outp(p - ((*this)[0]), dir()));
  }
  double distance(const complex<double> &p) const {
    return abs(outp(dir(), p - ((*this)[0]))) / abs(dir());
  }
};
struct S : public L {
  S(const complex<double> &p1, const complex<double> &p2) : L(p1, p2) {}
  S() {}
  int online(const complex<double> &p) const {
    if (!sig(abs(p - ((*this)[0]))) || !sig(abs(p - ((*this)[1]))))
      return BORDER;
    return !sig(abs(((*this)[0]) - p) + abs(((*this)[1]) - p) -
                abs(((*this)[0]) - ((*this)[1])));
  }
  double distance(const complex<double> &p) const {
    if (inp(p - ((*this)[0]), dir()) < EPS) return abs(p - ((*this)[0]));
    if (inp(p - ((*this)[1]), -dir()) < EPS) return abs(p - ((*this)[1]));
    return .0;
    return L::distance(p);
  }
  int intersect(const S &s) const {
    const int p = ccw(((*this)[0]), ((*this)[1]), s[0], 1) *
                  ccw(((*this)[0]), ((*this)[1]), s[1], 1);
    const int q =
        ccw(s[0], s[1], ((*this)[0]), 1) * ccw(s[0], s[1], ((*this)[1]), 1);
    return (p > 0 || q > 0) ? FALSE : (!p || !q) ? BORDER : TRUE;
  }
  int intersect(const L &l) const {
    if (l.online(((*this)[0])) || l.online(((*this)[1]))) return BORDER;
    return (sig(outp(l.dir(), ((*this)[0]) - l[0])) *
                sig(outp(l.dir(), ((*this)[1]) - l[0])) <=
            0);
  }
  double distance(const L &l) const {
    if (intersect(l)) return .0;
    return min(l.distance(((*this)[0])), l.distance(((*this)[1])));
  }
  double distance(const S &s) const {
    if (intersect(s)) return .0;
    return min(min(s.distance(((*this)[0])), s.distance(((*this)[1]))),
               min(distance(s[0]), distance(s[1])));
  }
};
struct C : public complex<double> {
  double r;
  friend istream &operator>>(istream &is, C &c) {
    operator>>(is, (complex<double> &)c);
    is >> c.r;
    return is;
  }
  int inside(const complex<double> &p) const {
    return less(norm(p - (*this)), r * r);
  }
};
inline int cc_intersect(const C &a, const C &b) {
  return less(abs(a.r - b.r), abs(a - b)) + less(abs(a - b), a.r + b.r) - 1;
}
inline int cl_intersect(const C &c, const L &l) {
  return less(l.distance(c), c.r);
}
inline int cs_intersect(const C &c, const S &s) {
  int d = less(s.distance(c), c.r);
  if (d != TRUE) return d;
  int p = c.inside(s[0]), q = c.inside(s[1]);
  return (p < 0 || q < 0) ? BORDER : p & q;
}
inline S cc_crosspoint(const C &c1, const C &c2) {
  if (!cc_intersect(c1, c2)) return S();
  double d = abs(c1 - c2);
  double x = (c1.r * c1.r - c2.r * c2.r + d * d) / (2 * d);
  double h = sqrt(c1.r * c1.r - x * x);
  complex<double> u = unit(c2 - c1);
  return S(c1 + u * x + u * complex<double>(0, 1) * h,
           c1 + u * x + u * complex<double>(0, -1) * h);
}
struct G : public vector<complex<double>> {
  S edge(int i) const {
    return S(((*this)[i]), ((*this)[i + 1 == size() ? 0 : i + 1]));
  }
  int contains(const complex<double> &p) const {
    double sum = .0;
    for (int i = 0; i < (int)(size()); i++) {
      if (S(((*this)[i]), ((*this)[(i + 1) % size()])).online(p)) return BORDER;
      sum += arg((((*this)[i]) - p) / (((*this)[(i + 1) % size()]) - p));
    }
    return !!sig(sum);
  }
  int contains(const S &s) const { return contains(s[0]) && contains(s[1]); }
  int contains(const L &l) const { return false; }
  int contains(const C &c) const {
    if (!contains((complex<double>)c)) return FALSE;
    double sum = .0;
    int res = TRUE;
    for (int i = 0; i < (int)(size()); i++) {
      if (c.inside(((*this)[i])) == TRUE ||
          less(edge(i).distance(c), c.r) == TRUE)
        return FALSE;
      else
        res |= c.inside(((*this)[i])) | less(edge(i).distance(c), c.r);
    }
    return res;
  }
  template <class T>
  double distance(const T &t) {
    if (contains(t)) return .0;
    double res = INF;
    for (int i = 0; i < (int)(size()); i++) {
      res = min(res, edge(i).distance(t));
    }
    return res;
  }
  double area() {
    double sum = 0;
    for (int i = 0; i < (int)(size()); i++)
      sum += outp(((*this)[i]), ((*this)[(i + 1) % size()]));
    return abs(sum / 2.);
  }
  G convex_hull(bool online = false) {
    if (size() < 2) return *this;
    sort((*this).begin(), (*this).end());
    G r;
    r.resize((int)size() * 2);
    int k = 0;
    for (int i = 0; i < size(); r[k++] = ((*this)[i++]))
      while (k > 1 && ccw(r[k - 2], r[k - 1], ((*this)[i])) < 1 - online) k--;
    int t = k;
    for (int i = (int)size() - 1; i >= 0; r[k++] = ((*this)[i--]))
      while (k > t && ccw(r[k - 2], r[k - 1], ((*this)[i])) < 1 - online) k--;
    r.resize(k - 1);
    return r;
  }
};
}  // namespace geom
using namespace geom;
namespace std {
bool operator<(const geom::complex<double> &a, const geom::complex<double> &b) {
  if (!geom::sig(a.real() - b.real())) return (a.imag() < b.imag());
  return (a.real() < b.real());
}
}  // namespace std
int n, m, l;
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> l, n) {
    vector<vector<S>> star(n);
    for (int i = 0; i < (int)(n); i++) {
      complex<double> p;
      double a, r;
      cin >> p >> a >> r;
      for (int j = 0; j < (int)(5); j++) {
        star[i].emplace_back(
            p + polar(r, (90 + a + j * 144) / 180. * PI),
            p + polar(r, (90 + a + (j + 1) * 144) / 180. * PI));
      }
    }
    vector<vector<double>> g(n, vector<double>(n, INF));
    for (int i = 0; i < (int)(n); i++) g[i][i] = 0;
    for (int i = 0; i < (int)(n); i++)
      for (int j = 0; j < (int)(n); j++)
        for (int ik = 0; ik < (int)(5); ik++)
          for (int jk = 0; jk < (int)(5); jk++)
            g[i][j] = g[j][i] = min(g[j][i], star[i][ik].distance(star[j][jk]));
    for (int k = 0; k < (int)(n); k++)
      for (int i = 0; i < (int)(n); i++)
        for (int j = 0; j < (int)(n); j++)
          g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    printf("%.20f\n", g[m - 1][l - 1]);
  }
  return 0;
}
