#include <bits/stdc++.h>
using Int = long long;
namespace extio {
std::string delimiter = " ", pdelimiter = " ";
std::string bracket_b = "", bracket_e = "";
void chdelim(const std::string& s) { delimiter = s; }
void chpdelim(const std::string& s) { pdelimiter = s; }
void chbracket(const std::string& b, const std::string& e) {
  bracket_b = b, bracket_e = e;
}
template <typename T>
void pcont(std::ostream& os, const T& x) {
  int c = 0;
  for (const auto& a : x) {
    if (c++) os << delimiter;
    os << a;
  }
}
template <typename T, typename U>
void ppair(std::ostream& os, const std::pair<T, U>& p) {
  os << bracket_b << p.first << pdelimiter << p.second << bracket_e;
}
}  // namespace extio
namespace std {
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& x) {
  extio::pcont(os, x);
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& x) {
  extio::pcont(os, x);
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const multiset<T>& x) {
  extio::pcont(os, x);
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const deque<T>& x) {
  extio::pcont(os, x);
  return os;
}
template <typename T, typename U>
ostream& operator<<(ostream& os, const map<T, U>& x) {
  extio::pcont(os, x);
  return os;
}
template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& x) {
  extio::ppair(os, x);
  return os;
}
template <typename T>
istream& operator>>(istream& is, tuple<int&, vector<T>&> x) {
  int N = get<0>(x);
  vector<T>& v = get<1>(x);
  v.clear();
  v.reserve(N);
  for (int i = (0); i < (int)(N); i += (1)) {
    T a;
    is >> a;
    v.emplace_back(a);
  }
  return is;
}
template <typename T>
istream& operator>>(istream& is, tuple<vector<T>&, int&> x) {
  return is >> tie(get<1>(x), get<0>(x));
}
template <typename T>
istream& operator>>(istream& is, tuple<int&, T*> x) {
  int N = get<0>(x);
  T* v = get<1>(x);
  for (int i = (0); i < (int)(N); i += (1)) {
    is >> v[i];
  }
  return is;
}
template <typename T>
istream& operator>>(istream& is, tuple<T*, int&> x) {
  return is >> tie(get<1>(x), get<0>(x));
}
}  // namespace std
template <typename T, typename U>
inline bool chmax(T& x, U a) {
  return x < a && (x = a, 1);
}
template <typename T, typename U>
inline bool chmin(T& x, U a) {
  return a < x && (x = a, 1);
}
inline int in() {
  int x;
  std::cin >> x;
  return x;
}
namespace orliv {
namespace graph {
struct Edge {
  using weight_type = long double;
  static constexpr weight_type INF =
      std::numeric_limits<weight_type>::max() - 100;
  int from, to;
  weight_type w;
  Edge(int from, int to, weight_type w = 1) : from(from), to(to), w(w) {}
  bool operator<(const Edge& rhs) const {
    if (w != rhs.w) return w > rhs.w;
    if (from != rhs.from) return from < rhs.from;
    return to < rhs.to;
  }
};
using Weight = Edge::weight_type;
using Edges = std::vector<Edge>;
using Weights = std::vector<Weight>;
using Path = std::vector<int>;
using Nodes = std::vector<int>;
}  // namespace graph
using Graph = std::vector<graph::Edges>;
}  // namespace orliv
namespace orliv {
namespace graph {
namespace shortest_path {
namespace util {
Path buildPath(int t, std::vector<int>& prev) {
  Path path;
  for (int u = t; u >= 0; u = prev[u]) {
    path.emplace_back(u);
  }
  std::reverse(path.begin(), path.end());
  return std::move(path);
}
}  // namespace util
Weights dijkstra(const Graph& g, int s, std::vector<int>& prev) {
  const int V = g.size();
  auto inf = Edge::INF;
  Weights dist(V, inf);
  prev.assign(V, -1);
  dist[s] = 0;
  std::priority_queue<Edge> pq;
  for (pq.emplace(-2, s, 0); !pq.empty();) {
    auto e = pq.top();
    pq.pop();
    if (prev[e.to] != -1) continue;
    prev[e.to] = e.from;
    for (const auto& f : g[e.to]) {
      if (dist[f.to] <= e.w + f.w) continue;
      pq.emplace(f.from, f.to, dist[f.to] = e.w + f.w);
    }
  }
  return std::move(dist);
}
Weights dijkstra(const Graph& g, int s) {
  std::vector<int> prev;
  return std::move(dijkstra(g, s, prev));
}
std::pair<Weight, Path> dijkstra(const Graph& g, int s, int t) {
  std::vector<int> prev;
  auto ws = dijkstra(g, s, prev);
  auto path = util::buildPath(t, prev);
  return std::move(std::make_pair(ws[t], std::move(path)));
}
}  // namespace shortest_path
}  // namespace graph
}  // namespace orliv
using namespace std;
using Real = double;
using P = std::complex<Real>;
const Real EPS = 1e-8;
Real cross(const P& a, const P& b) { return imag(conj(a) * b); }
Real dot(const P& a, const P& b) { return real(conj(a) * b); }
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0) return +1;
  if (cross(b, c) < 0) return -1;
  if (dot(b, c) < 0) return +2;
  if (norm(b) < norm(c)) return -2;
  return 0;
}
bool intersect(const P& a, const P& b, const P& c, const P& d) {
  return ccw(a, b, c) * ccw(a, b, d) <= 0 && ccw(c, d, a) * ccw(c, d, b) <= 0;
}
struct Star {
  std::vector<P> ps;
  Star(Real x, Real y, Real a, Real r) {
    P base(x, y);
    P p = std::polar(r, (a + 90) / 180.0 * M_PI);
    P rot = std::polar(1.0, 0.4 * M_PI);
    for (int i = (0); i < (int)(5); i += (1)) {
      ps.emplace_back(p + base);
      p *= rot;
    }
  }
  Real dist(const Star& other) const {
    Real d = 1e9;
    for (int i = (0); i < (int)(5); i += (1))
      for (int j = (0); j < (int)(5); j += (1)) {
        int ni = (i + 2) % 5;
        int nj = (j + 2) % 5;
        if (intersect(ps[i], ps[ni], other.ps[j], other.ps[nj])) {
          return 0;
        }
        chmin(d, abs(ps[i] - other.ps[j]));
      }
    return d;
  }
};
signed main() {
  int N, M, L;
  while (N = in(), M = in(), L = in(), N || M || L) {
    orliv::Graph g(N);
    vector<Star> stars;
    for (int i = (0); i < (int)(N); i += (1)) {
      Real x = in(), y = in(), a = in(), r = in();
      stars.emplace_back(x, y, a, r);
    }
    for (int i = (0); i < (int)(N); i += (1))
      for (int j = (0); j < (int)(N); j += (1)) {
        if (i == j) continue;
        auto d = stars[i].dist(stars[j]);
        g[i].emplace_back(i, j, d);
      }
    printf("%.20Lf\n",
           orliv::graph::shortest_path::dijkstra(g, M - 1, L - 1).first);
  }
  return 0;
}
