#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define REP(i,n) for (ll i = 0; i < (n); ++i)

template<typename T>
struct Point {
    T x, y;
    Point() : x(0), y(0) {}
    Point(T x, T y) : x(x), y(y) {}

    int quadrant() const {
        if(x == 0 && y == 0){
            return 0;
        }
        if(x >= 0){
            if(y >= 0){
                return 1;
            }else{
                return 4;
            }
        }else{
            if(y >= 0){
                return 2;
            }else{
                return 3;
            }
        }
    }

    Point& operator+=(const Point& other){
        x += other.x;
        y += other.y;
        return *this;
    }

    Point& operator-=(const Point& other){
        x -= other.x;
        y -= other.y;
        return *this;
    }

    Point operator+(const Point& other) const {
        return Point(x, y) += other;
    }
    Point operator-(const Point& other) const{
        return Point(x, y) -= other;
    }

    T cross(const Point& q) const {
        return x * q.y - y * q.x;
    }

    bool operator<(const Point& q) const {
        int qp = quadrant();
        int qq = q.quadrant();
        if(qp != qq){ return qp < qq; }
        return cross(q) > 0;
    }

    bool operator<=(const Point& q) const {
        int qp = quadrant();
        int qq = q.quadrant();
        if(qp != qq){ return qp < qq; }
        return cross(q) >= 0;
    }

    T dot(const Point& q) const {
        return x * q.x + y * q.y;
    }

    T norm2() const {
        return x * x + y * y;
    }

    double norm() const {
        return sqrt((double)norm2());
    }

    double dist(const Point& q) const {
        return (*this - q).norm();
    }
};

template<typename T>
double dist(const Point<T>& p, const Point<T>& q){
    return p.dist(q);
}

double continuous_ternary_search(
    double left, double right,
    function<double(double)> f,
    bool maximize,
    ll max_loop = 100
){
    function<double(double)> f2 = f;
    if(!maximize){
        f2 = [&](double x) -> double { return - f(x); };
    }
    REP(i, max_loop){
        if (f2((left * 2 + right) / 3) > f2((left + right * 2) / 3)){
            right = (left + right * 2) / 3;
        }else{
            left = (left * 2 + right) / 3;
        }
    }
    return (left + right) * 0.5;
}


vector<Point<double>> xy;

double max_dist(const Point<double>& p){
    double ret = 0;
    for(const auto& q : xy){ ret = max(ret, dist(p, q)); }
    return ret;
}

double min_max_dist(double x){
    double min_y = continuous_ternary_search(
        0, 1000,
        [&](double y){ return max_dist(Point<double>(x, y)); },
        false, 100
    );
    return max_dist(Point<double>(x, min_y));
}

void solve(long long N, std::vector<long long> x, std::vector<long long> y){
    xy.resize(N);
    REP(i, N){ xy.at(i) = Point<double>(x.at(i), y.at(i)); }

    double min_x = continuous_ternary_search(
        0, 1000,
        [&](double x){ return min_max_dist(x); },
        false, 100
    );
    double min_r = min_max_dist(min_x);
    printf("%.10f\n", min_r);
}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools
int main(){
    long long N;
    scanf("%lld",&N);
    std::vector<long long> x(N);
    std::vector<long long> y(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&x[i]);
        scanf("%lld",&y[i]);
    }
    solve(N, std::move(x), std::move(y));
    return 0;
}


Measured memory_bytes: 256