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 Haskell (GHC 7.10.3) (judge verdict: Accepted)

{-# LANGUAGE BangPatterns, Safe #-}
{-# Options_GHC -O2 #-}
--import qualified Data.ByteString.Char8 as C
import Data.Maybe
import Data.Int
import Control.Monad
import Control.Monad.ST
import Data.Array.ST.Safe
import Data.Array
import qualified Data.Array.Unboxed as UA
import Data.List
import Text.Printf

ri :: String -> Int
ri = read 

pmGen :: Int32 -> Int32
pmGen x = fromIntegral $! mod ((16807::Int64) * fromIntegral x) 2147483647

randoms :: Int32 -> [Int32]
randoms = iterate pmGen

randomPermutation :: [Int32] -> Int -> ([Int32], [Int32])
randomPermutation rnds n = runST $ do
  let 
    (r, t) = splitAt (n - 1) rnds
    !n32 = fromIntegral n :: Int32
  p <- newListArray (1, n) [1 .. n32] :: ST s (STUArray s Int Int32)
  forM_ (zip [n, pred n .. 2] r) $ \ (!i, !k) -> do
    let !j = succ $ mod (fromIntegral k) i
    temp <- readArray p i
    readArray p j >>= writeArray p i
    writeArray p j temp
  pe <- getElems p
  return (pe, t)

randomShuffle :: [a] -> [Int32] -> ([a], [Int32])
randomShuffle a rnds = (elems $ array (1, fromIntegral n) $ zip p a, t)
  where
    !n = length a 
    (p, t) = randomPermutation rnds n

eps :: Double 
eps = 1e-10

--(Line a b c): a * x + b * y = c
type Point = (Double, Double)
data Line = Line !Double !Double !Double
data Circle = Circle !Double !Double !Double

line :: Point -> Point -> Line
line (!x1, !y1) (!x2, !y2) = Line a b (a * x1 + b * y1)
  where
    !a = y2 - y1
    !b = x1 - x2

dist :: Point -> Point -> Double
dist (!x1, !y1) (!x2, !y2) = sqrt $! (x1 - x2) ^ 2 +  (y1 - y2) ^ 2

pointInCircle :: Point -> Circle -> Bool
pointInCircle p (Circle !x !y !r) = dist p (x, y) - r < eps

linesIntersection :: Line -> Line -> Maybe (Double, Double)
linesIntersection (Line a1 b1 c1) (Line a2 b2 c2)
  | abs d < eps = Nothing
  | otherwise = let !d' = 1.0 / d in Just ( d' * (c1 * b2 - c2 * b1), d' * (a1 * c2 - a2 * c1))
  where
    !d = a1 * b2 - a2 * b1

circle :: Point -> Point -> Circle
circle p1@(!x1, !y1) (!x2, !y2) = Circle x y (dist (x, y) p1)
  where
    !x = (x1 + x2) * 0.5
    !y = (y1 + y2) * 0.5

circumcircle ::  Point -> Point -> Point -> Maybe Circle
circumcircle p1 p2 p3 = liftM (\ p@(!x, !y) -> Circle x y (dist p p1)) $ linesIntersection (cp p1 p2) (cp p2 p3)
  where
    cp :: Point -> Point -> Line
    cp (!x1, !y1) (!x2, !y2) = Line a b (a * xm + b * ym)
      where
        !xm = (x1 + x2) * 0.5
        !ym = (y1 + y2) * 0.5
        !a = x2 - x1
        !b = y2 - y1


minimalEnclosingBallP2 :: [Point] -> Point -> Point -> Circle
minimalEnclosingBallP2 p q1 q2 = foldl' f (circle q1 q2) p 
  where
    f :: Circle -> Point -> Circle
    f c p = if pointInCircle p c then c else fromJust $ circumcircle q1 q2 p

minimalEnclosingBallP1 :: [Point] -> Point -> [Int32] -> (Circle, [Int32])
minimalEnclosingBallP1 p q1 rnds = (fst $ foldl' f ( circle q1 p', [p']) ps, rnds')
  where
    ( (p' : ps), rnds') = randomShuffle p rnds
    f :: (Circle, [Point]) -> Point -> (Circle, [Point])
    f (c, l) p = if pointInCircle p c then (c, p:l) else (minimalEnclosingBallP2 l q1 p, p:l) 

minimalEnclosingBall :: [Point] -> [Int32] -> Circle
minimalEnclosingBall p rnds = let (c, _, _) = foldl' f (circle p1 p2, [p1,p2], rnds') ps in c
  where
    ( (p1 : p2 : ps), rnds') = randomShuffle p rnds
    f :: (Circle, [Point], [Int32]) -> Point -> (Circle, [Point], [Int32])
    f (c, l, r) p = if pointInCircle p c then (c, p:l, r) else let (c', r') = minimalEnclosingBallP1 l p r in (c', p:l, r') 

solve :: [Int] -> Double
solve (n:a) 
  | n <= 1 = 0.0
  | otherwise = r
  where
    b = tuple2 $ take (2 * n) a
    tuple2 :: [Int] -> [(Double, Double)]
    tuple2 [] = []
    tuple2 (x:y:l) = (fromIntegral x, fromIntegral y) : tuple2 l
    (Circle _ _ !r) = minimalEnclosingBall b (randoms 7777)

main :: IO ()
main = printf "%.20f\n" . solve . map ri . words =<< getContents