#include <bits/stdc++.h>
using namespace std;
inline int sign(double x) { return (abs(x) < 1e-9 ? 0 : x > 0 ? 1 : -1); }
struct _Reader {
  template <class T>
  _Reader operator,(T &rhs) {
    cin >> rhs;
    return *this;
  }
};
struct _Writer {
  bool f;
  _Writer() : f(false) {}
  template <class T>
  _Writer operator,(const T &rhs) {
    cout << (f ? " " : "") << rhs;
    f = true;
    return *this;
  }
};
template <class T>
struct vevector : public vector<vector<T>> {
  vevector(int n = 0, int m = 0, const T &initial = T())
      : vector<vector<T>>(n, vector<T>(m, initial)) {}
};
template <class T>
struct vevevector : public vector<vevector<T>> {
  vevevector(int n = 0, int m = 0, int l = 0, const T &initial = T())
      : vector<vevector<T>>(n, vevector<T>(m, l, initial)) {}
};
template <class T>
struct vevevevector : public vector<vevevector<T>> {
  vevevevector(int n = 0, int m = 0, int l = 0, int k = 0,
               const T &initial = T())
      : vector<vevevector<T>>(n, vevevector<T>(m, l, k, initial)) {}
};
template <class T>
T read() {
  T t;
  cin >> t;
  return t;
}
template <class T>
vector<T> read(int n) {
  vector<T> v;
  for (int i = 0; i < (n); i++) {
    v.push_back(read<T>());
  }
  return v;
}
template <class T>
vevector<T> read(int n, int m) {
  vevector<T> v;
  for (int i = 0; i < (n); i++) v.push_back(read<T>(m));
  return v;
}
template <class T>
vevector<T> readjag() {
  return read<T>(read<int>());
}
template <class T>
vevector<T> readjag(int n) {
  vevector<T> v;
  for (int i = 0; i < (n); i++) v.push_back(readjag<T>());
  return v;
}
template <class T1, class T2>
inline istream &operator>>(istream &in, pair<T1, T2> &p) {
  in >> p.first >> p.second;
  return in;
}
template <class T1, class T2>
inline ostream &operator<<(ostream &out, pair<T1, T2> &p) {
  out << p.first << p.second;
  return out;
}
template <class T>
inline ostream &operator<<(ostream &out, vector<T> &v) {
  ostringstream ss;
  for (auto x : v) ss << x << ' ';
  auto s = ss.str();
  out << s.substr(0, s.length() - 1) << endl;
  return out;
}
struct P2 {
  double x, y;
  P2(double x = 0, double y = 0) : x(x), y(y) {}
  P2(complex<double> c) : x(c.real()), y(c.imag()) {}
  P2 operator+() const { return *this; }
  P2 operator+(const P2 &_) const { return P2(x + _.x, y + _.y); }
  P2 operator-() const { return P2(-x, -y); }
  P2 operator-(const P2 &_) const { return *this + -_; }
  P2 operator*(double _) const { return P2(x * _, y * _); }
  P2 operator/(double _) const { return P2(x / _, y / _); }
  double dot(const P2 &_) const { return x * _.x + y * _.y; }
  double cross(const P2 &_) const { return x * _.y - y * _.x; }
  double sqlength() const { return x * x + y * y; }
  double length() const { return sqrt(sqlength()); }
  P2 orthogonal() const { return P2(y, -x); }
  P2 direction() const { return *this / length(); }
};
inline istream &operator>>(istream &in, P2 &p) {
  in >> p.x >> p.y;
  return in;
}
inline ostream &operator<<(ostream &out, const P2 &p) {
  out << p.x << ' ' << p.y;
  return out;
}
inline double abs(P2 p2) { return p2.length(); }
inline P2 orthogonal(P2 p) { return p.orthogonal(); }
inline complex<double> orthogonal(complex<double> c) {
  return c * complex<double>(0, 1);
}
inline pair<P2, P2> get_same_distance_points(P2 a, P2 b, double d) {
  assert(abs(a - b) <= 2 * d + 1e-9);
  auto v = (a + b) / 2.0 - a;
  auto vl = abs(v);
  auto wl = sqrt(d * d - vl * vl);
  auto w = orthogonal(v) * (wl / vl);
  return make_pair(a + v + w, a + v - w);
}
inline int clockwise(P2 a, P2 b, P2 c) {
  const P2 u = b - a, v = c - a;
  if (u.cross(v) > 1e-9) {
    return 1;
  }
  if (u.cross(v) < -1e-9) {
    return -1;
  }
  if (u.dot(v) < -1e-9) {
    return -1;
  }
  if (u.sqlength() < v.sqlength() - 1e-9) {
    return 1;
  }
  return 0;
}
struct Line {
  P2 p, d;
  explicit Line(P2 pos = P2(), P2 dir = P2()) : p(pos), d(dir) {}
  static Line FromPD(P2 pos, P2 dir) { return Line(pos, dir); }
  static Line From2Point(P2 a, P2 b) { return Line(a, b - a); }
};
struct LineSeg {
  P2 p, d;
  explicit LineSeg(P2 pos = P2(), P2 dir = P2()) : p(pos), d(dir) {}
  static LineSeg FromPD(P2 pos, P2 dir) { return LineSeg(pos, dir); }
  static LineSeg From2Point(P2 a, P2 b) { return LineSeg(a, b - a); }
  operator Line() { return Line(p, d); }
};
inline P2 projective(P2 a, P2 b) { return a * (a.dot(b) / a.length()); }
inline P2 perpendicular_foot(P2 a, Line b) {
  Line l = Line(b.p - a, b.d);
  return a + l.p - projective(l.p, l.d);
}
inline LineSeg projective(LineSeg a, Line b) {
  return LineSeg(perpendicular_foot(a.p, b), projective(a.d, b.d));
}
inline P2 crossPoint(Line a, Line b) {
  return a.p + a.d * (b.d.cross(b.p - a.p) / b.d.cross(a.d));
}
inline bool contains(LineSeg a, P2 p) {
  return abs(a.p - p) + abs(a.p + a.d - p) - abs(a.d) < 1e-9;
}
inline bool isCross(Line a, Line b) { return abs(a.d.cross(b.d)) > 1e-9; }
inline bool isCross(Line a, LineSeg b) {
  return sign(a.d.cross(b.p - a.p)) * sign(a.d.cross(b.p + b.d - a.d)) <= 0;
}
inline bool isCross(LineSeg a, Line b) { return isCross(b, a); }
inline bool isCross(LineSeg a, LineSeg b) {
  P2 ae = a.p + a.d, be = b.p + b.d;
  return clockwise(a.p, ae, b.p) * clockwise(a.p, ae, be) <= 0 &&
         clockwise(b.p, be, a.p) * clockwise(b.p, be, ae) <= 0;
}
inline bool isOverlap(Line a, Line b) {
  return abs(a.d.cross(b.p - a.p)) < 1e-9;
}
inline bool isOverlap(Line a, LineSeg b) {
  return isOverlap(a, Line(b.p, b.d));
}
inline bool isOverlap(LineSeg a, Line b) { return isOverlap(b, a); }
inline bool isOverlap(LineSeg a, LineSeg b) {
  return contains(a, b.p) || contains(a, b.p + b.d) || contains(b, a.p) ||
         contains(b, a.p + a.d);
}
inline double getDistance(P2 a, P2 b) { return (a - b).length(); }
inline double getDistance(P2 a, Line b) {
  return abs(b.d.cross(a - b.p) / b.d.length());
}
inline double getDistance(P2 a, LineSeg b) {
  return min(getDistance(perpendicular_foot(a, (Line)b), a),
             min(getDistance(b.p, a), getDistance(b.p + b.d, a)));
}
inline double getDistance(Line a, P2 b) { return getDistance(b, a); }
inline double getDistance(Line a, Line b) {
  return isCross(a, b) ? 0 : getDistance(a, b.p);
}
inline double getDistance(Line a, LineSeg b) {
  return isCross(a, b) ? 0
                       : min(getDistance(a, b.p), getDistance(a, b.p + b.d));
}
inline double getDistance(LineSeg a, P2 b) { return getDistance(b, a); }
inline double getDistance(LineSeg a, Line b) { return getDistance(b, a); }
inline double getDistance(LineSeg a, LineSeg b) {
  return isCross(a, b)
             ? 0
             : min(min(getDistance(a.p, b.p), getDistance(a.p, b.p + b.d)),
                   min(getDistance(a.p + a.d, b.p),
                       getDistance(a.p + a.d, b.p + b.d)));
}
inline pair<pair<P2, P2>, pair<P2, P2>> get_distance_points(Line a, double ta,
                                                            Line b, double tb) {
  assert(isCross(a, b));
  P2 va = a.d.orthogonal().direction() * ta;
  P2 vb = b.d.orthogonal().direction() * tb;
  return make_pair(
      make_pair(crossPoint(Line(a.p + va, a.d), Line(b.p + vb, b.d)),
                crossPoint(Line(a.p + va, a.d), Line(b.p - vb, b.d))),
      make_pair(crossPoint(Line(a.p - va, a.d), Line(b.p + vb, b.d)),
                crossPoint(Line(a.p - va, a.d), Line(b.p - vb, b.d))));
}
struct Circle {
  P2 c;
  double r;
  Circle() : c(), r() {}
  Circle(double x, double y, double r) : c(x, y), r(r) {}
  Circle(P2 c, double r) : c(c), r(r) {}
  bool IntersectWith(const Circle &rhs) const {
    return abs(c - rhs.c) - (r + rhs.r) < 1e-9;
  }
  bool Contains(const P2 &p) const { return abs(p - c) - r < 1e-9; }
};
inline istream &operator>>(istream &in, Circle &c) {
  in >> c.c >> c.r;
  return in;
}
inline pair<P2, P2> crossPoint(Circle A, Circle B) {
  P2 v = B.c - A.c;
  P2 dir = v.direction();
  double d = v.length();
  double lh = (A.r * A.r + d * d - B.r * B.r) / (2 * d);
  P2 h = A.c + dir * lh;
  double lp = sqrt(A.r * A.r - lh * lh);
  P2 p = dir.orthogonal() * lp;
  return make_pair(h + p, h - p);
}
struct Rect {
  P2 l, s;
  Rect() : l(), s() {}
  Rect(double x, double y, double w, double h) : l(x, y), s(w, h) {}
  Rect(P2 location, P2 size) : l(location), s(size) {}
  bool Contains(const P2 &p) const {
    return p.x - l.x > -1e-9 && p.y - l.y > -1e-9 && p.x - (l.x + s.x) < 1e-9 &&
           p.y - (l.y + s.y) < 1e-9;
  }
};
template <class TCost = double>
struct Path {
  int from;
  int to;
  TCost cost;
  Path(int from = 0, int to = 0, TCost cost = 0)
      : from(from), to(to), cost(cost) {}
  bool operator<(const Path &rhs) const { return cost < rhs.cost; }
  bool operator>(const Path &rhs) const { return cost > rhs.cost; }
};
template <class TCost>
pair<vector<TCost>, vector<int>> dijkstra(
    const vector<vector<Path<TCost>>> &routes, int start = 0, int goal = -1) {
  int N = routes.size();
  priority_queue<Path<TCost>, vector<Path<TCost>>, greater<Path<TCost>>> q;
  q.push(Path<TCost>(start, start, 0));
  vector<int> prev(N, -1);
  vector<TCost> cost(N, (1L << 30));
  while (!q.empty()) {
    Path<TCost> cur = q.top();
    q.pop();
    int i = cur.to;
    if (prev[i] != -1) continue;
    prev[i] = cur.from;
    cost[i] = cur.cost;
    if (i == goal) {
      break;
    }
    for (int j = 0; j < (routes[i].size()); j++) {
      Path<TCost> next =
          Path<TCost>(i, routes[i][j].to, cur.cost + routes[i][j].cost);
      if (prev[i] != -1) q.push(next);
    }
  }
  return make_pair(cost, prev);
}
void solve();
int main() {
  solve();
  return 0;
}
void solve() {
  int cases = (1L << 30);
  for (int _ = 0; _ < (cases); _++) {
    int N, M, L;
    _Reader(), N, M, L;
    if (!N) {
      break;
    }
    vevector<LineSeg> segs(N);
    for (int _ = 0; _ < (N); _++) {
      int x, y, a, r;
      _Reader(), x, y, a, r;
      for (int i = 0; i < (5); i++) {
        int j = i + 1;
        double ai = (i * 144 + 90 + a) % 360 * 3.14159265358979323846 / 180.0;
        double aj = (j * 144 + 90 + a) % 360 * 3.14159265358979323846 / 180.0;
        P2 center(x, y);
        P2 pi = center + P2(cos(ai), sin(ai)).direction() * r;
        P2 pj = center + P2(cos(aj), sin(aj)).direction() * r;
        LineSeg s = LineSeg::From2Point(pi, pj);
        segs[_].push_back(s);
      }
    }
    vevector<Path<double>> graph(N);
    for (int i = 0; i < (N); i++)
      for (int j = 0; j < (N); j++) {
        double d = (1L << 30);
        for (int k = 0; k < (5); k++)
          for (int l = 0; l < (5); l++)
            d = min(d, getDistance(segs[i][k], segs[j][l]));
        graph[i].push_back({i, j, d});
      }
    printf("%.16f\n", dijkstra(graph, L - 1, -1).first[M - 1]);
    break;
  }
}
