#include <bits/stdc++.h>

using namespace std;

#define INF 100000000
#define YJ 1145141919
#define INF_INT_MAX 2147483647
#define INF_LL 9223372036854775
#define INF_LL_MAX 9223372036854775807
#define EPS 1e-10
#define MOD 1000000007
#define MOD9 998244353
#define Pi acos(-1)
#define LL long long
#define ULL unsigned long long
#define LD long double

#define int long long

using II = pair<int, int>;

int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a * b / gcd(a, b); }
int extgcd(int a, int b, int &x, int &y) { int g = a; x = 1; y = 0; if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x; return g; }

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(a)  begin((a)), end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())

const double mEPS = 1e-10;

//点をあらわすクラス
class Point{
public:
  double x, y;
  double c;

  Point(double x = 0.0, double y = 0.0) : x(x), y(y){}

  Point operator + (Point p){ return Point(x + p.x, y + p.y); }
  Point operator - (Point p){ return Point(x - p.x, y - p.y); }
  Point operator * (double a){ return Point(a*x, a*y); }
  Point operator / (double a){ return Point(x / a, y / a); }

  double abs(){ return sqrt(norm()); } //距離
  double norm(){ return x*x + y*y; }

  bool operator < (const Point &p) const{
    return x != p.x ? x < p.x : y < p.y;
  }

  //EPSは十分小さな値
  bool operator == (const Point &p) const {
    return fabs(x - p.x) < mEPS && fabs(y - p.y) < mEPS;
  }

};

class Segment{
public:
  Point p1, p2;
};

class Circle{
public:
  Point c;
  double r;
};

typedef vector<Point> Polygon;

//点を線として扱う
typedef Point Vector;
//線分を直線として扱う
typedef Segment Line;

//内積
double dot(Vector a, Vector b){
  return a.x*b.x + a.y*b.y;
}

//外積の大きさ
double cross(Vector a, Vector b){
  return a.x*b.y - a.y*b.x;
}

//degをradに変換
double changeDegToRad(double x){
  return x*acos(-1)/180.0;
}

//原点を中心に点pをrad回転させた時の点を返す
Point rollPointRad(Point p, double rad){
  Point ret;
  ret.x = p.x*cos(rad) - p.y*sin(rad);
  ret.y = p.x*sin(rad) + p.y*cos(rad);
  return ret;
}

//線分ｓに対して、点Pから引いた垂線との交点の座標
Point project(Line s, Point p){
  Vector base = s.p2 - s.p1;
  double r = dot(p - s.p1, base) / base.norm();
  return s.p1 + base*r;
}

//線分sを対称軸とした点ｐの線対称の点
Point reflect(Segment s, Point p){
  return p + (project(s, p) - p) * 2.0;
}

//線分po->p1に対してp2はp0を基準にどの方向に回転させたか
int ccw(Point p0, Point p1, Point p2){

  //p0->p1をp0始点、p1終点の基準ベクトルとしたとき

  //p0->p2が反時計回りになるとき
  static const int COUNTER_CLOCKWISE = 1;
  //p0->p2が時計回りになるとき
  static const int CLOCKWISE = -1;
  //p2,p0,p1の順で同一直線上にあるとき
  static const int ONLINE_BACK = 2;
  //p0,p1,p2 の順で同一直線上にある場合
  static const int ONLINE_FRONT = -2;
  //p2 が線分 p0p1 上にある場合
  static const int ON_SEGMENT = 0;

  Vector a = p1 - p0;
  Vector b = p2 - p0;

  if (cross(a, b) > mEPS) return COUNTER_CLOCKWISE;
  if (cross(a, b) < -mEPS) return CLOCKWISE;
  if (dot(a, b) < -mEPS) return ONLINE_BACK;
  if (a.norm() < b.norm()) return ONLINE_FRONT;

  return ON_SEGMENT;

}

//二つの線分の交差判定
bool intersect(Segment s1, Segment s2){
  return(ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 &&
	 ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0);
}

//二点の距離
double getDistancePP(Point a, Point b){
  return (a - b).abs();
}

//直線lと点pの距離
double getDistanceLP(Line l, Point p){
  return abs(cross(l.p2 - l.p1, p - l.p1) / (l.p2 - l.p1).abs());
}

//線分sと点pの距離
double getDistanceSP(Segment s, Point p){
  if (dot(s.p2 - s.p1, p - s.p1) < 0.0) return (p - s.p1).abs();
  if (dot(s.p1 - s.p2, p - s.p2) < 0.0) return (p - s.p2).abs();
  return getDistanceLP(s, p);
}

//線分と線分の距離
double getDistanceSS(Segment s1, Segment s2){
  if (intersect(s1, s2)) return 0.0;
  return min(min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)),
	     min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2)));
}

//線分と線分の交点
Point getCrossPoint(Segment s1, Segment s2){
  Vector base = s2.p2 - s2.p1;
  double d1 = abs(cross(base, s1.p1 - s2.p1));
  double d2 = abs(cross(base, s1.p2 - s2.p1));
  double t = d1 / (d1 + d2);
  return s1.p1 + (s1.p2 - s1.p1)*t;
}

