pub trait IterScan: Sized {
    type Output;
    fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output>;
}
pub trait MarkedIterScan: Sized {
    type Output;
    fn mscan<'a, I: Iterator<Item = &'a str>>(self, iter: &mut I) -> Option<Self::Output>;
}
#[derive(Debug)]
pub struct Scanner<'a> {
    iter: std::str::SplitAsciiWhitespace<'a>,
}
impl<'a> Scanner<'a> {
    #[inline]
    pub fn new(s: &'a str) -> Self {
        let iter = s.split_ascii_whitespace();
        Self { iter }
    }
    #[inline]
    pub fn scan<T: IterScan>(&mut self) -> <T as IterScan>::Output {
        T::scan(&mut self.iter).unwrap()
    }
    #[inline]
    pub fn mscan<T: MarkedIterScan>(&mut self, marker: T) -> <T as MarkedIterScan>::Output {
        marker.mscan(&mut self.iter).unwrap()
    }
    #[inline]
    pub fn scan_vec<T: IterScan>(&mut self, size: usize) -> Vec<<T as IterScan>::Output> {
        (0..size)
            .map(|_| T::scan(&mut self.iter).unwrap())
            .collect()
    }
    #[inline]
    pub fn scan_chars(&mut self) -> Vec<char> {
        self.iter.next().unwrap().chars().collect::<Vec<char>>()
    }
    #[inline]
    pub fn scan_chars_with(&mut self, base: char) -> Vec<usize> {
        self.iter
            .next()
            .unwrap()
            .chars()
            .map(|c| (c as u8 - base as u8) as usize)
            .collect::<Vec<usize>>()
    }
}
mod scanner_impls {
    use super::*;
    macro_rules !iter_scan_impls {($($t :ty ) *) =>{$(impl IterScan for $t {type Output =Self ;#[inline ] fn scan <'a ,I :Iterator <Item =&'a str >>(iter :&mut I ) ->Option <Self >{iter .next () ?.parse ::<$t >() .ok () } } ) *} ;}
    iter_scan_impls !(char u8 u16 u32 u64 usize i8 i16 i32 i64 isize f32 f64 u128 i128 String ) ;
    macro_rules !iter_scan_tuple_impl {($($T :ident ) *) =>{impl <$($T :IterScan ) ,*>IterScan for ($($T ,) *) {type Output =($(<$T as IterScan >::Output ,) *) ;#[inline ] fn scan <'a ,It :Iterator <Item =&'a str >>(_iter :&mut It ) ->Option <Self ::Output >{Some (($($T ::scan (_iter ) ?,) *) ) } } } ;}
    iter_scan_tuple_impl!();
    iter_scan_tuple_impl!(A);
    iter_scan_tuple_impl !(A B ) ;
    iter_scan_tuple_impl !(A B C ) ;
    iter_scan_tuple_impl !(A B C D ) ;
    iter_scan_tuple_impl !(A B C D E ) ;
    iter_scan_tuple_impl !(A B C D E F ) ;
    iter_scan_tuple_impl !(A B C D E F G ) ;
    iter_scan_tuple_impl !(A B C D E F G H ) ;
    iter_scan_tuple_impl !(A B C D E F G H I ) ;
    iter_scan_tuple_impl !(A B C D E F G H I J ) ;
    iter_scan_tuple_impl !(A B C D E F G H I J K ) ;
    pub struct ScannerIter<'a, 'b, T> {
        inner: &'b mut Scanner<'a>,
        _marker: std::marker::PhantomData<fn() -> T>,
    }
    impl<'a, 'b, T: IterScan> Iterator for ScannerIter<'a, 'b, T> {
        type Item = <T as IterScan>::Output;
        fn next(&mut self) -> Option<Self::Item> {
            T::scan(&mut self.inner.iter)
        }
    }
    impl<'a> Scanner<'a> {
        #[inline]
        pub fn iter<'b, T: IterScan>(&'b mut self) -> ScannerIter<'a, 'b, T> {
            ScannerIter {
                inner: self,
                _marker: std::marker::PhantomData,
            }
        }
    }
}
pub mod marker {
    use super::*;
    pub struct Usize1;
    impl IterScan for Usize1 {
        type Output = usize;
        #[inline]
        fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output> {
            usize::scan(iter).map(|x| x.wrapping_sub(1))
        }
    }
    pub struct Isize1;
    impl IterScan for Isize1 {
        type Output = isize;
        #[inline]
        fn scan<'a, I: Iterator<Item = &'a str>>(iter: &mut I) -> Option<Self::Output> {
            isize::scan(iter).map(|x| x.wrapping_sub(1))
        }
    }
}
#[macro_export]
macro_rules !min {($e :expr ) =>{$e } ;($e :expr ,$($es :expr ) ,+) =>{std ::cmp ::min ($e ,min !($($es ) ,+) ) } ;}
#[macro_export]
macro_rules !chmin {($dst :expr ,$($src :expr ) ,+) =>{{let x =std ::cmp ::min ($dst ,min !($($src ) ,+) ) ;$dst =x ;} } ;}
#[macro_export]
macro_rules !max {($e :expr ) =>{$e } ;($e :expr ,$($es :expr ) ,+) =>{std ::cmp ::max ($e ,max !($($es ) ,+) ) } ;}
#[macro_export]
macro_rules !chmax {($dst :expr ,$($src :expr ) ,+) =>{{let x =std ::cmp ::max ($dst ,max !($($src ) ,+) ) ;$dst =x ;} } ;}
/// implement Ord by PartialOrd
///
/// # Example
///
/// ```
/// # use competitive::tools::TotalOrd;
/// let mut a = vec![3.1, 4.1, 5.9, 2.6];
/// a.sort_by_key(|&x| TotalOrd(x));
/// ```
///
#[derive(PartialEq, PartialOrd)]
pub struct TotalOrd<T>(pub T);
impl<T: PartialEq> Eq for TotalOrd<T> {}
impl<T: PartialOrd> Ord for TotalOrd<T> {
    fn cmp(&self, other: &TotalOrd<T>) -> std::cmp::Ordering {
        self.0.partial_cmp(&other.0).unwrap()
    }
}
#[derive(Clone, Debug)]
pub struct Real(pub f64);
impl PartialEq for Real {
    fn eq(&self, other: &Real) -> bool {
        (self.0 - other.0).abs() < EPS
    }
}
impl PartialOrd for Real {
    fn partial_cmp(&self, other: &Real) -> Option<std::cmp::Ordering> {
        if self == other {
            Some(std::cmp::Ordering::Equal)
        } else {
            self.0.partial_cmp(&other.0)
        }
    }
}
pub const EPS: f64 = 1e-8;
use std::ops::{Add, Div, Mul, Neg, Sub};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Complex<T> {
    pub re: T,
    pub im: T,
}
impl<T> Complex<T> {
    #[inline]
    pub fn new(re: T, im: T) -> Self {
        Complex { re, im }
    }
    #[inline]
    pub fn transpose(self) -> Self {
        Complex {
            re: self.im,
            im: self.re,
        }
    }
}
impl<T: Neg<Output = T>> Complex<T> {
    #[inline]
    pub fn conjugate(self) -> Self {
        Self::new(self.re, -self.im)
    }
}
impl<T: Add<Output = T> + Mul<Output = T>> Complex<T> {
    #[inline]
    pub fn dot(self, rhs: Self) -> T {
        self.re * rhs.re + self.im * rhs.im
    }
}
impl<T: Sub<Output = T> + Mul<Output = T>> Complex<T> {
    #[inline]
    pub fn cross(self, rhs: Self) -> T {
        self.re * rhs.im - self.im * rhs.re
    }
}
impl<T: Copy + Add<Output = T> + Mul<Output = T>> Complex<T> {
    #[inline]
    pub fn norm(self) -> T {
        self.re * self.re + self.im * self.im
    }
}
impl Complex<f64> {
    #[inline]
    pub fn polar(r: f64, theta: f64) -> Self {
        Self::new(r * theta.cos(), r * theta.sin())
    }
    #[inline]
    pub fn abs(self) -> f64 {
        self.re.hypot(self.im)
    }
    #[inline]
    pub fn unit(self) -> Self {
        self / self.abs()
    }
    #[inline]
    pub fn angle(self) -> f64 {
        self.im.atan2(self.re)
    }
}
impl<T: Add<Output = T>> Add for Complex<T> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Self::new(self.re + rhs.re, self.im + rhs.im)
    }
}
impl<T: Copy + Add<Output = T>> Add<T> for Complex<T> {
    type Output = Self;
    fn add(self, rhs: T) -> Self::Output {
        Self::new(self.re + rhs, self.im + rhs)
    }
}
impl<T: Sub<Output = T>> Sub for Complex<T> {
    type Output = Self;
    fn sub(self, rhs: Self) -> Self::Output {
        Self::new(self.re - rhs.re, self.im - rhs.im)
    }
}
impl<T: Copy + Sub<Output = T>> Sub<T> for Complex<T> {
    type Output = Self;
    fn sub(self, rhs: T) -> Self::Output {
        Self::new(self.re - rhs, self.im - rhs)
    }
}
impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T>> Mul for Complex<T> {
    type Output = Self;
    fn mul(self, rhs: Self) -> Self::Output {
        Self::new(
            self.re * rhs.re - self.im * rhs.im,
            self.re * rhs.im + self.im * rhs.re,
        )
    }
}
impl<T: Copy + Mul<Output = T>> Mul<T> for Complex<T> {
    type Output = Self;
    fn mul(self, rhs: T) -> Self::Output {
        Self::new(self.re * rhs, self.im * rhs)
    }
}
impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>> Div
    for Complex<T>
{
    type Output = Self;
    fn div(self, rhs: Self) -> Self::Output {
        let d = rhs.re * rhs.re + rhs.im * rhs.im;
        Self::new(
            (self.re * rhs.re + self.im * rhs.im) / d,
            (self.im * rhs.re - self.re * rhs.im) / d,
        )
    }
}
impl<T: Copy + Div<Output = T>> Div<T> for Complex<T> {
    type Output = Self;
    fn div(self, rhs: T) -> Self::Output {
        Self::new(self.re / rhs, self.im / rhs)
    }
}
impl<T: Neg<Output = T>> Neg for Complex<T> {
    type Output = Self;
    fn neg(self) -> Self::Output {
        Self::new(-self.re, -self.im)
    }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum CCW {
    /// a--b--c
    OnlineFront = -2,
    /// a--b-vc
    Clockwise = -1,
    /// a--c--b
    OnSegment = 0,
    /// a--b-^c
    CounterClockwise = 1,
    /// c--a--b
    OnlineBack = 2,
}
pub fn ccw(a: Point, b: Point, c: Point) -> CCW {
    let x = b - a;
    let y = c - a;
    if Real(x.cross(y)) > Real(0.) {
        CCW::CounterClockwise
    } else if Real(x.cross(y)) < Real(0.) {
        CCW::Clockwise
    } else if Real(x.dot(y)) < Real(0.) {
        CCW::OnlineBack
    } else if Real(x.abs()) < Real(y.abs()) {
        CCW::OnlineFront
    } else {
        CCW::OnSegment
    }
}
pub type Point = Complex<f64>;
#[derive(Clone, Debug, PartialEq)]
pub struct Circle {
    c: Point,
    r: f64,
}
impl Circle {
    pub fn new(c: Point, r: f64) -> Self {
        Circle { c: c, r: r }
    }
    pub fn cross_circle(&self, other: &Self) -> Option<(Point, Point)> {
        let d = (self.c - other.c).abs();
        let rc = (d * d + self.r * self.r - other.r * other.r) / (2. * d);
        let rs2 = self.r * self.r - rc * rc;
        if rs2 < 0. {
            return None;
        }
        let rs = rs2.abs().sqrt();
        let diff = (other.c - self.c) / d;
        Some((
            self.c + diff * Point::new(rc, rs),
            self.c + diff * Point::new(rc, -rs),
        ))
    }
    pub fn contains_point(&self, p: Point) -> bool {
        Real((self.c - p).abs()) <= Real(self.r)
    }
}
/// binary search helper
pub trait Bisect: Copy {
    /// return between two elements
    fn halve(self, other: Self) -> Self;
    /// the end condition of binary search
    fn section_end(self, other: Self) -> bool;
}
mod bisect_impl {
    use super::*;
    macro_rules !impl_bisect_unsigned {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {if self >other {other +(self -other ) /2 } else {self +(other -self ) /2 } } fn section_end (self ,other :Self ) ->bool {(if self >other {self -other } else {other -self } ) <=1 } } ) *} ;}
    macro_rules !impl_bisect_signed {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {(self +other ) /2 } fn section_end (self ,other :Self ) ->bool {(self -other ) .abs () <=1 } } ) *} ;}
    macro_rules !impl_bisect_float {($($t :ty ) *) =>{$(impl Bisect for $t {fn halve (self ,other :Self ) ->Self {(self +other ) /2. } fn section_end (self ,other :Self ) ->bool {(self -other ) .abs () <=1e-8 } } ) *} ;}
    impl_bisect_unsigned !(u8 u16 u32 u64 usize ) ;
    impl_bisect_signed !(i8 i16 i32 i64 isize ) ;
    impl_bisect_float !(f32 f64 ) ;
}
pub fn binary_search<T: Bisect, F: Fn(T) -> bool>(f: F, ok: T, err: T) -> T {
    let mut ok = ok;
    let mut err = err;
    while !ok.section_end(err) {
        let m = ok.halve(err);
        if f(m) {
            ok = m;
        } else {
            err = m;
        }
    }
    ok
}
pub fn lower_bound<T: Bisect + Ord>(v: &[T], x: T) -> usize {
    binary_search(|i| v[i as usize] >= x, v.len() as i64, -1) as usize
}
pub fn upper_bound<T: Bisect + Ord>(v: &[T], x: T) -> usize {
    binary_search(|i| v[i as usize] > x, v.len() as i64, -1) as usize
}
fn main() {
    #[allow(unused_imports)]
    use std::io::{Read as _, Write as _};
    let __out = std::io::stdout();
    let mut __in_buf = String::new();
    std::io::stdin().read_to_string(&mut __in_buf).unwrap();
    let mut scanner = Scanner::new(&__in_buf);
    #[allow(unused_macros)]
    macro_rules !scan {() =>{scan !(usize ) } ;(($($t :tt ) ,*) ) =>{($(scan !($t ) ) ,*) } ;([$t :tt ;$len :expr ] ) =>{(0 ..$len ) .map (|_ |scan !($t ) ) .collect ::<Vec <_ >>() } ;({chars :$b :expr } ) =>{scanner .scan_chars_with ($b ) } ;({$t :tt =>$f :expr } ) =>{$f (scan !($t ) ) } ;(chars ) =>{scanner .scan_chars () } ;($t :ty ) =>{scanner .scan ::<$t >() } ;}
    let mut __out = std::io::BufWriter::new(__out.lock());
    #[allow(unused_macros)]
    macro_rules !print {($($arg :tt ) *) =>(::std ::write !(__out ,$($arg ) *) .unwrap () ) }
    #[allow(unused_macros)]
    macro_rules !println {($($arg :tt ) *) =>(::std ::writeln !(__out ,$($arg ) *) .unwrap () ) }
    #[allow(unused_macros)]
    macro_rules! echo {
        ($iter :expr ) => {
            echo!($iter, "\n")
        };
        ($iter :expr ,$sep :expr ) => {
            let mut iter = $iter;
            if let Some(item) = iter.next() {
                print!("{}", item);
            }
            for item in iter {
                print!("{}{}", $sep, item);
            }
            println!();
        };
    }
    let n = scan!();
    let k = scan!();
    let xyc = scan!([(f64, f64, f64); n]);
    let ans = binary_search(
        |t| {
            // d == t/c
            let cs: Vec<_> = xyc
                .iter()
                .map(|&(x, y, c)| Circle::new(Point::new(x, y), t / c))
                .collect();
            let mut ps: Vec<_> = xyc.iter().map(|&(x, y, _)| Point::new(x, y)).collect();
            for i in 0..n - 1 {
                for j in 0..n {
                    let c1 = &cs[i];
                    let c2 = &cs[j];
                    if let Some((p1, p2)) = c1.cross_circle(c2) {
                        ps.push(p1);
                        ps.push(p2);
                    }
                }
            }
            let mut res = 0;
            for p in ps {
                let mut cnt = 0;
                for c in cs.iter() {
                    cnt += c.contains_point(p) as usize;
                }
                chmax!(res, cnt);
            }
            res >= k
        },
        1e10,
        0.,
    );
    println!("{}", ans);
}

Measured memory_bytes: 2728