Problem:
Score : 600 points

Problem Statement

Given are N points (x_i, y_i) in a two-dimensional plane.

Find the minimum radius of a circle such that all the points are inside or on it.

Constraints

2 \leq N \leq 50

0 \leq x_i \leq 1000

0 \leq y_i \leq 1000

The given N points are all different.

The values in input are all integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
:
x_N y_N

Output

Print the minimum radius of a circle such that all the N points are inside or on it.

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

Sample Input 1

2
0 0
1 0

Sample Output 1

0.500000000000000000

Both points are contained in the circle centered at (0.5,0) with a radius of 0.5.

Sample Input 2

3
0 0
0 1
1 0

Sample Output 2

0.707106781186497524

Sample Input 3

10
10 9
5 9
2 0
0 0
2 7
3 3
2 5
10 0
3 7
1 9

Sample Output 3

6.726812023536805158

If the absolute or relative error from our answer is at most 10^{-6}, the output will be considered correct.

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

#![allow(unused_imports)]
use {
   proconio::{fastout, input, marker::*},
   std::cmp::*,
   std::collections::*,
};

use std::ops::*;
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
struct Point<T> {
   x: T,
   y: T,
}
impl<T: Add<Output = T>> Add for Point<T> {
   type Output = Point<T>;
   fn add(self, other: Self) -> Self::Output {
      Point {
         x: self.x + other.x,
         y: self.y + other.y,
      }
   }
}
impl<T: Sub<Output = T>> Sub for Point<T> {
   type Output = Point<T>;
   fn sub(self, other: Self) -> Self::Output {
      Point {
         x: self.x - other.x,
         y: self.y - other.y,
      }
   }
}
impl<T: Copy + Clone + Mul<Output = T>> Mul<T> for Point<T> {
   type Output = Point<T>;
   fn mul(self, other: T) -> Self::Output {
      Point {
         x: self.x * other,
         y: self.y * other,
      }
   }
}
impl<T: Copy + Clone + Div<Output = T>> Div<T> for Point<T> {
   type Output = Point<T>;
   fn div(self, other: T) -> Self::Output {
      Point {
         x: self.x / other,
         y: self.y / other,
      }
   }
}
impl<T: Copy + Clone + Add<Output = T> + Mul<Output = T>> Point<T> {
   fn new(x: T, y: T) -> Self { Point { x: x, y: y } }
   fn dot(self, other: Self) -> T { self.x * other.x + self.y * other.y }
   fn pow(self) -> T { self.dot(self) }
}
impl Point<f64> {
   fn abs(self) -> f64 { self.dot(self).sqrt() }
   fn rot(self, theta: f64) -> Self {
      Point {
         x: self.x * theta.cos() - self.y * theta.sin(),
         y: self.x * theta.sin() + self.y * theta.cos(),
      }
   }
}

use std::f64::consts::PI;
fn intersection(r: f64, p1: Point<f64>, p2: Point<f64>) -> Option<(Point<f64>, Point<f64>)> {
   let pm = (p1 + p2) / 2.0;
   let pd = p1 - p2;
   let dr = pd.abs();
   if dr <= 2.0 * r {
      let h = (r * r - dr * dr / 4.0).sqrt();
      let ph = pd.rot(PI / 2.0) / dr * h;
      return Some((pm + ph, pm - ph));
   }
   None
}

fn main() {
   input! {
      n:usize,
      xy: [(f64, f64); n]
   }
   let ps: Vec<_> = xy.iter().map(|&(x, y)| Point::new(x, y)).collect();

   let mut low = 0f64;
   let mut high = 1000f64;
   let mut pm = vec![];
   for i in 0..n {
      for j in i + 1..n {
         pm.push((ps[i] + ps[j]) / 2.0);
      }
   }

   for &p1 in pm.iter() {
      let mut mx = 0f64;
      for &p2 in ps.iter() {
         let r = (p1 - p2).abs();
         if mx < r {
            mx = r;
         }
      }
      if mx < high {
         high = mx;
      }
   }

   'outer: for _ in 0..100 {
      let r = (high + low) / 2.0;
      let mut points = pm.clone();
      for i in 0..n - 1 {
         for j in i + 1..n {
            if let Some((p1, p2)) = intersection(r, ps[i], ps[j]) {
               points.push(p1);
               points.push(p2);
            } else {
               low = r;
               continue 'outer;
            }
         }
      }
      let mut flag = false;
      let mut rm = 0f64;
      'outer1: for &p1 in points.iter() {
         for &p2 in ps.iter() {
            let rn = (p1 - p2).abs();
            if rn > r {
               continue 'outer1;
            }
            if rn > rm {
               rm = rn;
            }
         }
         flag = true;
         break;
      }
      if flag {
         high = rm;
      } else {
         low = r;
      }
   }
   println!("{0:.10}", high);
}