//円Cと線分lの交点(交点を持たない場合は判定しない)
pair<Point, Point> getCrossPoints(Circle c, Line l){

  Vector pr = project(l, c.c);
  Vector e = (l.p2 - l.p1) / (l.p2 - l.p1).abs();

  double base = sqrt(c.r*c.r - (pr - c.c).norm());
  return make_pair(pr + e * base, pr - e*base);

}

double arg(Vector p){ return atan2(p.y, p.x); }
Vector polar(double a, double r){ return Point(cos(r)*a, sin(r)*a); }

//円C1とC2の交点を求める(交差しない場合は判定しない)
pair<Point, Point> getCrossPoints(Circle c1, Circle c2){
  double d = (c1.c - c2.c).abs();
  double a = acos((c1.r*c1.r + d*d - c2.r*c2.r) / (2 * c1.r*d));
  double t = arg(c2.c - c1.c);
  return make_pair(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));
}

//2円の共通接線
vector<Line> tangentCircleLines(Circle c1, Circle c2){

  vector<Line> ret;

  double d = getDistancePP(c1.c, c2.c);

  for(int i = 0; i < 2; i++){
    double sin = (c1.r - (1 - i*2)*c2.r)/d;
    if(!(sin*sin < 1 + mEPS))
      break;
    double cos = sqrt(max(1-sin*sin, 0.0));
    for(int j = 0; j < 2; j++){
      Point a = c2.c - c1.c;
      Point b(sin, (1-j*2)*cos);
      Point n;
      n.x = (a.x*b.x - a.y*b.y)/d; n.y = (a.x*b.y + a.y*b.x)/d;
      Line tmp;
      tmp.p1 = c1.c + n*c1.r;
      tmp.p2 = c2.c + n*(1-i*2)*c2.r;
      ret.push_back(tmp);
      if(cos < mEPS)
	      break; //重複する接線を無視
    }
  }

  return ret;

}

//多角形gの中に点pが含まれているかどうか
int contains(Polygon g, Point p){

  const int IN = 2;
  const int ON = 1;
  const int OUT = 0;

  int n = g.size();

  bool x = false;

  for (int i = 0; i < n; i++){
    Point a = g[i] - p, b = g[(i + 1) % n] - p;
    if (abs(cross(a, b)) < mEPS && dot(a, b) < mEPS) return ON;
    if (a.y > b.y) swap(a, b);
    if (a.y < mEPS && mEPS < b.y && cross(a, b) > mEPS) x = !x;
  }

  return (x ? IN : OUT);

}

//凸法(直線上にある点もすべて反時計周りに列挙する)
Polygon andrewScan(Polygon s){

  Polygon u, l;

  if (s.size() < 3) return s;

  sort(s.begin(), s.end()); //x,yを基準にソート

  u.push_back(s[0]);
  u.push_back(s[1]);

  l.push_back(s[s.size() - 1]);
  l.push_back(s[s.size() - 2]);

  //凸方の上部を生成
  for (int i = 2; i < s.size(); i++){
    for (int n = u.size(); n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) == 1; n--){
      u.pop_back();
    }
    u.push_back(s[i]);
  }

  //凸法の下部を生成
  for (int i = s.size() - 3; i >= 0; i--){
    for (int n = l.size(); n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) == 1; n--){
      l.pop_back();
    }
    l.push_back(s[i]);
  }

  //反時計回りになるように凸包の点の列
  reverse(l.begin(), l.end());
  for (int i = u.size() - 2; i >= 1; i--)
    l.push_back(u[i]);

  return l;

}

const int MAX_N = 65;
int N, K;
Point P[MAX_N];

bool check(double t) 
{
  Circle C[MAX_N];
  REP(n,N) {
    C[n].c = P[n];
    C[n].r = t / P[n].c;
  }

  REP(i,N) {
    FOR(j,i+1,N) {
      if(C[i].r + C[j].r < (C[i].c - C[j].c).abs()) {
        continue;
      }
      auto pp = getCrossPoints(C[i], C[j]);
      vector<Point> pVec; pVec.push_back(pp.first); pVec.push_back(pp.second);
      for(Point point : pVec) {
        if(std::isnan(point.x) || std::isnan(point.y)) {
          continue;
        }
        int ret = 0;
        REP(k,N) {
          double len = (P[k] - point).abs();
          if(len * P[k].c <= t + mEPS) {
            ret++;
          }
        }
        if(K <= ret) {
          return true;
        }
      }
    }
  }

  REP(i,N) {
    int ret = 0;
    REP(j,N) {
      double len = (P[j] - P[i]).abs();
      if(len * P[j].c <= t + mEPS) {
        ret++;
      }
    }
    if(K <= ret) {
      return true;
    }
  }

  return false;
}

signed main()
{
  cin >> N >> K;
  REP(n,N) {
    cin >> P[n].x >> P[n].y >> P[n].c;
  }

  double l = 0, r = 100000000000;
  REP(loop, 100) {
    double mid = (l+r)/2;
    if(check(mid)) {
      r = mid;
    } else {
      l = mid;
    }
  }
  
  printf("%.10f\n", (l+r)/2);

  return 0;
}


Measured memory_bytes: 384