#include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

class Vec;
Vec operator/(const Vec& v, const double& divisor);
Vec operator*(const double& scale, const Vec& v);

class Vec {
  using F = double;
  vector<F> container;

 public:
  Vec(size_t size) : container(size) {}
  Vec(initializer_list<F> elements)
      : container(elements.begin(), elements.end()) {}
  size_t dim() const { return container.size(); }
  F& operator[](const size_t size) { return container.at(size); }
  const F& operator[](const size_t size) const { return container.at(size); }
  Vec operator+(const Vec& other) const {
    Vec ret(*this);
    for (size_t i = 0; i < dim(); i++) ret[i] += other[i];
    return ret;
  }
  Vec operator-(const Vec& other) const { return (*this) + (-other); }
  Vec operator-() const { return -1.0 * (*this); }
  F inner(const Vec& other) const {
    F acc = 0;
    for (size_t i = 0; i < dim(); i++) {
      acc += (*this)[i] * other[i];
    }
    return acc;
  }
  F norm() const { return sqrt(inner(*this)); }
  Vec unit() const { return (*this) / this->norm(); }
};
Vec operator/(const Vec& v, const double& divisor) { return 1.0 / divisor * v; }
Vec operator*(const double& scale, const Vec& v) {
  Vec ret(v);
  for (size_t i = 0; i < ret.dim(); i++) ret[i] *= scale;
  return ret;
}

vector<Vec> intersection(const Vec& center, double radius, const Vec& grad,
                         double c) {
  vector<Vec> result;

  const double g = grad.norm();
  const double dist = (c - grad.inner(center)) / g;

  const double det = radius * radius - dist * dist;
  if (det >= 0) {
    const double s = sqrt(det);
    const Vec u = grad.unit();
    const Vec p = center + dist * u;
    Vec dir({-u[1], u[0]});

    result.push_back(p + s * dir);
    result.push_back(p - s * dir);
  }

  return result;
}

using Y = tuple<int, int, int>;
int countp(const Vec& center, double t, const vector<Y>& niku, double eps) {
  int N = niku.size();

  int result = 0;
  rep(i, N) {
    int x, y, c;
    tie(x, y, c) = niku[i];
    if (pow(center[0] - x, 2) + pow(center[1] - y, 2) <= pow(t / c, 2) + eps)
      result++;
  }
  return result;
}

int main() {
  int N, K;
  cin >> N >> K;

  vector<Y> niku(N);
  rep(i, N) {
    int x, y, c;
    cin >> x >> y >> c;
    niku[i] = Y(x, y, c);
  }

  const double eps = 1e-7;

  double lb = 0;
  double ub = 100 * 4'000;
  while (ub - lb > eps && (ub - lb) / ((ub + lb) / 2) > eps) {
    const double mid = (lb + ub) / 2;

    int mCnt = 0;
    rep(i, N) {
      int x, y, c;
      tie(x, y, c) = niku[i];

      mCnt = max(mCnt, countp(Vec({(double)x, (double)y}), mid, niku, eps));
    }

    rep(i, N) for (int j = i + 1; j < N; j++) {
      int x0, x1, y0, y1, c0, c1;
      tie(x0, y0, c0) = niku[i];
      tie(x1, y1, c1) = niku[j];

      const double r0 = mid / c0;
      const double r1 = mid / c1;

      Vec grad({2.0 * (x1 - x0), 2.0 * (y1 - y0)});
      const double C =
          (r0 - r1) * (r0 + r1) - (x0 - x1) * (x0 + x1) - (y0 - y1) * (y0 + y1);

      Vec center({(double)x0, (double)y0});
      vector<Vec> ps = intersection(center, r0, grad, C);

      for (auto p : ps) {
        mCnt = max(mCnt, countp(p, mid, niku, eps));
      }
    }

    (mCnt >= K ? ub : lb) = mid;
  }
  cout << fixed << setprecision(7) << ub << endl;
  return 0;
}

Measured memory_bytes: 256