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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Linq;

using E = System.Linq.Enumerable;
using System.Numerics;

internal partial class Solver {
    public void Run() {
        var n = ni();
        var x = new int[n];
        var y = new int[n];
        for (int i = 0; i < n; i++) {
            x[i] = ni();
            y[i] = ni();
        }
        var p = x.Zip(y, (X, Y) => new Vector3(X, Y, 0)).ToList();

        cout.WriteLine("{0:F20}", SmallestEnclosingBall.Find(p).Radius);

    }

}

public class Sphere {
    public Vector3 Center;
    public double Radius;

    public bool IsInside(Vector3 p) {
        if ((Center - p).Abs() < Radius + (1e-9)) {
            return true;
        }

        return false;
    }
}

public struct Vector3 {
    public readonly double X, Y, Z;
    public Vector3(double x = 0, double y = 0, double z = 0) {
        X = x;
        Y = y;
        Z = z;
    }

    public static Vector3 operator +(Vector3 v1, Vector3 v2) {
        return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
    }
    public static Vector3 operator -(Vector3 v1, Vector3 v2) {
        return new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
    }
    public static Vector3 operator *(Vector3 v, double a) {
        return new Vector3(v.X * a, v.Y * a, v.Z * a);
    }
    public static Vector3 operator *(double a, Vector3 v) {
        return new Vector3(v.X * a, v.Y * a, v.Z * a);
    }
    public static Vector3 operator /(Vector3 v, double a) {
        return v * (1.0 / a);
    }
    public static double Dot(Vector3 v1, Vector3 v2) {
        return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
    }

    public double Norm() {
        return X * X + Y * Y + Z * Z;
    }
    public double Abs() {
        return Math.Sqrt(Norm());
    }
}
/// <summary>
/// 最小包含球
/// 
/// http://www.inf.ethz.ch/personal/gaertner/texts/own_work/esa99_final.pdf
/// </summary>
public static class SmallestEnclosingBall {
    private static readonly Vector3[] v = new Vector3[4];
    private static readonly Vector3[] c = new Vector3[4];
    private static readonly double[] r = new double[4];

    private static Sphere b_md(List<Vector3> R) {
        int n = R.Count;
        if (n >= 1) {
            r[0] = 0;
            c[0] = R[0];
            if (n > 1) {
                int p = n - 1;
                v[p] = R[p] - c[0];
                for (int j = 1; j < p; j++) {
                    v[p] -= v[j] * Vector3.Dot(v[j], R[p] - c[0]) / v[j].Norm();
                }
                double d = (R[p] - c[p - 1]).Abs();
                double e = (d - r[p - 1] * r[p - 1] / d) / 2.0;
                c[p] = c[p - 1] + v[p] / v[p].Norm() * e * d;
                r[p] = (c[p] - R[0]).Abs();
            }
            return new Sphere() { Center = c[n - 1], Radius = r[n - 1] };
        }
        return new Sphere() { Center = new Vector3(), Radius = -1 };
    }

    private static Sphere b_miniball(LinkedListNode<Vector3> node, LinkedList<Vector3> points, List<Vector3> stacked) {
        var D = b_md(stacked);
        if (stacked.Count == 4) {
            return D;
        }

        var current = points.First;
        while (current != node) {
            var next = current.Next;
            if (!D.IsInside(current.Value)) {
                stacked.Add(current.Value);
                D = b_miniball(current, points, stacked);
                stacked.RemoveAt(stacked.Count - 1);
                points.AddFirst(current.Value);
                points.Remove(current);
            }
            current = next;
        }
        return D;
    }

    public static Sphere Find(IEnumerable<Vector3> points) {
        var list = new LinkedList<Vector3>();
        var R = new List<Vector3>();
        foreach (var V in points) {
            list.AddLast(V);
        }
        return b_miniball(null, list, R);
    }
}

