fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());

    let n: usize = sc.read();
    let k: usize = sc.read();

    let mut circles = vec![];
    for _ in 0..n {
        let x: f64 = sc.read();
        let y: f64 = sc.read();
        let c: f64 = sc.read();
        circles.push((x, y, c));
    }

    let mut ok = 1e15;
    let mut ng = 0.0;
    let mut p_ok = ok;
    let mut p_ng = ng;
    loop {
        let time = (ok + ng) / 2.0;

        if is_ok(&circles, k, time) {
            ok = time;
        } else {
            ng = time;
        }

        if p_ok == ok && p_ng == ng {
            break;
        }
        p_ok = ok;
        p_ng = ng;
    }

    println!("{}", (ok + ng) / 2.0);
}

fn is_ok(circles: &[(f64, f64, f64)], k: usize, time: f64) -> bool {
    let circles = circles
        .iter()
        .map(|&(x, y, c)| {
            let r = time / c;
            (Point(x, y), r)
        })
        .collect::<Vec<_>>();

    let n = circles.len();
    let mut candidates = vec![];
    for i in 0..n {
        for j in 0..i {
            let c1 = circles[i];
            let c2 = circles[j];
            candidates.extend(cc_intersect(c1, c2));
        }
        candidates.push(circles[i].0);
    }

    for p in candidates.into_iter() {
        let mut count = 0;
        for &(center, r) in circles.iter() {
            let dist = (center - p).abs();
            if dist <= r + 1e-7 {
                count += 1;
            }
        }
        if count >= k {
            return true;
        }
    }
    false
}

pub fn cc_intersect((p1, r1): (Point, f64), (p2, r2): (Point, f64)) -> Vec<Point> {
    let dist = (p1 - p2).abs();
    if dist > r1 + r2 {
        return Vec::new();
    }

    let rc = (dist * dist + r1 * r1 - r2 * r2) / (2. * dist);
    let rs = (r1 * r1 - rc * rc).sqrt();
    let diff = (p2 - p1) / dist;
    vec![p1 + diff * Point(rc, rs), p1 + diff * Point(rc, -rs)]
}

#[derive(Copy, Clone)]
pub struct Point(f64, f64);

impl Point {
    fn abs(self) -> f64 {
        let x = self.0;
        let y = self.1;
        (x * x + y * y).sqrt()
    }
}

impl ::std::ops::Add<Point> for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point(self.0 + rhs.0, self.1 + rhs.1)
    }
}

impl ::std::ops::Sub<Point> for Point {
    type Output = Point;
    fn sub(self, rhs: Point) -> Point {
        Point(self.0 - rhs.0, self.1 - rhs.1)
    }
}

impl ::std::ops::Div<f64> for Point {
    type Output = Point;
    fn div(self, rhs: f64) -> Point {
        Point(self.0 / rhs, self.1 / rhs)
    }
}

impl ::std::ops::Mul<Point> for Point {
    type Output = Point;
    fn mul(self, rhs: Point) -> Point {
        let Point(x1, y1) = self;
        let Point(x2, y2) = rhs;
        Point(x1 * x2 - y1 * y2, x1 * y2 + y1 * x2)
    }
}
pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> Self {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 4476