Problem:
Score : 600 points

Problem Statement

Takahashi wants to grill N pieces of meat on a grilling net, which can be seen as a two-dimensional plane. The coordinates of the i-th piece of meat are \left(x_i, y_i\right), and its hardness is c_i.

Takahashi can use one heat source to grill the meat. If he puts the heat source at coordinates \left(X, Y\right), where X and Y are real numbers, the i-th piece of meat will be ready to eat in c_i \times \sqrt{\left(X - x_i\right)^2 + \left(Y-y_i\right)^2} seconds.

Takahashi wants to eat K pieces of meat. Find the time required to have K or more pieces of meat ready if he put the heat source to minimize this time.

Constraints

All values in input are integers.

1 \leq N \leq 60

1 \leq K \leq N

-1000 \leq x_i , y_i \leq 1000

\left(x_i, y_i\right) \neq \left(x_j, y_j\right) \left(i \neq j \right)

1 \leq c_i \leq 100

Input

Input is given from Standard Input in the following format:

N K
x_1 y_1 c_1
\vdots
x_N y_N c_N

Output

Print the answer.

It will be considered correct if its absolute or relative error from our answer is at most 10^{-6}.

Sample Input 1

4 3
-1 0 3
0 0 3
1 0 2
1 1 40

Sample Output 1

2.4

If we put the heat source at \left(-0.2, 0\right), the 1-st, 2-nd, and 3-rd pieces of meat will be ready to eat within 2.4 seconds. This is the optimal place to put the heat source.

Sample Input 2

10 5
-879 981 26
890 -406 81
512 859 97
362 -955 25
128 553 17
-885 763 2
449 310 57
-656 -204 11
-270 76 40
184 170 16

Sample Output 2

7411.2252

Solution in Rust (1.15.1) (judge verdict: Accepted)

macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut iter = s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; }
macro_rules ! input_inner { ( $ iter : expr ) => { } ; ( $ iter : expr , ) => { } ; ( $ iter : expr , mut $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let mut $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , mut $ var : ident $ ( $ r : tt ) * ) => { let mut $ var = $ iter . next ( ) . unwrap ( ) . parse ::< usize > ( ) . unwrap ( ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident $ ( $ r : tt ) * ) => { let $ var = $ iter . next ( ) . unwrap ( ) . parse ::< usize > ( ) . unwrap ( ) ; input_inner ! { $ iter $ ( $ r ) * } } ; }
macro_rules ! read_value { ( $ iter : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ iter , $ t ) ) ,* ) } ; ( $ iter : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ iter , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ iter : expr , chars ) => { read_value ! ( $ iter , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ iter : expr , usize1 ) => { read_value ! ( $ iter , usize ) - 1 } ; ( $ iter : expr , $ t : ty ) => { $ iter . next ( ) . unwrap ( ) . parse ::<$ t > ( ) . unwrap ( ) } ; }
trait Bisect: Copy {
    fn halve(self, other: Self) -> Self;
    fn section_end(self, other: Self) -> bool;
}
impl Bisect for f64 {
    fn halve(self, other: Self) -> Self {
        (self + other) / 2.
    }
    fn section_end(self, other: Self) -> bool {
        (self - other).abs() <= 1e-8
    }
}
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
}
#[derive(Debug, Clone, Copy)]
struct Complex {
    x: f64,
    y: f64,
}
impl Complex {
    fn new(x: f64, y: f64) -> Complex {
        Complex { x: x, y: y }
    }
    fn abs(self) -> f64 {
        (self.x * self.x + self.y * self.y).sqrt()
    }
    #[allow(dead_code)]
    fn dot(self, other: Complex) -> f64 {
        self.x * other.x + self.y * other.y
    }
    #[allow(dead_code)]
    fn cross(self, other: Complex) -> f64 {
        self.x * other.y - self.y * other.x
    }
}
impl std::ops::Add for Complex {
    type Output = Complex;
    fn add(self, other: Complex) -> Complex {
        Complex {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}
impl std::ops::Add<f64> for Complex {
    type Output = Complex;
    fn add(self, other: f64) -> Complex {
        Complex {
            x: self.x + other,
            y: self.y + other,
        }
    }
}
impl std::ops::Sub for Complex {
    type Output = Complex;
    fn sub(self, other: Complex) -> Complex {
        Complex {
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}
impl std::ops::Sub<f64> for Complex {
    type Output = Complex;
    fn sub(self, other: f64) -> Complex {
        Complex {
            x: self.x - other,
            y: self.y - other,
        }
    }
}
impl std::ops::Mul for Complex {
    type Output = Complex;
    fn mul(self, other: Complex) -> Complex {
        Complex {
            x: self.x * other.x - self.y * other.y,
            y: self.x * other.y + self.y * other.x,
        }
    }
}
impl std::ops::Mul<f64> for Complex {
    type Output = Complex;
    fn mul(self, other: f64) -> Complex {
        Complex {
            x: self.x * other,
            y: self.y * other,
        }
    }
}
impl std::ops::Div<f64> for Complex {
    type Output = Complex;
    fn div(self, other: f64) -> Complex {
        Complex {
            x: self.x / other,
            y: self.y / other,
        }
    }
}
impl std::ops::Neg for Complex {
    type Output = Complex;
    fn neg(self) -> Complex {
        Complex {
            x: -self.x,
            y: -self.y,
        }
    }
}
const EPS: f64 = 1e-8;
#[derive(Debug, Clone)]
struct Circle {
    c: Complex,
    r: f64,
}
impl Circle {
    fn new(c: Complex, r: f64) -> Circle {
        Circle { c: c, r: r }
    }
    fn cross_circle(&self, other: &Circle) -> Option<(Complex, Complex)> {
        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 * Complex::new(rc, rs),
            self.c + diff * Complex::new(rc, -rs),
        ))
    }
    fn contains_point(&self, p: Complex) -> bool {
        (self.c - p).abs() <= self.r + EPS
    }
}
struct Niku {
    ps: Vec<Complex>,
    c: Vec<f64>,
    k: usize,
}
impl Niku {
    fn new(xyc: Vec<(f64, f64, f64)>, k: usize) -> Niku {
        Niku {
            ps: xyc
                .iter()
                .map(|&(x, y, _)| Complex::new(x, y))
                .collect::<Vec<_>>(),
            c: xyc.iter().map(|&(_, _, c)| c).collect::<Vec<_>>(),
            k: k,
        }
    }
    fn ok(&self, t: f64) -> bool {
        let n = self.ps.len();
        let circles = self
            .ps
            .iter()
            .zip(self.c.iter())
            .map(|(&p, &c)| Circle::new(p, t / c))
            .collect::<Vec<_>>();
        let mut v = self.ps.clone();
        for i in 0..n - 1 {
            for j in i + 1..n {
                if let Some((p1, p2)) = circles[i].cross_circle(&circles[j]) {
                    v.push(p1);
                    v.push(p2);
                }
            }
        }
        v.into_iter()
            .any(|p| circles.iter().filter(|c| c.contains_point(p)).count() >= self.k)
    }
}
fn main() {
    input! { n, k, xyc: [(f64, f64, f64); n] };
    let niku = Niku::new(xyc, k);
    println!("{}", binary_search(|t| niku.ok(t), 300000., 0.));
}