// PREWRITEN CODE BEGINS FROM HERE
internal partial class Solver : Scanner {
    public static void Main(string[] args) {
#if LOCAL
        byte[] inputBuffer = new byte[1000000];
        var inputStream = Console.OpenStandardInput(inputBuffer.Length);
        using (var reader = new StreamReader(inputStream, Console.InputEncoding, false, inputBuffer.Length)) {
            Console.SetIn(reader);
            new Solver(Console.In, Console.Out).Run();
        }
#else
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver(Console.In, Console.Out).Run();
        Console.Out.Flush();
#endif
    }

#pragma warning disable IDE0052
    private readonly TextReader cin;
    private readonly TextWriter cout;
#pragma warning restore IDE0052

    public Solver(TextReader reader, TextWriter writer)
        : base(reader) {
        cin = reader;
        cout = writer;
    }
    public Solver(string input, TextWriter writer)
        : this(new StringReader(input), writer) {
    }

#pragma warning disable IDE1006
#pragma warning disable IDE0051
    private int ni() { return NextInt(); }
    private int[] ni(int n) { return NextIntArray(n); }
    private long nl() { return NextLong(); }
    private long[] nl(int n) { return NextLongArray(n); }
    private double nd() { return NextDouble(); }
    private double[] nd(int n) { return NextDoubleArray(n); }
    private string ns() { return Next(); }
    private string[] ns(int n) { return NextArray(n); }
#pragma warning restore IDE1006
#pragma warning restore IDE0051
}

internal static class LinqPadExtension {
    [Conditional("DEBUG")]
    public static void Dump<T>(this T obj) {
#if DEBUG
        LINQPad.Extensions.Dump(obj);
#endif
    }
}

public class Scanner {
    private readonly TextReader Reader;
    private readonly CultureInfo ci = CultureInfo.InvariantCulture;

    private readonly char[] buffer = new char[2 * 1024];
    private int cursor = 0, length = 0;
    private string Token;
    private readonly StringBuilder sb = new StringBuilder(1024);

    public Scanner()
        : this(Console.In) {
    }

    public Scanner(TextReader reader) {
        Reader = reader;
    }

    public int NextInt() { return (int)NextLong(); }
    public long NextLong() {
        var s = Next();
        long r = 0;
        int i = 0;
        bool negative = false;
        if (s[i] == '-') {
            negative = true;
            i++;
        }
        for (; i < s.Length; i++) {
            r = r * 10 + (s[i] - '0');
#if DEBUG
            if (!char.IsDigit(s[i])) throw new FormatException();
#endif
        }
        return negative ? -r : r;
    }
    public double NextDouble() { return double.Parse(Next(), ci); }
    public string[] NextArray(int size) {
        string[] array = new string[size];
        for (int i = 0; i < size; i++) {
            array[i] = Next();
        }

        return array;
    }
    public int[] NextIntArray(int size) {
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextInt();
        }

        return array;
    }

    public long[] NextLongArray(int size) {
        long[] array = new long[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextLong();
        }

        return array;
    }

    public double[] NextDoubleArray(int size) {
        double[] array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextDouble();
        }

        return array;
    }

    public string Next() {
        if (Token == null) {
            if (!StockToken()) {
                throw new InvalidOperationException();
            }
        }
        var token = Token;
        Token = null;
        return token;
    }

    public bool HasNext() {
        if (Token != null) {
            return true;
        }

        return StockToken();
    }

    private bool StockToken() {
        while (true) {
            sb.Clear();
            while (true) {
                if (cursor >= length) {
                    cursor = 0;
                    if ((length = Reader.Read(buffer, 0, buffer.Length)) <= 0) {
                        break;
                    }
                }
                var c = buffer[cursor++];
                if (33 <= c && c <= 126) {
                    sb.Append(c);
                } else {
                    if (sb.Length > 0) break;
                }
            }

            if (sb.Length > 0) {
                Token = sb.ToString();
                return true;
            }

            return false;
        }
    }
}