#include <bits/stdc++.h>
#define REP(i, n)     for(int i = 0;i < n;i++)
#define REPR(i, n)    for(int i = n;i >= 0;i--)
#define FOR(i, m, n)  for(int i = m;i < n;i++)
#define FORR(i, m, n) for(int i = m;i >= n;i--)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define VRSORT(v) sort(v.begin(), v.end(),greater<long long>());
#define ALL(X) (X).begin(),(X).end()
#define INF 99999999
#define M_PI 3.14159265358979323846
#define MOD 1000000007

#ifdef __LOCAL
    #define DBG(X) cout << #X << " = " << (X) << endl;
    #define SAY(X) cout << (X) << endl;
#else
    #define DBG(X)
    #define SAY(X)
#endif

#ifdef __LOCAL
    #include <filesystem>
    namespace fs = std::filesystem;
#endif

using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

int dx[]={1, 0, -1, 0, 0};
int dy[]={0, 1, 0, -1, 0};
const int INT_INF = (int)(2e9);
const ll  LL_INF = (ll)(2e18);
const int NIL = -1;
static mt19937 _g(time(nullptr));
 
std::string pad(int num){ char buffer[4]; std::snprintf(buffer, sizeof(buffer), "%03d", num); return buffer;}
inline ll randint(ll a, ll b) { ll w = (_g() << 31LL) ^ _g(); return a + w % (b - a + 1); }
inline void fast_io() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); };
template<typename T> inline T sign(T x) { return T(x > 0) - T(x < 0); }
template<typename T, typename S> inline ostream& operator<<(ostream& os, const pair<T, S> p) { cout << "[" << p.first << ";" << p.second << "]"; return os; }
template<typename T, typename S> inline ostream& operator<<(ostream& os, const map<T, S> p) { for (auto el : p) os << "[" << el.first << " " << el.second << "]"; return os; }
template<typename T> inline ostream& operator<<(ostream& os, const vector<T>& v) { for (auto el : v) os << el << " "; return os; }
template<typename T> inline T fetch() { T ret; cin >> ret; return ret; }
template<typename T> inline vector<T> fetch_vec(int sz) { vector<T> ret(sz); for (auto& elem : ret) cin >> elem; return ret; }


const double eps = 1e-9;

int N,K;
struct Niku{
    double x,y;
    double c;
    Niku(double x,double y, double c):x(x),y(y),c(c){};
};
struct Point{
    double x,y;
    Point(double x,double y):x(x),y(y){};
};
vector<Niku> nikus;

void input(){
    fast_io();
    #ifdef __LOCAL
        fs::path p = __FILE__;
        fs::path input,output;
        input = output = p.parent_path();
        input += string("/input/") + string(p.stem()) + string(".txt");
        output += string("/output/") + string(p.stem()) + string(".txt");
        freopen(input.c_str(), "r", stdin);
        freopen(output.c_str(), "w", stdout);
    #endif
    cin >> N >> K;
    nikus.assign(N,Niku(0,0,0));
    REP(i,N){
        cin >> nikus[i].x >> nikus[i].y >> nikus[i].c;
    }
}

int countCoverd(double x, double y, vector<Niku> NikusX){
    int ans=0;
    for(auto niku:NikusX) ans += (((niku.x-x)*(niku.x-x)+(niku.y-y)*(niku.y-y))<=niku.c*niku.c+1e-6);
    // +eps分の余分がなかったら判定を間違う。
    // for(auto niku:NikusX) ans += (((niku.x-x)*(niku.x-x)+(niku.y-y)*(niku.y-y))<=niku.c*niku.c);
    return ans;
}

vector<Point> interPoint(Niku c1, Niku c2){
    vector<Point> ret;
    if(c1.x==c2.x && c1.y==c2.y) return ret;
    double r = (c1.c+c2.c)*(c1.c+c2.c);
    double rx = (c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y);
    if(r-rx<-eps) return ret;
    if(abs(r-rx)<=eps) {
        double x,y;
        x = (c1.x+c2.x)/2;
        y = (c1.y+c2.y)/2;
        ret.emplace_back(x,y);
        return ret;
    }
    if(r-rx>eps) {
        double x1 = c2.x-c1.x;
        double y1 = c2.y-c1.y;
        double a = (x1*x1+y1*y1+c1.c*c1.c-c2.c*c2.c)/2;
        double x,y;
        double D;
        double r;
        double d = (x1*x1+y1*y1)*c1.c*c1.c-a*a;
        if(d<0) return ret;
        D = sqrt(d);
        r = (x1*x1+y1*y1);
        x = (a*x1+y1*D)/r + c1.x;
        y = (a*y1-x1*D)/r + c1.y;
        ret.emplace_back(x,y);
        x = (a*x1-y1*D)/r + c1.x;
        y = (a*y1+x1*D)/r + c1.y;
        ret.emplace_back(x,y);
        return ret;
        }
    return ret;
}

int isOK(double t){
    vector<Niku> nikusT;
    for(auto niku:nikus) nikusT.emplace_back(niku.x, niku.y, t/niku.c);
    int ret=0;
    // for(auto niku:nikusT) ret = max(ret,countCoverd(niku.x, niku.y, nikusT));
    vector<Point> X;
    for(auto niku:nikusT) X.emplace_back(niku.x, niku.y);
    REP(i,N-1) for(int j=i+1;j<N;j++){
    // for(auto c1:nikusT) for(auto c2:nikusT) {
        auto Y = interPoint(nikusT[i],nikusT[j]);
        if(!Y.empty()) copy(Y.begin(),Y.end(),back_inserter(X));
        }
    for(auto c:X) {
        // DBG(c.x)
        // DBG(c.y)
        // DBG(countCoverd(c.x, c.y, nikusT))
        ret = max(ret,countCoverd(c.x, c.y, nikusT));
        }
    return ret;
}

int solve(){
    if(K==1) {cout << 0 << endl; return 0;}
    double ok=2000000;
    double ng=eps;
    double m;
    while((ok-ng)>eps){
        m=(ok+ng)/2;
        if(isOK(m)>=K) ok = m;
        else ng = m;
        // DBG(m)
    }
    cout << fixed << setprecision(10);
    cout << ok << endl;
    return 0;
    
}


int main()
{
    input();
    solve();
    // for(double m=2.4;m<3;m+=0.1){
        // double m = 2.8;
        // cout << m << " " << isOK(m) << endl;
    // }
    return 0;
}


Measured memory_bytes: 384