Problem:
Problem I:
Most Distant Point from the Sea
The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it
is natural to ask a question: "Where is the most distant point from the sea?" The answer to
this question for Honshu was found in 1996. The most distant point is located in former Usuda
Town, Nagano Prefecture, whose distance from the sea is 114.86 km.
In this problem, you are asked to write a program which, given a map of an island, finds the
most distant point from the sea in the island, and reports its distance from the sea. In order to
simplify the problem, we only consider maps representable by convex polygons.
Input
The input consists of multiple datasets. Each dataset represents a map of an island, which is a convex polygon. The format of a dataset is as follows.
n
x
1
y
1
.
   .
   .
x
n
y
n
Every input item in a dataset is a non-negative integer. Two input items in a line are separated by a space.
n
in the first line is the number of vertices of the polygon, satisfying 3 ≤
n
≤ 100. Subsequent
n
lines are the
x
- and
y
-coordinates of the
n
vertices. Line segments (
x
i
,
y
i
) - (
x
i
+1
,
y
i
+1
) (1 ≤
i
≤
n
- 1) and the line segment (
x
n
,
y
n
) - (
x
1
,
y
1
) form the border of the polygon in counterclockwise order. That is, these line segments see the inside of the polygon in the left of their directions. All coordinate values are between 0 and 10000, inclusive.
You can assume that the polygon is simple, that is, its border never crosses or touches itself. As stated above, the given polygon is always a convex one.
The last dataset is followed by a line containing a single zero.
Output
For each dataset in the input, one line containing the distance of the most distant point from
the sea should be output. An output line should not contain extra characters such as spaces.
The answer should not have an error greater than 0.00001 (10
-5
). You may output any number
of digits after the decimal point, provided that the above accuracy condition is satisfied.
Sample Input
4
0 0
10000 0
10000 10000
0 10000
3
0 0
10000 0
7000 1000
6
0 40
100 20
250 40
250 70
100 90
0 70
3
0 0
10000 10000
5000 5001
0
Output for the Sample Input
5000.000000
494.233641
34.542948
0.353553

Submitted solutions:

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

template < class T > struct point {
    T x, y;
    point() : x(0), y(0) {}
    point(T x, T y) : x(x), y(y) {}
    point(std::pair< T, T > p) : x(p.first), y(p.second) {}
    point& operator+=(const point& p) { x += p.x, y += p.y; return *this; }
    point& operator-=(const point& p) { x -= p.x, y -= p.y; return *this; }
    point& operator*=(const T r) { x *= r, y *= r; return *this; }
    point& operator/=(const T r) { x /= r, y /= r; return *this; }
    point operator+(const point& p) const { return point(*this) += p; }
    point operator-(const point& p) const { return point(*this) -= p; }
    point operator*(const T r) const { return point(*this) *= r; }
    point operator/(const T r) const { return point(*this) /= r; }
    point operator-() const { return {-x, -y}; }
    bool operator==(const point& p) const { return x == p.x and y == p.y; }
    bool operator!=(const point& p) const { return x != p.x or  y != p.y; }
    bool operator<(const point& p) const { return x == p.x ? y < p.y : x < p.x; }
    point< T > rot(double theta) {
        static_assert(is_floating_point_v< T >);
        double cos_ = std::cos(theta), sin_ = std::sin(theta);
        return {cos_ * x - sin_ * y, sin_ * x + cos_ * y};
    }
};
template < class T > istream& operator>>(istream& is, point< T >& p) { return is >> p.x >> p.y; }
template < class T > ostream& operator<<(ostream& os, point< T >& p) { return os << p.x << " " << p.y; }
template < class T > T dot(const point< T >& a, const point< T >& b) { return a.x * b.x + a.y * b.y; }
template < class T > T det(const point< T >& a, const point< T >& b) { return a.x * b.y - a.y * b.x; }
template < class T > T norm(const point< T >& p) { return p.x * p.x + p.y * p.y; }
template < class T > double abs(const point< T >& p) { return std::sqrt(norm(p)); }
template < class T > double angle(const point< T >& p) { return std::atan2(p.y, p.x); }
template < class T > int sign(const T x) {
    T e = (is_integral_v< T > ? 1 : 1e-8);
    if(x <= -e) return -1;
    if(x >= +e) return +1;
    return 0;
}
template < class T > bool equals(const T& a, const T& b) { return sign(a - b) == 0; }
template < class T > int ccw(const point< T >& a, point< T > b, point< T > c) {
    b -= a, c -= a;
    if(sign(det(b, c)) == +1) return +1; // counter clockwise
    if(sign(det(b, c)) == -1) return -1; //         clockwise
    if(sign(dot(b, c)) == -1) return +2; // c-a-b
    if(norm(b) < norm(c)) return -2;     // a-b-c
    return 0;                            // a-c-b
}

template < class T > struct line {
    point< T > a, b;
    line() {}
    line(point< T > a, point< T > b) : a(a), b(b) {}
};
template < class T > point< T > projection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
}
template < class T > point< T > reflection(const line< T >& l, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    return p + (projection(l, p) - p) * T(2);
}
template < class T > bool orthogonal(const line< T >& a, const line< T >& b) { return equals(dot(a.b - a.a, b.b - b.a), T(0)); }
template < class T > bool parallel  (const line< T >& a, const line< T >& b) { return equals(det(a.b - a.a, b.b - b.a), T(0)); }
template < class T > point< T > cross_point_ll(const line< T >& l, const line< T >& m) {
    static_assert(is_floating_point_v< T >);
    T A = det(l.b - l.a, m.b - m.a);
    T B = det(l.b - l.a, l.b - m.a);
    if(equals(abs(A), T(0)) and equals(abs(B), T(0))) return m.a;
    return m.a + (m.b - m.a) * B / A;
}

template < class T > using segment = line< T >;
template < class T > bool intersect_ss(const segment< T >& s, const segment< T >& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 and ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
template < class T > double distance_sp(const segment< T >& s, const point< T >& p) {
    static_assert(is_floating_point_v< T >);
    point r = projection(s, p);
    if(ccw(s.a, s.b, r) == 0) return abs(r - p);
    return std::min(abs(s.a - p), abs(s.b - p));
}
template < class T > double distance_ss(const segment< T >& a, const segment< T >& b) {
    if(intersect_ss(a, b)) return 0;
    return std::min({ distance_sp(a, b.a), distance_sp(a, b.b), distance_sp(b, a.a), distance_sp(b, a.b) });
}

template < class T > using polygon = std::vector< point< T > >;
template < class T > T area2(const polygon< T >& p) {
    T s = 0;
    int n = p.size();
    for(int i = 0; i < n; i++) s += det(p[i], p[(i + 1) % n]);
    return s;
}
template < class T > T area(const polygon< T >& p) { return area2(p) / T(2); }

template < class T > bool is_convex(const polygon< T >& p) {
    int n = p.size();
    for(int i = 0; i < n; i++) if(ccw(p[(i - 1 + n) % n], p[i], p[(i + 1) % n]) == -1) return false;
    return true;
}
template < class T > int contains(const polygon< T >& g, const point< T >& p) {
    int n = g.size();
    bool in = false;
    for(int i = 0; i < n; i++) {
        point a = g[i] - p, b = g[(i + 1) % n] - p;
        if(sign(a.y - b.y) == +1) std::swap(a, b);
        if(sign(a.y) <= 0 and sign(b.y) ==+1 and sign(det(a, b)) == -1) in = !in;
        if(sign(det(a, b)) == 0 and sign(dot(a, b)) <= 0) return 1; // ON
    }
    return in ? 2 : 0;
}
template < class T > polygon< T > convex_cut(const polygon< T >& p, const line< T >& l) {
    int n = p.size();
    polygon< T > res;
    for(int i = 0; i < n; i++) {
        point now = p[i], nxt = p[(i + 1) % n];
        if(ccw(l.a, l.b, now) != -1) res.push_back(now);
        if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0) res.push_back(cross_point_ll(line(now, nxt), l));
    }
    return res;
}
template < class T > polygon< T > convex_hull(polygon< T >& p) {
    int n = p.size(), k = 0;
    if(n <= 2) return p;
    std::sort(p.begin(), p.end());
    polygon< T > ch(n + n);
    for(int i = 0; i < n; ch[k++] = p[i++])
        while(k >= 2 and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
        while(k >= t and sign(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) == -1) k--;
    ch.resize(k - 1);
    return ch;
}
template < class T > T diameter2(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    int n = p.size(), is = 0, js = 0;
    for(int i = 1; i < n; i++) {
        if(sign(p[i].y - p[is].y) == +1) is = i;
        if(sign(p[i].y - p[js].y) == -1) js = i;
    }
    T dist_max = norm(p[is] - p[js]);
    int maxi = is, i = is, maxj = js, j = js;
    do {
        if(sign(det(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j])) >= 0) j = (j + 1) % n; else i = (i + 1) % n;
        if(norm(p[i] - p[j]) > dist_max) {
            dist_max = norm(p[i] - p[j]);
            maxi = i, maxj = j;
        }
    } while(i != is or j != js);
    return dist_max;
}
template < class T > double diameter(const polygon< T >& p) {
    static_assert(is_floating_point_v< T >);
    return std::sqrt(diameter2(p));
}

template < class T > struct circle {
    point< T > p;
    T r;
    circle() = default;
    circle(point< T > p, T r) : p(p), r(r) {}
};
template < class T > istream& operator>>(istream& is, circle< T >& c) { return is >> c.p >> c.r; }
template < class T > int intersect_cc(circle< T > c1, circle< T > c2) {
    if(c1.r < c2.r) std::swap(c1, c2);
    T d = abs(c1.p - c2.p);
    if(sign(c1.r + c2.r - d) == -1) return 4;
    if(equals(c1.r + c2.r, d)) return 3;
    if(sign(c1.r - c2.r - d) == -1) return 2;
    if(equals(c1.r - c2.r, d)) return 1;
    return 0;
}
template < class T > std::pair<point< T >, point< T >> cross_point_cc(const circle< T >& c1, const circle< T >& c2) {
    T d = abs(c1.p - c2.p);
    T a = std::acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    T t = angle(c2.p - c1.p);
    point< T > p1 = c1.p + point< T >(std::cos(t + a), std::sin(t + a)) * c1.r;
    point< T > p2 = c1.p + point< T >(std::cos(t - a), std::sin(t - a)) * c1.r;
    return {p1, p2};
}

f64 solve(int n) {
    polygon<f64> p(n);
    for(int i : rep(n)) p[i] = in();

    return bin_search_real<f64>(0, 1e4, [&](f64 x) {
        polygon<f64> a = p;
        for(int i : rep(n)) {
            line<f64> l(p[i], p[(i + 1) % n]);

            point<f64> dp = p[(i + 1) % n] - p[i];
            point<f64> e(-dp.y, dp.x);
            e /= abs(e);
            l.a += e * x;
            l.b += e * x;

            a = convex_cut(a, l);
        }
        return a.size() >= 2;
    });
}

int main() {
    while(true) {
        int n = in();
        if(n == 0) return 0;
        printer::precision(20);
        print(solve(n));
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3516
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) {
        os << v[i];
        if (i < (int) v.size() - 1) os << " ";
    }
    return os;
}

template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}



using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-8;
inline bool eq(T a, T b) { return std::abs(a - b) <= eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) <= eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a <= b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec perp(const Vec& a) {
    return Vec(-a.imag(), a.real());
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// -1: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

std::vector<Vec> halfplane_intersection(std::vector<std::pair<Vec, Vec>> hps) {
    using Hp = std::pair<Vec, Vec>;  // (normal vector, a point on the border)

    auto intersection = [&](const Hp& l1, const Hp& l2) -> Vec {
        auto d = l2.second - l1.second;
        Vec e(-l1.first.imag(), l1.first.real());
        return l1.second + (dot(d, l2.first) / cross(l1.first, l2.first)) * e;
    };

    // check if the halfplane h contains the point p
    auto contains = [&](const Hp& h, const Vec& p) -> bool {
        return dot(p - h.second, h.first) > 0;
    };

    constexpr T INF = 1e15;
    hps.emplace_back(Vec(1, 0), Vec(-INF, 0));  // -INF <= x
    hps.emplace_back(Vec(-1, 0), Vec(INF, 0));  // x <= INF
    hps.emplace_back(Vec(0, 1), Vec(0, -INF));  // -INF <= y
    hps.emplace_back(Vec(0, -1), Vec(0, INF));  // y <= INF

    std::sort(hps.begin(), hps.end(), [&](const auto& h1, const auto& h2) {
        return std::arg(h1.first) < std::arg(h2.first);
    });

    std::deque<Hp> dq;
    int len = 0;
    for (auto& hp : hps) {
        while (len > 1 && !contains(hp, intersection(dq[len-1], dq[len-2]))) {
            dq.pop_back();
            --len;
        }

        while (len > 1 && !contains(hp, intersection(dq[0], dq[1]))) {
            dq.pop_front();
            --len;
        }

        // parallel
        if (len > 0 && eq(cross(dq[len-1].first, hp.first), 0)) {
            // opposite
            if (lt(dot(dq[len-1].first, hp.first), 0)) {
                return {};
            }
            // same
            if (!contains(hp, dq[len-1].second)) {
                dq.pop_back();
                --len;
            } else continue;
        }

        dq.push_back(hp);
        ++len;
    }

    while (len > 2 && !contains(dq[0], intersection(dq[len-1], dq[len-2]))) {
        dq.pop_back();
        --len;
    }

    while (len > 2 && !contains(dq[len-1], intersection(dq[0], dq[1]))) {
        dq.pop_front();
        --len;
    }

    if (len < 3) return {};

    std::vector<Vec> poly(len);
    for (int i = 0; i < len - 1; ++i) {
        poly[i] = intersection(dq[i], dq[i+1]);
    }
    poly[len-1] = intersection(dq[len-1], dq[0]);
    return poly;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;
        vector<Vec> pts(n);
        for (auto& p : pts) cin >> p;

        double lb = 0, ub = 1e9;
        rep(_,0,100) {
            double m = (lb + ub) / 2;
            vector<pair<Vec, Vec>> hps;
            rep(i,0,n) {
                auto d = pts[(i+1)%n] - pts[i];
                auto e = Vec(-d.imag(), d.real());
                auto q = pts[i] + e/abs(e)*m;
                hps.push_back({e, q});
            }
            if (halfplane_intersection(hps).empty()) {
                ub = m;
            } else {
                lb = m;
            }
        }
        cout << lb << "\n";
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3888
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) {
        os << v[i];
        if (i < (int) v.size() - 1) os << " ";
    }
    return os;
}

template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}



using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-8;
inline bool eq(T a, T b) { return std::abs(a - b) <= eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) <= eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a <= b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec perp(const Vec& a) {
    return Vec(-a.imag(), a.real());
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// -1: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

std::vector<Vec> halfplane_intersection(std::vector<std::pair<Vec, Vec>> hps) {
    using Hp = std::pair<Vec, Vec>;  // (normal vector, a point on the border)

    auto intersection = [&](const Hp& l1, const Hp& l2) -> Vec {
        T a1 = l1.first.real(), b1 = l1.first.imag(), c1 = -dot(l1.first, l1.second);
        T a2 = l2.first.real(), b2 = l2.first.imag(), c2 = -dot(l2.first, l2.second);
        return {-(c1*b2-b1*c2)/(a1*b2-a2*b1), -(c1*a2-a1*c2)/(b1*a2-b2*a1)};
    };

    // check if the halfplane h contains the point p
    auto contains = [&](const Hp& h, const Vec& p) -> bool {
        return dot(p - h.second, h.first) > 0;
    };

    constexpr T INF = 1e15;
    hps.emplace_back(Vec(1, 0), Vec(-INF, 0));  // -INF <= x
    hps.emplace_back(Vec(-1, 0), Vec(INF, 0));  // x <= INF
    hps.emplace_back(Vec(0, 1), Vec(0, -INF));  // -INF <= y
    hps.emplace_back(Vec(0, -1), Vec(0, INF));  // y <= INF

    std::sort(hps.begin(), hps.end(), [&](const auto& h1, const auto& h2) {
        return std::arg(h1.first) < std::arg(h2.first);
    });

    std::deque<Hp> dq;
    int len = 0;
    for (auto& hp : hps) {
        while (len > 1 && !contains(hp, intersection(dq[len-1], dq[len-2]))) {
            dq.pop_back();
            --len;
        }

        while (len > 1 && !contains(hp, intersection(dq[0], dq[1]))) {
            dq.pop_front();
            --len;
        }

        // parallel
        if (len > 0 && eq(cross(dq[len-1].first, hp.first), 0)) {
            // opposite
            if (lt(dot(dq[len-1].first, hp.first), 0)) {
                return {};
            }
            // same
            if (!contains(hp, dq[len-1].second)) {
                dq.pop_back();
                --len;
            } else continue;
        }

        dq.push_back(hp);
        ++len;
    }

    while (len > 2 && !contains(dq[0], intersection(dq[len-1], dq[len-2]))) {
        dq.pop_back();
        --len;
    }

    while (len > 2 && !contains(dq[len-1], intersection(dq[0], dq[1]))) {
        dq.pop_front();
        --len;
    }

    if (len < 3) return {};

    std::vector<Vec> poly(len);
    for (int i = 0; i < len - 1; ++i) {
        poly[i] = intersection(dq[i], dq[i+1]);
    }
    poly[len-1] = intersection(dq[len-1], dq[0]);
    return poly;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;
        vector<Vec> pts(n);
        for (auto& p : pts) cin >> p;

        double lb = 0, ub = 1e9;
        rep(_,0,100) {
            double m = (lb + ub) / 2;
            vector<pair<Vec, Vec>> hps;
            rep(i,0,n) {
                auto d = pts[(i+1)%n] - pts[i];
                auto e = Vec(-d.imag(), d.real());
                auto q = pts[i] + e/abs(e)*m;
                hps.push_back({e, q});
            }
            if (halfplane_intersection(hps).empty()) {
                ub = m;
            } else {
                lb = m;
            }
        }
        cout << lb << "\n";
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3884
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int) v.size(); ++i) {
        os << v[i];
        if (i < (int) v.size() - 1) os << " ";
    }
    return os;
}

template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}



using T = double;
using Vec = std::complex<T>;

const T PI = std::acos(-1);

constexpr T eps = 1e-8;
inline bool eq(T a, T b) { return std::abs(a - b) <= eps; }
inline bool eq(Vec a, Vec b) { return std::abs(a - b) <= eps; }
inline bool lt(T a, T b) { return a < b - eps; }
inline bool leq(T a, T b) { return a <= b + eps; }

std::istream& operator>>(std::istream& is, Vec& p) {
    T x, y;
    is >> x >> y;
    p = {x, y};
    return is;
}

struct Line {
    Vec p1, p2;
    Line() = default;
    Line(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Segment {
    Vec p1, p2;
    Segment() = default;
    Segment(const Vec& p1, const Vec& p2) : p1(p1), p2(p2) {}
    Vec dir() const { return p2 - p1; }
};

struct Circle {
    Vec c;
    T r;
    Circle() = default;
    Circle(const Vec& c, T r) : c(c), r(r) {}
};

using Polygon = std::vector<Vec>;

T dot(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).real();
}

T cross(const Vec& a, const Vec& b) {
    return (std::conj(a) * b).imag();
}

Vec rot(const Vec& a, T ang) {
    return a * Vec(std::cos(ang), std::sin(ang));
}

Vec perp(const Vec& a) {
    return Vec(-a.imag(), a.real());
}

Vec projection(const Line& l, const Vec& p) {
    return l.p1 + dot(p - l.p1, l.dir()) * l.dir() / std::norm(l.dir());
}

Vec reflection(const Line& l, const Vec& p) {
    return T(2) * projection(l, p) - p;
}

// 0: collinear
// 1: counter-clockwise
// -1: clockwise
int ccw(const Vec& a, const Vec& b, const Vec& c) {
    if (eq(cross(b - a, c - a), 0)) return 0;
    if (lt(cross(b - a, c - a), 0)) return -1;
    return 1;
}

void sort_by_arg(std::vector<Vec>& pts) {
    std::sort(pts.begin(), pts.end(), [&](auto& p, auto& q) {
        if ((p.imag() < 0) != (q.imag() < 0)) return (p.imag() < 0);
        if (cross(p, q) == 0) {
            if (p == Vec(0, 0)) return !(q.imag() < 0 || (q.imag() == 0 && q.real() > 0));
            if (q == Vec(0, 0)) return  (p.imag() < 0 || (p.imag() == 0 && p.real() > 0));
            return (p.real() > q.real());
        }
        return (cross(p, q) > 0);
    });
}

std::vector<std::pair<double, double>> halfplane_intersection(std::vector<std::tuple<double, double, double>> hps) {
    using Line = std::tuple<double, double, double>;
    using Point = std::pair<double, double>;

    constexpr double INF = 1e9;
    hps.emplace_back(-1, 0, INF);  // x <= INF
    hps.emplace_back(1, 0, INF);   // x >= -INF
    hps.emplace_back(0, -1, INF);  // y <= INF
    hps.emplace_back(0, 1, INF);   // y >= -INF

    std::sort(hps.begin(), hps.end(), [&](const auto& l1, const auto& l2) {
        auto [a1, b1, _c1] = l1;
        auto [a2, b2, _c2] = l2;
        return std::atan2(b1, a1) < std::atan2(b2, a2);
    });

    auto intersection = [&](const Line& l1, const Line& l2) -> Point {
        auto [a1, b1, c1] = l1;
        auto [a2, b2, c2] = l2;
        return {-(c1*b2-b1*c2)/(a1*b2-a2*b1), -(c1*a2-a1*c2)/(b1*a2-b2*a1)};
    };

    // check if the halfplane h contains the point p
    auto contains = [&](const Line& h, const Point& p) -> bool {
        auto [x, y] = p;
        auto [a, b, c] = h;
        return a*x+b*y+c > 0;
    };

    auto dot = [&](const Line& l1, const Line& l2) -> double {
        auto [a1, b1, _c1] = l1;
        auto [a2, b2, _c2] = l2;
        return a1*a2 + b1*b2;
    };

    auto cross = [&](const Line& l1, const Line& l2) -> double {
        auto [a1, b1, _c1] = l1;
        auto [a2, b2, _c2] = l2;
        return a1*b2 - a2*b1;
    };

    auto get_point = [&](const Line& line) -> Point {
        auto [a, b, c] = line;
        if (eq(b, 0)) return {-c/a, 0};
        return {0, -c/b};
    };

    std::deque<Line> dq;
    int len = 0;
    for (auto& hp : hps) {
        auto [a, b, c] = hp;
        while (len > 1 && !contains(hp, intersection(dq[len-1], dq[len-2]))) {
            dq.pop_back();
            --len;
        }

        while (len > 1 && !contains(hp, intersection(dq[0], dq[1]))) {
            dq.pop_front();
            --len;
        }

        // parallel
        if (len > 0 && eq(cross(dq[len-1], hp), 0)) {
            // opposite
            if (lt(dot(dq[len-1], hp), 0)) {
                return {};
            }
            // same
            if (!contains(hp, get_point(dq[len-1]))) {
                dq.pop_back();
                --len;
            } else continue;
        }

        dq.push_back(hp);
        ++len;
    }

    while (len > 2 && !contains(dq[0], intersection(dq[len-1], dq[len-2]))) {
        dq.pop_back();
        --len;
    }

    while (len > 2 && !contains(dq[len-1], intersection(dq[0], dq[1]))) {
        dq.pop_front();
        --len;
    }

    if (len < 3) return {};

    std::vector<Point> poly(len);
    for (int i = 0; i < len - 1; ++i) {
        poly[i] = intersection(dq[i], dq[i+1]);
    }
    poly[len-1] = intersection(dq[len-1], dq[0]);
    return poly;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;
        vector<Vec> pts(n);
        for (auto& p : pts) cin >> p;

        double lb = 0, ub = 1e9;
        rep(_,0,100) {
        // rep(_,0,1) {
            double m = (lb + ub) / 2;
            // double m = 1e9;
            vector<tuple<double, double, double>> hps;
            rep(i,0,n) {
                auto d = pts[(i+1)%n] - pts[i];
                auto e = Vec(-d.imag(), d.real());
                auto q = pts[i] + e/abs(e)*m;
                double c = -dot(e, q);
                hps.push_back({e.real(), e.imag(), c});
            }
            if (halfplane_intersection(hps).empty()) {
                ub = m;
            } else {
                lb = m;
            }
        }
        cout << lb << "\n";
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3920
final_rank: 15

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
// #include <atcoder/convolution>
// using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 1020000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

namespace geometry {
    // Point : 複素数型を位置ベクトルとして扱う
    // 実軸(real)をx軸、挙軸(imag)をy軸として見る
    using D = long double;
    using Point = complex<D>;
    const D EPS = 1e-7;
    const D PI = acosl(-1);

    inline bool equal(const D &a, const D &b) { return fabs(a - b) < EPS; }

    // 単位ベクトル(unit vector)を求める
    Point unitVector(const Point &a) { return a / abs(a); }

    // 法線ベクトル(normal vector)を求める
    // 90度回転した単位ベクトルをかける
    // -90度がよければPoint(0, -1)をかける
    Point normalVector(const Point &a) { return a * Point(0, 1); }

    // 内積(dot product) : a・b = |a||b|cosΘ
    D dot(const Point &a, const Point &b) {
        return (a.real() * b.real() + a.imag() * b.imag());
    }

    // 外積(cross product) : a×b = |a||b|sinΘ
    D cross(const Point &a, const Point &b) {
        return (a.real() * b.imag() - a.imag() * b.real());
    }

    // 点pを反時計回りにtheta度回転
    // thetaはラジアン！！！
    Point rotate(const Point &p, const D &theta) {
        return Point(cos(theta) * p.real() - sin(theta) * p.imag(),
                     sin(theta) * p.real() + cos(theta) * p.imag());
    }

    // ラジアン->度
    D radianToDegree(const D &radian) { return radian * 180.0 / PI; }

    // 度->ラジアン
    D degreeToRadian(const D &degree) { return degree * PI / 180.0; }

    // 点の回転方向
    // 点a, b, cの位置関係について(aが基準点)
    int ccw(const Point &a, Point b, Point c) {
        b -= a, c -= a;
        // 点a, b, c が
        // 反時計回りの時、
        if(cross(b, c) > EPS) return 1;
        // 時計回りの時、
        if(cross(b, c) < -EPS) return -1;
        // c, a, bがこの順番で同一直線上にある時、
        if(dot(b, c) < 0) return 2;
        // a, b, cがこの順番で同一直線上にある場合、
        if(norm(b) < norm(c)) return -2;
        // cが線分ab上にある場合、
        return 0;
    }

    // Line : 直線を表す構造体
    // b - a で直線・線分を表せる
    struct Line {
        Point a, b;
        Line() = default;
        Line(Point a, Point b) : a(a), b(b) {}
        // Ax+By=C
        Line(D A, D B, D C) {
            if(equal(A, 0)) {
                a = Point(0, C / B), b = Point(1, C / B);
            } else if(equal(B, 0)) {
                b = Point(C / A, 0), b = Point(C / A, 1);
            } else {
                a = Point(0, C / B), b = Point(C / A, 0);
            }
        }
    };

    // Segment : 線分を表す構造体
    // Lineと同じ
    struct Segment : Line {
        Segment() = default;

        Segment(Point a, Point b) : Line(a, b) {}
    };

    // Circle : 円を表す構造体
    // pが中心の位置ベクトル、rは半径
    struct Circle {
        Point p;
        D r;

        Circle() = default;

        Circle(Point p, D r) : p(p), r(r) {}
    };

    // 2直線の直交判定 : a⊥b <=> dot(a, b) = 0
    bool isOrthogonal(const Line &a, const Line &b) {
        return equal(dot(a.b - a.a, b.b - b.a), 0);
    }
    // 2直線の平行判定 : a//b <=> cross(a, b) = 0
    bool isParallel(const Line &a, const Line &b) {
        return equal(cross(a.b - a.a, b.b - b.a), 0);
    }

    // 点cが直線ab上にあるか
    bool isPointOnLine(const Point &a, const Point &b, const Point &c) {
        return isParallel(Line(a, b), Line(a, c));
    }

    // 点cが"線分"ab上にあるか
    bool isPointOnSegment(const Point &a, const Point &b, const Point &c) {
        // |a-c| + |c-b| <= |a-b| なら線分上
        return (abs(a - c) + abs(c - b) < abs(a - b) + EPS);
    }

    // 直線lと点pの距離を求める
    D distanceBetweenLineAndPoint(const Line &l, const Point &p) {
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 線分lと点pの距離を求める
    // 定義：点pから「線分lのどこか」への最短距離
    D distanceBetweenSegmentAndPoint(const Segment &l, const Point &p) {
        if(dot(l.b - l.a, p - l.a) < EPS) return abs(p - l.a);
        if(dot(l.a - l.b, p - l.b) < EPS) return abs(p - l.b);
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }

    // 直線s, tの交点の計算
    Point crossPoint(const Line &s, const Line &t) {
        D d1 = cross(s.b - s.a, t.b - t.a);
        D d2 = cross(s.b - s.a, s.b - t.a);
        if(equal(abs(d1), 0) && equal(abs(d2), 0)) return t.a;
        return t.a + (t.b - t.a) * (d2 / d1);
    }

    // 線分s, tの交点の計算
    Point crossPoint(const Segment &s, const Segment &t) {
        return crossPoint(Line(s), Line(t));
    }

    // 線分sと線分tが交差しているかどうか
    // bound:線分の端点を含むか
    bool isIntersect(const Segment &s, const Segment &t, bool bound) {
        return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) < bound &&
               ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) < bound;
    }

    // 線分sとtの距離
    D distanceBetweenSegments(const Segment &s, const Segment &t) {
        if(isIntersect(s, t, 1)) return (D)(0);
        D ans = distanceBetweenSegmentAndPoint(s, t.a);
        chmin(ans, distanceBetweenSegmentAndPoint(s, t.b));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.a));
        chmin(ans, distanceBetweenSegmentAndPoint(t, s.b));
        return ans;
    }

    // 射影(projection)
    // 直線(線分)lに点pから引いた垂線の足を求める
    Point projection(const Line &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    Point projection(const Segment &l, const Point &p) {
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    // 反射(reflection)
    // 直線lを対称軸として点pと線対称の位置にある点を求める
    Point reflection(const Line &l, const Point &p) {
        return p + (projection(l, p) - p) * (D)2.0;
    }

    // 2つの円の交差判定
    // 返り値は共通接線の数
    int isIntersect(const Circle &c1, const Circle &c2) {
        D d = abs(c1.p - c2.p);
        // 2つの円が離れている場合
        if(d > c1.r + c2.r + EPS) return 4;
        // 外接している場合
        if(equal(d, c1.r + c2.r)) return 3;
        // 内接している場合
        if(equal(d, abs(c1.r - c2.r))) return 1;
        // 内包している場合
        if(d < abs(c1.r - c2.r) - EPS) return 0;
        return 2;
    }

    // 2つの円の交点
    vector<Point> crossPoint(const Circle &c1, const Circle &c2) {
        vector<Point> res;
        int mode = isIntersect(c1, c2);
        // 2つの中心の距離
        D d = abs(c1.p - c2.p);
        // 2円が離れている場合
        if(mode == 4) return res;
        // 1つの円がもう1つの円に内包されている場合
        if(mode == 0) return res;
        // 2円が外接する場合
        if(mode == 3) {
            D t = c1.r / (c1.r + c2.r);
            res.emplace_back(c1.p + (c2.p - c1.p) * t);
            return res;
        }
        // 内接している場合
        if(mode == 1) {
            if(c2.r < c1.r - EPS) {
                res.emplace_back(c1.p + (c2.p - c1.p) * (c1.r / d));
            } else {
                res.emplace_back(c2.p + (c1.p - c2.p) * (c2.r / d));
            }
            return res;
        }
        // 2円が重なる場合
        D rc1 = (c1.r * c1.r + d * d - c2.r * c2.r) / (2 * d);
        D rs1 = sqrt(c1.r * c1.r - rc1 * rc1);
        if(c1.r - abs(rc1) < EPS) rs1 = 0;
        Point e12 = (c2.p - c1.p) / abs(c2.p - c1.p);
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, 1));
        res.emplace_back(c1.p + rc1 * e12 + rs1 * e12 * Point(0, -1));
        return res;
    }

    // 点pが円cの内部(円周上も含む)に入っているかどうか
    bool isInCircle(const Circle &c, const Point &p) {
        D d = abs(c.p - p);
        return (equal(d, c.r) || d < c.r - EPS);
    }

    // 円cと直線lの交点
    vector<Point> crossPoint(const Circle &c, const Line &l) {
        vector<Point> res;
        D d = distanceBetweenLineAndPoint(l, c.p);
        // 交点を持たない
        if(d > c.r + EPS) return res;
        // 接する
        Point h = projection(l, c.p);
        if(equal(d, c.r)) {
            res.emplace_back(h);
            return res;
        }
        Point e = unitVector(l.b - l.a);
        D ph = sqrt(c.r * c.r - d * d);
        res.emplace_back(h - e * ph);
        res.emplace_back(h + e * ph);
        return res;
    }

    // 点pを通る円cの接線
    // 2本あるので、接点のみを返す
    vector<Point> tangentToCircle(const Point &p, const Circle &c) {
        return crossPoint(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
    }

    // 円の共通接線
    vector<Line> tangent(const Circle &a, const Circle &b) {
        vector<Line> ret;
        // 2円の中心間の距離
        D g = abs(a.p - b.p);
        // 円が内包されている場合
        if(equal(g, 0)) return ret;
        Point u = unitVector(b.p - a.p);
        Point v = rotate(u, PI / 2);
        for(int s : {-1, 1}) {
            D h = (a.r + b.r * s) / g;
            if(equal(h * h, 1)) {
                ret.emplace_back(a.p + (h > 0 ? u : -u) * a.r,
                                 a.p + (h > 0 ? u : -u) * a.r + v);

            } else if(1 - h * h > 0) {
                Point U = u * h, V = v * sqrt(1 - h * h);
                ret.emplace_back(a.p + (U + V) * a.r,
                                 b.p - (U + V) * (b.r * s));
                ret.emplace_back(a.p + (U - V) * a.r,
                                 b.p - (U - V) * (b.r * s));
            }
        }
        return ret;
    }

    // 多角形の面積を求める
    D PolygonArea(const vector<Point> &p) {
        D res = 0;
        int n = p.size();
        for(int i = 0; i < n - 1; i++) res += cross(p[i], p[i + 1]);
        res += cross(p[n - 1], p[0]);
        return res * 0.5;
    }

    // 凸多角形かどうか
    bool isConvex(const vector<Point> &p) {
        int n = p.size();
        int now, pre, nxt;
        for(int i = 0; i < n; i++) {
            pre = (i - 1 + n) % n;
            nxt = (i + 1) % n;
            now = i;
            if(ccw(p[pre], p[now], p[nxt]) == -1) return false;
        }
        return true;
    }

    // 凸包 O(NlogN)
    vector<Point> ConvexHull(vector<Point> &p) {
        int n = (int)p.size(), k = 0;
        sort(all(p), [](const Point &a, const Point &b) {
            return (real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b));
        });
        vector<Point> ch(2 * n);
        // 一直線上の3点を含める -> (< -EPS)
        // 含め無い -> (< EPS)
        for(int i = 0; i < n; ch[k++] = p[i++]) { // lower
            while(k >= 2 &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) { // upper
            while(k >= t &&
                  cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < EPS)
                --k;
        }
        ch.resize(k - 1);
        return ch;
    }

    // 多角形gに点pが含まれているか?
    // 含まれる:2, 辺上にある:1, 含まれない:0
    int isContained(const vector<Point> &g, const Point &p) {
        bool in = false;
        int n = (int)g.size();
        for(int i = 0; i < n; i++) {
            Point a = g[i] - p, b = g[(i + 1) % n] - p;
            if(imag(a) > imag(b)) swap(a, b);
            if(imag(a) <= EPS && EPS < imag(b) && cross(a, b) < -EPS) in = !in;
            if(cross(a, b) == 0 && dot(a, b) <= 0) return 1;
        }
        return (in ? 2 : 0);
    }

    vector<Point> convex_cut(const vector<Point> &g, Line l){
        vector<Point> ret;
        for(int i=0; i<g.size(); i++){
            Point now = g[i], nxt = g[(i+1)%g.size()];
            if(ccw(l.a,l.b,now) != -1) ret.push_back(now);
            if(ccw(l.a,l.b,now) * ccw(l.a,l.b,nxt) < 0){
                ret.push_back(crossPoint(Line(now,nxt),l));
            }
        }
        return ret;
    }

    bool equal (const Point &a, const Point &b) {
        return equal(a.real(),b.real()) && equal(a.imag(),b.imag());
    }

    D circlesIntersectArea(Circle &a, Circle &b){
        double d = abs(a.p - b.p);
        if(d >= a.r + b.r - EPS) return 0; //2円が離れている
        auto R = minmax(a.r,b.r);
        if(d <= R.second - R.first + EPS) return R.first*R.first*pi; //円が円を内包する
        D theta1 = acos((d*d + a.r*a.r - b.r*b.r)/(2*a.r*d));
        D theta2 = acos((d*d + b.r*b.r - a.r*a.r)/(2*b.r*d));
        D ret = a.r*a.r*(theta1-cos(theta1)*sin(theta1)) + b.r*b.r*(theta2-cos(theta2)*sin(theta2));
        return ret;
    }
} // namespace geometry

using namespace geometry;


int main(){
	while(1){
        int n; cin >> n;
        if(!n) break;
        vector<Point> g(n);
        rep(i,n){
            int x,y; cin >> x >> y;
            g[i] = Point(x,y);
        }
        D ok = 0, ng = 100000;
        rep(z,60){
            D mid = (ok+ng) / 2;
            auto calcLine = [&](Point a, Point b) -> Line {
                Point diff = b - a;
                Point vec = unitVector(Point(-diff.imag(),diff.real()));
                vec *= mid;
                return Line(a+vec, b+vec);
            };
            vector<Point> G = g;
            rep(i,n){
                Line l = calcLine(g[i],g[(i+1)%n]);
                G = convex_cut(G,l);
            }
            if(G.size() <= 1) ng = mid;
            else ok = mid; 
        }
        printf("%.10Lf\n",ok);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3368
final_rank: 2

code_snippet: #line 2 "library/bits/stdc++.h"

// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
#line 2 "Source.cpp"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#line 2 "library/kotamanegi/geometry.hpp"
#define _USE_MATH_DEFINES
using namespace std;

typedef long double ld;
typedef complex<ld> Point;
typedef pair<Point, Point> Segment;
typedef Segment Line;

const ld EPS = 1e-10;

ld abs(Line x)
{
  return abs(x.second - x.first);
}

// dot = |a||b| cos(theta)
ld dot(Point a, Point b)
{
  return a.real() * b.real() + a.imag() * b.imag();
}

// cross = |a||b| sin(theta)
ld cross(Point a, Point b)
{
  return a.real() * b.imag() - a.imag() * b.real();
}

// 射影: 直線sと点pから引いた垂線の交点
Point projection(Line s, Point p)
{
  Point base = s.second - s.first;
  ld r = dot(p - s.first, base) / norm(base);
  return s.first + base * r;
}

// 反射: 点pを直線sと線対称に移動した点
Point reflection(Line s, Point p)
{
  return p + (projection(s, p) - p) * Point{2.0, 0.0};
}

Line vertical_bisector(Line x)
{
  Point now = (x.first + x.second) * Point{0.5, 0};
  return Line(now, now + (x.second - x.first) * Point{0, M_PI_2});
}

enum class Position
{
  COUNTER_CLOCKWISE, // 反時計回り
  CLOCKWISE,         // 時計回り
  ON_LINE_BACK,      // Lineの始点側に点がある
  ON_LINE_FRONT,     // Lineの終点側に点がある
  ON_SEGMENT         // Line上に点がある
};

// ccw: 線分sと点pの位置関係を示す
Position ccw(Line s, Point p)
{
  Point a = s.second - s.first, b = p - s.first;
  if (cross(a, b) > eps)
    return Position::COUNTER_CLOCKWISE;
  if (cross(a, b) < -eps)
    return Position::CLOCKWISE;
  if (dot(a, b) < -EPS)
    return Position::ON_LINE_BACK;
  if (norm(a) < norm(b))
    return Position::ON_LINE_FRONT;
  return Position::ON_SEGMENT;
}

// 平行判定
bool is_parallel(Point a, Point b) { return abs(cross(a, b)) < EPS; }
bool is_parallel(Line a, Line b) { return is_parallel(a.second - a.first, b.second - b.first); }

// 直交判定
bool is_orthogonal(Point a, Point b) { return abs(dot(a, b)) < EPS; }
bool is_orthogonal(Line a, Line b) { return is_orthogonal(a.second - a.first, b.second - b.first); }

// 交差判定
bool is_intersect_line(Line s1, Segment s2)
{
  if (cross(s1.second - s1.first, s2.first - s1.first) * cross(s1.second - s1.first, s2.second - s1.first) > eps)
  {
    return false;
  }
  if (ccw(s1, s2.first) == Position::ON_LINE_BACK and ccw(s1, s2.second) == Position::ON_LINE_BACK)
  {
    return false;
  }
  if (ccw(s1, s2.first) == Position::ON_LINE_FRONT and ccw(s1, s2.second) == Position::ON_LINE_FRONT)
  {
    return false;
  }
  return true;
}

bool is_intersect(Segment s1, Segment s2)
{
  for (int i = 0; i < 2; ++i)
  {
    if (!is_intersect_line(s1, s2))
    {
      return false;
    }
    swap(s1, s2);
  }
  return true;
}

// 交差点
Point intersection_point(Line s1, Line s2)
{
  ld s, t;
  ld deno = cross(s1.second - s1.first, s2.second - s2.first) + eps;
  s = cross(s2.first - s1.first, s2.second - s2.first) / deno;
  return s1.first + s * (s1.second - s1.first);
}

//線分と点の距離
ld distance(Segment s, Point p)
{
  if (dot(s.second - s.first, p - s.first) < eps)
    return abs(p - s.first);
  if (dot(s.first - s.second, p - s.second) < eps)
    return abs(p - s.second);
  return abs(cross(s.second - s.first, p - s.first)) / abs(s);
}

//線分と線分の距離
ld distance(Segment s1, Segment s2)
{
  if (is_intersect(s1, s2))
  {
    return 0;
  }
  return min({distance(s1, s2.first), distance(s1, s2.second), distance(s2, s1.first), distance(s2, s1.second)});
}

typedef vector<Point> Polygon;

//多角形の面積
ld area(Polygon poly)
{
  ld ans = 0;
  for (int i = 0; i < poly.size(); ++i)
  {
    Point a = poly[i], b = poly[(i + 1) % poly.size()];
    ans += cross(a, b);
  }
  ans /= 2.0L;
  return abs(ans);
}

//凸多角形か判定
bool is_convex(Polygon poly)
{
  for (int i = 0; i < poly.size(); ++i)
  {
    Line a = {poly[i], poly[(i + 1) % poly.size()]};
    if (ccw(a, poly[(i + 2) % poly.size()]) == Position::CLOCKWISE)
      return false;
  }
  return true;
}

//多角形上に点があるか判定
bool is_on_polygon(Polygon poly, Point p)
{
  for (int i = 0; i < poly.size(); ++i)
  {
    Line a = {poly[i], poly[(i + 1) % poly.size()]};
    if (ccw(a, p) == Position::ON_SEGMENT)
      return true;
  }
  return false;
}

//多角形内に点があるか判定
bool is_inside_polygon(Polygon poly, Point p)
{
  if (is_on_polygon(poly, p))
    return true;
  const int n = poly.size();
  int wn = 0;
  for (int i = 0; i < n; ++i)
  {
    ld vt = (p.imag() - poly[i].imag()) / (poly[(i + 1) % n].imag() - poly[i].imag());
    if (p.real() < (poly[i].real() + vt * (poly[(i + 1) % n].real() - poly[i].real())))
    {
      if ((poly[i].imag() <= p.imag()) and (poly[(i + 1) % n].imag() > p.imag()))
      {
        wn++;
      }
      else if ((poly[i].imag() > p.imag()) and (poly[(i + 1) % n].imag() <= p.imag()))
      {
        wn--;
      }
    }
  }
  if (wn != 0)
    return true;
  return false;
}

// 凸包
Polygon convex_hull(Polygon poly)
{
  sort(ALL(poly), [](auto &l, auto &r)
       {
    if(l.real() != r.real()) return l.real() < r.real();
    return l.imag() < r.imag(); });
  Polygon ans;
  ans.push_back(poly[0]);
  ans.push_back(poly[1]);
  for (int i = 2; i < poly.size(); ++i)
  {
    while (ans.size() >= 2)
    {
      Point x = ans[ans.size() - 2];
      Point y = ans[ans.size() - 1];
      if (ccw({x, y}, poly[i]) == Position::COUNTER_CLOCKWISE)
      {
        ans.pop_back();
      }
      else
        break;
    }
    ans.push_back(poly[i]);
  }

  Polygon reversed_ans;
  reversed_ans.push_back(poly[0]);
  reversed_ans.push_back(poly[1]);
  for (int i = 2; i < poly.size(); ++i)
  {
    while (reversed_ans.size() >= 2)
    {
      Point x = reversed_ans[reversed_ans.size() - 2];
      Point y = reversed_ans[reversed_ans.size() - 1];
      if (ccw({x, y}, poly[i]) == Position::CLOCKWISE)
      {
        reversed_ans.pop_back();
      }
      else
        break;
    }
    reversed_ans.push_back(poly[i]);
  }
  for (int q = reversed_ans.size() - 2; q >= 1; --q)
  {
    ans.push_back(reversed_ans[q]);
  }
  return ans;
}

// 凸多角形の直径
ld diameter(Polygon poly)
{
  ld ans = 0;
  int itr = 0;
  REP(i, poly.size())
  {
    if (abs(poly[i] - poly[0]) > abs(poly[itr] - poly[0]))
    {
      itr = i;
    }
  }
  REP(i, poly.size())
  {
    while (abs(poly[(itr + 1) % poly.size()] - poly[i]) > abs(poly[itr] - poly[i]))
    {
      itr++;
      itr %= poly.size();
    }
    ans = max(ans, abs(poly[itr] - poly[i]));
  }
  return ans;
}

// 凸多角形の切断
Polygon convex_cut(Polygon poly, Line l)
{
  Polygon ans;
  for (int i = 0; i < poly.size(); ++i)
  {
    Point now = poly[i];
    Point nxt = poly[(i + 1) % poly.size()];
    if (ccw(l, now) != Position::CLOCKWISE)
    {
      ans.push_back(now);
    }
    if (is_intersect_line(l, {now, nxt}))
    {
      ans.push_back(intersection_point(l, {now, nxt}));
    }
  }
  return ans;
}
#line 17 "Source.cpp"

#define int long long

bool judge(ld dist,Polygon poly){
  Polygon cur = poly;
  for (int i = 0;i < poly.size();++i){
    Line now = {poly[i], poly[(i + 1) % poly.size()]};
    Line moves = vertical_bisector(now);
    Point Move = moves.second - moves.first;
    Move /= abs(Move);
    now.first += Move * dist;
    now.second += Move * dist;
    cur = convex_cut(cur, now);
  }
  if (cur.size() >= 2)
    return true;
  return false;
}

void solve()
{
  int n;
  cin >> n;
  if(n == 0)
    exit(0);
  Polygon poly;
  REP(i,n){
    ld a,b;
    cin >> a >> b;
    poly.push_back({a, b});
  }

  ld bot = 0;
  ld top = 1e9;
  REP(t,100){
    ld mid = (bot + top) / 2.0;
    if(judge(mid,poly)){
      bot = mid;
    }else{
      top = mid;
    }
  }
  cout << bot << endl;
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 10000;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3604
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

// base
namespace geometry {
  using namespace std;
  using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

istream &operator>>(istream &is, geometry::point &p) {
  geometry::real_number x, y;
  is >> x >> y;
  p = geometry::point(x, y);
  return is;
}

ostream &operator<<(ostream &os, const geometry::point &p) {
  return os << p.real() << " " << p.imag();
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// line
namespace geometry {
  struct line {
    point a, b;

    line() = default;
    line(point a, point b) : a(a), b(b) {}
  };

  using lines = vector< line >;
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; i++) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

// convex cut
namespace geometry {
  polygon convex_cut(const polygon &poly, const line &l) {
    polygon res;
    int n = poly.size();
    for (int i = 0; i < n; i++) {
      int j = (i + 1 == n ? 0 : i + 1);

      real_number cf = cross(l.a - poly[i], l.b - poly[i]);
      real_number cs = cross(l.a - poly[j], l.b - poly[j]);

      if (sign(cf) >= 0) res.emplace_back(poly[i]);
      if (sign(cf) * sign(cs) < 0) {
        real_number s = cross(poly[j] - poly[i], l.a - l.b);
        real_number t = cross(l.a - poly[i], l.a - l.b);
        res.emplace_back(poly[i] + t / s * (poly[j] - poly[i]));
      }
    }

    return res;
  }
}

void solve(int n) {
  geometry::polygon poly(n);
  for (auto &pts : poly) cin >> pts;

  auto check = [&](geometry::real_number d) {
    geometry::polygon cut = poly;
    
    for (int i = 0; i < n; i++) {
      using geometry::point;
      point vec = poly[(i+1) % n] - poly[i];
      point orth = geometry::rotate(geometry::PI / 2, vec);
      point dv = orth / abs(orth) * d;

      geometry::line l(poly[i] + dv ,poly[(i+1) % n] + dv);
      cut = convex_cut(cut, l);
    }

    return not(geometry::equals(geometry::area(cut), 0));
  };

  geometry::real_number ok = 0, ng = 10000;
  for (int qi = 0; qi < 300; qi++) {
    geometry::real_number mid = (ok + ng) / 2;

    if (check(mid)) ok = mid;
    else ng = mid;
  }

  cout << fixed << setprecision(7);
  cout << ok << endl;
}

int main() {
  int n;

  while (cin >> n, n) {
    solve(n);
  }
}
accuracy: 1
time_ms: 90
memory_kb: 3768
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

// Geometry Library
// written by okuraofvegetable

#define pb push_back
#define DOUBLE_INF 1e50
#define Points vector<Point>
#define double long double

#define EQ(a, b) (abs((a) - (b)) < eps)
#define GT(a, b) ((a) > (b))
#define GE(a, b) (GT(a, b) || EQ(a, b))
#define LT(a, b) ((a) < (b))
#define LE(a, b) (LT(a, b) || EQ(a, b))

inline double add(double a, double b) {
  if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
  return a + b;
}

// --------------------- Point -----------------------

#define Vector Point
struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) { return Point(add(x, p.x), add(y, p.y)); }
  Point operator-(Point p) { return Point(add(x, -p.x), add(y, -p.y)); }
  Point operator*(double d) { return Point(x * d, y * d); }
  Point operator/(double d) { return Point(x / d, y / d); }
  double dot(Point p) { return add(x * p.x, y * p.y); }
  double det(Point p) { return add(x * p.y, -y * p.x); }
  double norm() { return sqrt(x * x + y * y); }
  double norm2() { return x * x + y * y; }
  double dist(Point p) { return ((*this) - p).norm(); }
  double dist2(Point p) { return sq(x - p.x) + sq(y - p.y); }
  double arg() { return atan2(y, x); }             // [-PI,PI]
  double arg(Vector v) { return v.arg() - arg(); } // henkaku
  double angle(Vector v) {                         // [0,PI]
    return acos(cos(arg(v)));
  }
  Vector normalize() { return (*this) * (1.0 / norm()); }
  Point vert() { return Point(-y, x); }

  // Signed area of triange (0,0) (x,y) (p.x,p.y)
  double area(Point p) { return (x * p.y - p.x * y) / 2.0; }
  friend istream &operator>>(istream &is, Point &p) { return is >> p.x >> p.y; }
  friend ostream &operator<<(ostream &os, const Point &p) {
    return os << fixed << setprecision(10) << '(' << p.x << ',' << p.y << ')';
  }
};

Point divide_rate(Point a, Point b, double A, double B) {
  assert(!EQ(A + B, 0.0));
  return (a * B + b * A) * (1.0 / (A + B));
}

Vector polar(double len, double arg) {
  return Vector(cos(arg) * len, sin(arg) * len);
}

// Direction a -> b -> c
// verified AOJ CGL_1_C
enum { COUNTER_CLOCKWISE, CLOCKWISE, ONLINE_BACK, ONLINE_FRONT, ON_SEGMENT };
int ccw(Point a, Point b, Point c) {
  Vector p = b - a;
  Vector q = c - a;
  if (p.det(q) > 0.0) return COUNTER_CLOCKWISE; // counter clockwise
  if (p.det(q) < 0.0) return CLOCKWISE;         // clockwise
  if (p.dot(q) < 0.0) return ONLINE_BACK;       // c--a--b online_back
  if (p.norm() < q.norm()) return ONLINE_FRONT; // a--b--c online_front
  return ON_SEGMENT;                            // a--c--b on_segment
}

// --------------------- Line ------------------------
struct Line {
  Point a, b;
  Line() {}
  Line(Point a, Point b) : a(a), b(b) {}
  bool on(Point q) { return EQ((a - q).det(b - q), 0.0); }
  // following 2 functions verified AOJ CGL_2_A
  bool is_parallel(Line l) { return EQ((a - b).det(l.a - l.b), 0.0); }
  bool is_orthogonal(Line l) { return EQ((a - b).dot(l.a - l.b), 0.0); }
  Point intersection(Line l) {
    assert(!is_parallel(l));
    return a + (b - a) * ((l.b - l.a).det(l.a - a) / (l.b - l.a).det(b - a));
  }
  // Projection of p to this line
  // verified AOJ CGL_1_A
  Point projection(Point p) {
    return (b - a) * ((b - a).dot(p - a) / (b - a).norm2()) + a;
  }
  double distance(Point p) {
    Point q = projection(p);
    return p.dist(q);
  }
  // Reflection point of p onto this line
  // verified AOJ CGL_1_B
  Point refl(Point p) {
    Point proj = projection(p);
    return p + ((proj - p) * 2.0);
  }
  bool left(Point p) {
    if ((p - a).det(b - a) > 0.0)
      return true;
    else
      return false;
  }
  friend istream &operator>>(istream &is, Line &l) { return is >> l.a >> l.b; }
  friend ostream &operator<<(ostream &os, const Line &l) {
    return os << l.a << " -> " << l.b;
  }
};

// ------------------- Segment  ----------------------
struct Segment {
  Point a, b;
  Segment() {}
  Segment(Point a, Point b) : a(a), b(b) {}
  Line line() { return Line(a, b); }
  bool on(Point q) {
    return (EQ((a - q).det(b - q), 0.0) && LE((a - q).dot(b - q), 0.0));
  }
  // verified AOJ CGL_2_B
  bool is_intersect(Segment s) {
    if (line().is_parallel(s.line())) {
      if (on(s.a) || on(s.b)) return true;
      if (s.on(a) || s.on(b)) return true;
      return false;
    }
    Point p = line().intersection(s.line());
    if (on(p) && s.on(p))
      return true;
    else
      return false;
  }
  bool is_intersect(Line l) {
    if (line().is_parallel(l)) {
      if (l.on(a) || l.on(b))
        return true;
      else
        return false;
    }
    Point p = line().intersection(l);
    if (on(p))
      return true;
    else
      return false;
  }
  // following 2 distance functions are verified at AOJ CGL_2_D
  double distance(Point p) {
    double res = DOUBLE_INF;
    Point q = line().projection(p);
    if (on(q)) res = min(res, p.dist(q));
    res = min(res, min(p.dist(a), p.dist(b)));
    return res;
  }
  double distance(Segment s) {
    if (is_intersect(s)) return 0.0;
    double res = DOUBLE_INF;
    res = min(res, s.distance(a));
    res = min(res, s.distance(b));
    res = min(res, this->distance(s.a));
    res = min(res, this->distance(s.b));
    return res;
  }
  friend istream &operator>>(istream &is, Segment &s) {
    return is >> s.a >> s.b;
  }
  friend ostream &operator<<(ostream &os, const Segment &s) {
    return os << s.a << " -> " << s.b;
  }
};

// ------------------- Polygon -----------------------
// Note: A polygon generally don't need to be convex.

typedef vector<Point> Polygon;
// verified AOJ CGL_3_A
double area(Polygon &pol) {
  Points vec;
  double res = 0.0;
  int M = pol.size();
  for (int i = 0; i < M; i++) {
    res += (pol[i] - pol[0]).area(pol[(i + 1) % M] - pol[0]);
  }
  return res;
}

bool is_convex(Polygon &pol) {
  int n = pol.size();
  for (int i = 0; i < n - 1; i++) {
    if (ccw(pol[i], pol[i + 1], pol[(i + 2) % n]) == CLOCKWISE) {
      return false;
    }
  }
  return true;
}

// vecrified AOJ CGL_3_C
enum { OUT, ON, IN };
int contained(Polygon &pol, Point p) {
  int n = pol.size();
  Point outer(1e9, p.y);
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(pol[i], pol[(i + 1) % n]);
    if (e.on(p)) return ON;
    Vector a = pol[i] - p;
    Vector b = pol[(i + 1) % n] - p;
    if (a.y > b.y) swap(a, b);
    if (LE(a.y, 0.0) && GT(b.y, 0.0)) {
      if (LT(a.det(b), 0.0)) cnt++;
    }
  }
  if ((cnt & 1) == 1)
    return IN;
  else
    return OUT;
}

// Cut conovex polygon by a line and return left polygon
// verified AOJ CGL_4_C
Polygon convex_cut(Polygon &cv, Line l) {
  int n = cv.size();
  Polygon left;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(cv[i], cv[(i + 1) % n]);
    if (ccw(l.a, l.b, cv[i]) != CLOCKWISE) left.pb(cv[i]);
    if (e.is_intersect(l)) {
      if (!e.line().is_parallel(l)) { left.pb(e.line().intersection(l)); }
    }
  }
  return left;
}

bool solve() {
  int N;
  cin >> N;

  if (N == 0) return false;

  vector<Point> ps(N);
  for (int i = 0; i < N; i++) cin >> ps[i];

  auto check = [&](double K) {
    vector<Line> ls;
    for (int i = 0; i < N; i++) {
      Point a = ps[i], b = ps[(i + 1) % N];
      Vector d = (b - a).vert().normalize() * K;
      ls.emplace_back(a + d, b + d);
    }
    vector<Point> cand;
    for (int i = 0; i < ls.size(); i++) {
      for (int j = i + 1; j < ls.size(); j++) {
        if (ls[i].is_parallel(ls[j])) continue;
        cand.push_back(ls[i].intersection(ls[j]));
      }
    }
    dmp(K);
    dmp(ls);
    dmp(cand);
    for (auto c : cand) {
      if (contained(ps, c) == OUT) continue;
      bool valid = true;
      for (int i = 0; i < N; i++) {
        Point a = ps[i], b = ps[(i + 1) % N];
        dmp(Segment(a, b).distance(c), K);
        if (GE(Segment(a, b).distance(c), K)) {
          continue;
        } else {
          valid = false;
          break;
        }
      }
      if (valid) return true;
    }
    return false;
  };

  double l = 0.0, r = 10000.0;
  for (int i = 0; i < 50; i++) {
    double mid = (l + r) / 2.0;
    bool res = check(mid);
    dmp(mid, res);
    if (res)
      l = mid;
    else
      r = mid;
  }

  cout << l << endl;

  return true;
}

int main() {
  fastio();
  if (!multitest) {
    while (solve()) {}
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 1860
memory_kb: 3808
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-7
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

// Geometry Library
// written by okuraofvegetable

#define pb push_back
#define DOUBLE_INF 1e50
#define Points vector<Point>
#define double long double

#define EQ(a, b) (abs((a) - (b)) < eps)
#define GT(a, b) ((a) > (b))
#define GE(a, b) (GT(a, b) || EQ(a, b))
#define LT(a, b) ((a) < (b))
#define LE(a, b) (LT(a, b) || EQ(a, b))

inline double add(double a, double b) {
  if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
  return a + b;
}

// --------------------- Point -----------------------

#define Vector Point
struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) { return Point(add(x, p.x), add(y, p.y)); }
  Point operator-(Point p) { return Point(add(x, -p.x), add(y, -p.y)); }
  Point operator*(double d) { return Point(x * d, y * d); }
  Point operator/(double d) { return Point(x / d, y / d); }
  double dot(Point p) { return add(x * p.x, y * p.y); }
  double det(Point p) { return add(x * p.y, -y * p.x); }
  double norm() { return sqrt(x * x + y * y); }
  double norm2() { return x * x + y * y; }
  double dist(Point p) { return ((*this) - p).norm(); }
  double dist2(Point p) { return sq(x - p.x) + sq(y - p.y); }
  double arg() { return atan2(y, x); }             // [-PI,PI]
  double arg(Vector v) { return v.arg() - arg(); } // henkaku
  double angle(Vector v) {                         // [0,PI]
    return acos(cos(arg(v)));
  }
  Vector normalize() { return (*this) * (1.0 / norm()); }
  Point vert() { return Point(-y, x); }

  // Signed area of triange (0,0) (x,y) (p.x,p.y)
  double area(Point p) { return (x * p.y - p.x * y) / 2.0; }
  friend istream &operator>>(istream &is, Point &p) { return is >> p.x >> p.y; }
  friend ostream &operator<<(ostream &os, const Point &p) {
    return os << fixed << setprecision(10) << '(' << p.x << ',' << p.y << ')';
  }
};

Point divide_rate(Point a, Point b, double A, double B) {
  assert(!EQ(A + B, 0.0));
  return (a * B + b * A) * (1.0 / (A + B));
}

Vector polar(double len, double arg) {
  return Vector(cos(arg) * len, sin(arg) * len);
}

// Direction a -> b -> c
// verified AOJ CGL_1_C
enum { COUNTER_CLOCKWISE, CLOCKWISE, ONLINE_BACK, ONLINE_FRONT, ON_SEGMENT };
int ccw(Point a, Point b, Point c) {
  Vector p = b - a;
  Vector q = c - a;
  if (p.det(q) > 0.0) return COUNTER_CLOCKWISE; // counter clockwise
  if (p.det(q) < 0.0) return CLOCKWISE;         // clockwise
  if (p.dot(q) < 0.0) return ONLINE_BACK;       // c--a--b online_back
  if (p.norm() < q.norm()) return ONLINE_FRONT; // a--b--c online_front
  return ON_SEGMENT;                            // a--c--b on_segment
}

// --------------------- Line ------------------------
struct Line {
  Point a, b;
  Line() {}
  Line(Point a, Point b) : a(a), b(b) {}
  bool on(Point q) { return EQ((a - q).det(b - q), 0.0); }
  // following 2 functions verified AOJ CGL_2_A
  bool is_parallel(Line l) { return EQ((a - b).det(l.a - l.b), 0.0); }
  bool is_orthogonal(Line l) { return EQ((a - b).dot(l.a - l.b), 0.0); }
  Point intersection(Line l) {
    assert(!is_parallel(l));
    return a + (b - a) * ((l.b - l.a).det(l.a - a) / (l.b - l.a).det(b - a));
  }
  // Projection of p to this line
  // verified AOJ CGL_1_A
  Point projection(Point p) {
    return (b - a) * ((b - a).dot(p - a) / (b - a).norm2()) + a;
  }
  double distance(Point p) {
    Point q = projection(p);
    return p.dist(q);
  }
  // Reflection point of p onto this line
  // verified AOJ CGL_1_B
  Point refl(Point p) {
    Point proj = projection(p);
    return p + ((proj - p) * 2.0);
  }
  bool left(Point p) {
    if ((p - a).det(b - a) > 0.0)
      return true;
    else
      return false;
  }
  friend istream &operator>>(istream &is, Line &l) { return is >> l.a >> l.b; }
  friend ostream &operator<<(ostream &os, const Line &l) {
    return os << l.a << " -> " << l.b;
  }
};

// ------------------- Segment  ----------------------
struct Segment {
  Point a, b;
  Segment() {}
  Segment(Point a, Point b) : a(a), b(b) {}
  Line line() { return Line(a, b); }
  bool on(Point q) {
    return (EQ((a - q).det(b - q), 0.0) && LE((a - q).dot(b - q), 0.0));
  }
  // verified AOJ CGL_2_B
  bool is_intersect(Segment s) {
    if (line().is_parallel(s.line())) {
      if (on(s.a) || on(s.b)) return true;
      if (s.on(a) || s.on(b)) return true;
      return false;
    }
    Point p = line().intersection(s.line());
    if (on(p) && s.on(p))
      return true;
    else
      return false;
  }
  bool is_intersect(Line l) {
    if (line().is_parallel(l)) {
      if (l.on(a) || l.on(b))
        return true;
      else
        return false;
    }
    Point p = line().intersection(l);
    if (on(p))
      return true;
    else
      return false;
  }
  // following 2 distance functions are verified at AOJ CGL_2_D
  double distance(Point p) {
    double res = DOUBLE_INF;
    Point q = line().projection(p);
    if (on(q)) res = min(res, p.dist(q));
    res = min(res, min(p.dist(a), p.dist(b)));
    return res;
  }
  double distance(Segment s) {
    if (is_intersect(s)) return 0.0;
    double res = DOUBLE_INF;
    res = min(res, s.distance(a));
    res = min(res, s.distance(b));
    res = min(res, this->distance(s.a));
    res = min(res, this->distance(s.b));
    return res;
  }
  friend istream &operator>>(istream &is, Segment &s) {
    return is >> s.a >> s.b;
  }
  friend ostream &operator<<(ostream &os, const Segment &s) {
    return os << s.a << " -> " << s.b;
  }
};

// ------------------- Polygon -----------------------
// Note: A polygon generally don't need to be convex.

typedef vector<Point> Polygon;
// verified AOJ CGL_3_A
double area(Polygon &pol) {
  Points vec;
  double res = 0.0;
  int M = pol.size();
  for (int i = 0; i < M; i++) {
    res += (pol[i] - pol[0]).area(pol[(i + 1) % M] - pol[0]);
  }
  return res;
}

bool is_convex(Polygon &pol) {
  int n = pol.size();
  for (int i = 0; i < n - 1; i++) {
    if (ccw(pol[i], pol[i + 1], pol[(i + 2) % n]) == CLOCKWISE) {
      return false;
    }
  }
  return true;
}

// vecrified AOJ CGL_3_C
enum { OUT, ON, IN };
int contained(Polygon &pol, Point p) {
  int n = pol.size();
  Point outer(1e9, p.y);
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(pol[i], pol[(i + 1) % n]);
    if (e.on(p)) return ON;
    Vector a = pol[i] - p;
    Vector b = pol[(i + 1) % n] - p;
    if (a.y > b.y) swap(a, b);
    if (LE(a.y, 0.0) && GT(b.y, 0.0)) {
      if (LT(a.det(b), 0.0)) cnt++;
    }
  }
  if ((cnt & 1) == 1)
    return IN;
  else
    return OUT;
}

// Cut conovex polygon by a line and return left polygon
// verified AOJ CGL_4_C
Polygon convex_cut(Polygon &cv, Line l) {
  int n = cv.size();
  Polygon left;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(cv[i], cv[(i + 1) % n]);
    if (ccw(l.a, l.b, cv[i]) != CLOCKWISE) left.pb(cv[i]);
    if (e.is_intersect(l)) {
      if (!e.line().is_parallel(l)) { left.pb(e.line().intersection(l)); }
    }
  }
  return left;
}

bool solve() {
  int N;
  cin >> N;

  if (N == 0) return false;

  vector<Point> ps(N);
  for (int i = 0; i < N; i++) cin >> ps[i];

  auto check = [&](double K) {
    vector<Line> ls;
    for (int i = 0; i < N; i++) {
      Point a = ps[i], b = ps[(i + 1) % N];
      Vector d = (b - a).vert().normalize() * K;
      ls.emplace_back(a + d, b + d);
    }
    vector<Point> cand;
    for (int i = 0; i < ls.size(); i++) {
      for (int j = i + 1; j < ls.size(); j++) {
        if (ls[i].is_parallel(ls[j])) continue;
        cand.push_back(ls[i].intersection(ls[j]));
      }
    }
    dmp(K);
    dmp(ls);
    dmp(cand);
    for (auto c : cand) {
      if (contained(ps, c) == OUT) continue;
      bool valid = true;
      for (int i = 0; i < N; i++) {
        Point a = ps[i], b = ps[(i + 1) % N];
        dmp(Segment(a, b).distance(c), K);
        if (Segment(a, b).distance(c) < K - eps) {
          valid = false;
          break;
        }
      }
      if (valid) return true;
    }
    return false;
  };

  double l = 0.0, r = 10000.0;
  for (int i = 0; i < 50; i++) {
    double mid = (l + r) / 2.0;
    bool res = check(mid);
    dmp(mid, res);
    if (res)
      l = mid;
    else
      r = mid;
  }

  cout << l << endl;

  return true;
}

int main() {
  fastio();
  if (!multitest) {
    while (solve()) {}
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 1560
memory_kb: 3764
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}

template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;

template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------------ ACL --------------------

// #include <atcoder/modint>
// constexpr int MOD = 998244353;
// constexpr int MOD = 1000000007;
// using mint = atcoder::static_modint<MOD>;
// ostream &operator<<(ostream &os, const mint &v) {
//   return os << v.val();
// }

// ------------ End of template --------------

#define endl "\n"
using ll = long long;
using pii = pair<int, int>;

const bool multitest = false;

// Geometry Library
// written by okuraofvegetable

#define pb push_back
#define DOUBLE_INF 1e50
#define Points vector<Point>
// #define double long double

#define EQ(a, b) (abs((a) - (b)) < eps)
#define GT(a, b) ((a) > (b))
#define GE(a, b) (GT(a, b) || EQ(a, b))
#define LT(a, b) ((a) < (b))
#define LE(a, b) (LT(a, b) || EQ(a, b))

inline double add(double a, double b) {
  if (abs(a + b) < eps * (abs(a) + abs(b))) return 0;
  return a + b;
}

// --------------------- Point -----------------------

#define Vector Point
struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) { return Point(add(x, p.x), add(y, p.y)); }
  Point operator-(Point p) { return Point(add(x, -p.x), add(y, -p.y)); }
  Point operator*(double d) { return Point(x * d, y * d); }
  Point operator/(double d) { return Point(x / d, y / d); }
  double dot(Point p) { return add(x * p.x, y * p.y); }
  double det(Point p) { return add(x * p.y, -y * p.x); }
  double norm() { return sqrt(x * x + y * y); }
  double norm2() { return x * x + y * y; }
  double dist(Point p) { return ((*this) - p).norm(); }
  double dist2(Point p) { return sq(x - p.x) + sq(y - p.y); }
  double arg() { return atan2(y, x); }             // [-PI,PI]
  double arg(Vector v) { return v.arg() - arg(); } // henkaku
  double angle(Vector v) {                         // [0,PI]
    return acos(cos(arg(v)));
  }
  Vector normalize() { return (*this) * (1.0 / norm()); }
  Point vert() { return Point(-y, x); }

  // Signed area of triange (0,0) (x,y) (p.x,p.y)
  double area(Point p) { return (x * p.y - p.x * y) / 2.0; }
  friend istream &operator>>(istream &is, Point &p) { return is >> p.x >> p.y; }
  friend ostream &operator<<(ostream &os, const Point &p) {
    return os << '(' << p.x << ',' << p.y << ')';
  }
};

Point divide_rate(Point a, Point b, double A, double B) {
  assert(!EQ(A + B, 0.0));
  return (a * B + b * A) * (1.0 / (A + B));
}

Vector polar(double len, double arg) {
  return Vector(cos(arg) * len, sin(arg) * len);
}

// Direction a -> b -> c
// verified AOJ CGL_1_C
enum { COUNTER_CLOCKWISE, CLOCKWISE, ONLINE_BACK, ONLINE_FRONT, ON_SEGMENT };
int ccw(Point a, Point b, Point c) {
  Vector p = b - a;
  Vector q = c - a;
  if (p.det(q) > 0.0) return COUNTER_CLOCKWISE; // counter clockwise
  if (p.det(q) < 0.0) return CLOCKWISE;         // clockwise
  if (p.dot(q) < 0.0) return ONLINE_BACK;       // c--a--b online_back
  if (p.norm() < q.norm()) return ONLINE_FRONT; // a--b--c online_front
  return ON_SEGMENT;                            // a--c--b on_segment
}

// --------------------- Line ------------------------
struct Line {
  Point a, b;
  Line() {}
  Line(Point a, Point b) : a(a), b(b) {}
  bool on(Point q) { return EQ((a - q).det(b - q), 0.0); }
  // following 2 functions verified AOJ CGL_2_A
  bool is_parallel(Line l) { return EQ((a - b).det(l.a - l.b), 0.0); }
  bool is_orthogonal(Line l) { return EQ((a - b).dot(l.a - l.b), 0.0); }
  Point intersection(Line l) {
    assert(!is_parallel(l));
    return a + (b - a) * ((l.b - l.a).det(l.a - a) / (l.b - l.a).det(b - a));
  }
  // Projection of p to this line
  // verified AOJ CGL_1_A
  Point projection(Point p) {
    return (b - a) * ((b - a).dot(p - a) / (b - a).norm2()) + a;
  }
  double distance(Point p) {
    Point q = projection(p);
    return p.dist(q);
  }
  // Reflection point of p onto this line
  // verified AOJ CGL_1_B
  Point refl(Point p) {
    Point proj = projection(p);
    return p + ((proj - p) * 2.0);
  }
  bool left(Point p) {
    if ((p - a).det(b - a) > 0.0)
      return true;
    else
      return false;
  }
  friend istream &operator>>(istream &is, Line &l) { return is >> l.a >> l.b; }
  friend ostream &operator<<(ostream &os, const Line &l) {
    return os << l.a << " -> " << l.b;
  }
};

// ------------------- Segment  ----------------------
struct Segment {
  Point a, b;
  Segment() {}
  Segment(Point a, Point b) : a(a), b(b) {}
  Line line() { return Line(a, b); }
  bool on(Point q) {
    return (EQ((a - q).det(b - q), 0.0) && LE((a - q).dot(b - q), 0.0));
  }
  // verified AOJ CGL_2_B
  bool is_intersect(Segment s) {
    if (line().is_parallel(s.line())) {
      if (on(s.a) || on(s.b)) return true;
      if (s.on(a) || s.on(b)) return true;
      return false;
    }
    Point p = line().intersection(s.line());
    if (on(p) && s.on(p))
      return true;
    else
      return false;
  }
  bool is_intersect(Line l) {
    if (line().is_parallel(l)) {
      if (l.on(a) || l.on(b))
        return true;
      else
        return false;
    }
    Point p = line().intersection(l);
    if (on(p))
      return true;
    else
      return false;
  }
  // following 2 distance functions are verified at AOJ CGL_2_D
  double distance(Point p) {
    double res = DOUBLE_INF;
    Point q = line().projection(p);
    if (on(q)) res = min(res, p.dist(q));
    res = min(res, min(p.dist(a), p.dist(b)));
    return res;
  }
  double distance(Segment s) {
    if (is_intersect(s)) return 0.0;
    double res = DOUBLE_INF;
    res = min(res, s.distance(a));
    res = min(res, s.distance(b));
    res = min(res, this->distance(s.a));
    res = min(res, this->distance(s.b));
    return res;
  }
  friend istream &operator>>(istream &is, Segment &s) {
    return is >> s.a >> s.b;
  }
  friend ostream &operator<<(ostream &os, const Segment &s) {
    return os << s.a << " -> " << s.b;
  }
};

// ------------------- Polygon -----------------------
// Note: A polygon generally don't need to be convex.

typedef vector<Point> Polygon;
// verified AOJ CGL_3_A
double area(Polygon &pol) {
  Points vec;
  double res = 0.0;
  int M = pol.size();
  for (int i = 0; i < M; i++) {
    res += (pol[i] - pol[0]).area(pol[(i + 1) % M] - pol[0]);
  }
  return res;
}

bool is_convex(Polygon &pol) {
  int n = pol.size();
  for (int i = 0; i < n - 1; i++) {
    if (ccw(pol[i], pol[i + 1], pol[(i + 2) % n]) == CLOCKWISE) {
      return false;
    }
  }
  return true;
}

// vecrified AOJ CGL_3_C
enum { OUT, ON, IN };
int contained(Polygon &pol, Point p) {
  int n = pol.size();
  Point outer(1e9, p.y);
  int cnt = 0;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(pol[i], pol[(i + 1) % n]);
    if (e.on(p)) return ON;
    Vector a = pol[i] - p;
    Vector b = pol[(i + 1) % n] - p;
    if (a.y > b.y) swap(a, b);
    if (LE(a.y, 0.0) && GT(b.y, 0.0)) {
      if (LT(a.det(b), 0.0)) cnt++;
    }
  }
  if ((cnt & 1) == 1)
    return IN;
  else
    return OUT;
}

// Cut conovex polygon by a line and return left polygon
// verified AOJ CGL_4_C
Polygon convex_cut(Polygon &cv, Line l) {
  int n = cv.size();
  Polygon left;
  for (int i = 0; i < n; i++) {
    Segment e = Segment(cv[i], cv[(i + 1) % n]);
    if (ccw(l.a, l.b, cv[i]) != CLOCKWISE) left.pb(cv[i]);
    if (e.is_intersect(l)) {
      if (!e.line().is_parallel(l)) { left.pb(e.line().intersection(l)); }
    }
  }
  return left;
}

bool solve() {
  int N;
  cin >> N;

  if (N == 0) return false;

  vector<Point> ps(N);
  for (int i = 0; i < N; i++) cin >> ps[i];

  auto check = [&](double K) {
    vector<Line> ls;
    auto pol = ps;
    for (int i = 0; i < N; i++) {
      Point a = ps[i], b = ps[(i + 1) % N];
      Vector d = (b - a).vert().normalize() * K;
      pol = convex_cut(pol, Line(a + d, b + d));
    }
    // vector<Point> cand;
    // for (int i = 0; i < ls.size(); i++) {
    //   for (int j = i + 1; j < ls.size(); j++) {
    //     if (ls[i].is_parallel(ls[j])) continue;
    //     cand.push_back(ls[i].intersection(ls[j]));
    //   }
    // }
    // // dmp(K);
    // // dmp(ls);
    // // dmp(cand);
    // for (auto c : cand) {
    //   if (contained(ps, c) == OUT) continue;
    //   bool valid = true;
    //   for (int i = 0; i < N; i++) {
    //     Point a = ps[i], b = ps[(i + 1) % N];
    //     if (Segment(a, b).distance(c) < K) {
    //       valid = false;
    //       break;
    //     }
    //   }
    //   if (valid) return true;
    // }
    return pol.size() > 0;
  };

  double l = 0.0, r = 1000000.0;
  for (int i = 0; i < 200; i++) {
    double mid = (l + r) / 2.0;
    if (check(mid))
      l = mid;
    else
      r = mid;
  }

  cout << l << endl;

  return true;
}

int main() {
  fastio();
  if (!multitest) {
    while (solve()) {}
  } else {
    cerr << "[Warning] Multi testcase mode on" << endl;
    int t;
    cin >> t;
    while (t--) solve();
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3512
final_rank: 6

code_snippet: #include<bits/stdc++.h> 
using namespace std;
using ll=long long int;
//using Int=__int128;
#define ALL(A) A.begin(),A.end()
template<typename T1,typename T2> bool chmin(T1 &a,T2 b){if(a<=b)return 0; a=b; return 1;}
template<typename T1,typename T2> bool chmax(T1 &a,T2 b){if(a>=b)return 0; a=b; return 1;}
template<typename T> constexpr int bitUP(T x,int a){return (x>>a)&1;}
//→　↓　←　↑ 
int dh[4]={0,1,0,-1}, dw[4]={1,0,-1,0};
//右上から時計回り
//int dh[8]={-1,0,1,1,1,0,-1,-1}, dw[8]={1,1,1,0,-1,-1,-1,0};
//long double EPS = 1e-6;
//long double PI = acos(-1);
//const ll INF=(1LL<<62);
const int MAX=(1<<30);
constexpr ll MOD=1000000000+7;
//constexpr ll MOD=998244353;


inline void bin101(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(20);
}

using Graph=vector<vector<int>>;

template<typename T >
struct edge {
	int to;
	T cost;
	edge()=default;
	edge(int to, T cost) : to(to), cost(cost) {}

};
template<typename T>
using WeightGraph=vector<vector<edge<T>>>;

//要素数n 初期値x
template<typename T>
inline vector<T> vmake(size_t n,T x){
	return vector<T>(n,x);
}

//a,b,c,x data[a][b][c] 初期値x
template<typename... Args>
auto vmake(size_t n,Args... args){
	auto v=vmake(args...);
	return vector<decltype(v)>(n,move(v));
}

////////////////////////////
// マクロや型
////////////////////////////

using DD=long double;

const DD EPS=1e-12;
const DD INF=1e50;
const DD PI=acosl(-1.0);
#define EQ(a,b) (abs( (a) - (b) )<EPS) //a==b
#define LS(a,b) ( (a)+EPS<(b) ) //a<b
#define GR(a,b) ( (a)>(b)+EPS ) //a>b
#define LE(a,b) ( (a)<(b)+EPS ) //a<=b
#define GE(a,b) ( (a)>(b)-EPS ) //a>=b

#define X real()
#define Y imag()


//点
using Point=complex<DD>;
istream &operator>>(istream &is, Point &p) {
  DD x,y;
  is>>x>>y;
  p=Point(x,y);
  return is;
}

//点a→点bの線分
//aとbが等しい時、色々バグるから注意!
struct Segment{
    Point a,b;
    Segment()=default;
    Segment(Point a,Point b) :a(a),b(b){}
    Segment(DD ax,DD ay,DD bx,DD by):a(ax,ay),b(bx,by){}
    Segment(DD r,Point a) :a(a),b(a+polar((DD)1.0,r)){} 
};
using Line=Segment;

//円
struct Circle{
    Point p;
    DD r;
    Circle()=default;
    Circle(Point p,DD r):p(p),r(r){}
};

using Polygon=vector<Point>;

////////////////////////////
// 基本計算
////////////////////////////

//度→ラジアン
inline DD torad(const DD deg){return deg*PI/180;}
//ラジアン→度
inline DD todeg(const DD rad){return rad*180/PI;}
//内積 |a||b|cosθ
inline DD dot(const Point &a,const Point &b){return (conj(a)*b).X;}
//外積 |a||b|sinθ
inline DD cross(const Point &a,const Point &b){return (conj(a)*b).Y;}
//ベクトルpを反時計回りにtheta(ラジアン)回転
Point rotate(const Point &p,const DD theta){return p*Point(cos(theta),sin(theta));}

//余弦定理 cos(角度abc(ラジアン))を返す
//長さの対応に注意 ab:辺abの長さ
//verify:https://codeforces.com/gym/102056/problem/F
DD cosine_formula(const DD ab,const DD bc,const DD ca){
    return (ab*ab+bc*bc-ca*ca)/(2*ab*bc);
}

inline bool xy_sort(const Point &a,const Point &b){
    if(a.X+EPS<b.X) return true;
    if(EQ(a.X,b.X) && a.Y+EPS<b.Y) return true;
    return false;
}
inline bool yx_sort(const Point &a,const Point &b){
    if(a.Y+EPS<b.Y) return true;
    if(EQ(a.Y,b.Y) && a.X+EPS<b.X) return true;
    return false;
}
namespace std{
    inline bool operator<(const Point &a,const Point &b)noexcept{
        return xy_sort(a,b);
    }
}
//DDの比較関数
//map<DD,vector<pii>,DDcom>
struct DDcom{
    bool operator()(const DD a, const DD b) const noexcept {
        return a+EPS<b;
    }
};


////////////////////////////
// 平行や直交
////////////////////////////

bool isOrthogonal(const Point &a,const Point &b){
    return EQ(dot(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isOrthogonal(const Segment &s,const Segment &t){
    return EQ(dot(s.a-s.b,t.a-t.b),0.0);
}
bool isParallel(const Point &a,const Point &b){
    return EQ(cross(a,b),0.0);
}
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool isParallel(const Segment &s,const Segment &t){
    return EQ(cross(s.a-s.b,t.a-t.b),0);
}
//線分a→bに対して点cがどの位置にあるか
//反時計回り:1　時計回り:-1 直線上(a,b,c:-2 a,c,b:0 c,a,b:2)
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
//線分a→bの端点にcがあるなら0と判定されるはず
int ccw(const Point &a,Point b,Point c){
    if(EQ(abs(b-c),0) or EQ(abs(a-c),0)) return 0;
    b-=a;c-=a;
    if(cross(b,c)>EPS) return 1;
    if(cross(b,c)<-EPS) return -1;
    if(dot(b,c)<-EPS) return 2;
    if(LS(norm(b),norm(c))) return -2;
    return 0;
}

////////////////////////////
// 射影と反射
////////////////////////////

//射影
//直線lに点pから垂線を引いたときの交点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point project(const Point &p,const Line &l){
    Point base=l.b-l.a;
    DD r=dot(p-l.a,base)/norm(base);
    return l.a+base*r;
}
//反射
//直線lに対して点pと対称な点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflect(const Point &p,const Line &l){
    return p+(project(p,l)-p)*(DD)2.0;
}

////////////////////////////
// 点との距離
////////////////////////////

//点と直線の距離
DD DistPL(const Point &p,const Line &l){
    return abs(cross(l.b-l.a,p-l.a))/abs(l.b-l.a);
}
//点と線分の距離
DD DistPS(const Point &p,const Segment &s){
    if( dot(s.b-s.a,p-s.a)<0.0 ) return abs(p-s.a);
    if( dot(s.a-s.b,p-s.b)<0.0 ) return abs(p-s.b);
    return DistPL(p,s);
}

////////////////////////////
// 線分と直線
////////////////////////////

//線分a-b,c-dは交差するか?
//接する場合も交差すると判定
//接する場合は交差しないとするなら<=を<に変換
bool intersect(const Point &a,const Point &b,const Point &c,const Point &d){
    return(ccw(a,b,c)*ccw(a,b,d)<=0 && ccw(c,d,a)*ccw(c,d,b)<=0);
}
//線分s,tは交差するか？
//接する場合も交差すると判定
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B&lang=ja
//接する場合は交差しないとするならintersectの<=を<に変換
bool intersect(const Segment &s,const Segment &t){
    return intersect(s.a,s.b,t.a,t.b);
}
// 2直線の交点
// 線分の場合はintersectをしてから使う
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C&lang=ja
Point crossPoint(const Line &s,const Line &t){
    Point base=t.b-t.a;
    DD d1=cross(base,t.a-s.a);
    DD d2=cross(base,s.b-s.a);
    if(EQ(d1,0) and EQ(d2,0)) return s.a; //同じ直線
    if(EQ(d2,0)) assert(false); //交点がない
    return s.a+d1/d2*(s.b-s.a);
}
//線分と線分の距離
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D&lang=ja
DD Dist(const Segment &s,const Segment &t){
    if(intersect(s,t)) return 0.0;
    return min(min(DistPS(t.a,s),DistPS(t.b,s)),min(DistPS(s.a,t),DistPS(s.b,t)) );
}
bool issame(const Line &l,const Line &m){
    if (GR(abs(cross(m.a - l.a, l.b - l.a)),0) ) return false;
    if (GR(abs(cross(m.b - l.a, l.b - l.a)),0) ) return false;
    return true;
}

////////////////////////////
// 円
////////////////////////////
//直線lと円Cの交点
//l.aにより近い方がindexが小さい
//veirfy:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
vector<Point> crossPointLC(const Line &l,const Circle &c){
    vector<Point> ret;
    if(GR(DistPL(c.p,l),c.r)) return ret; //交点がないとき、空ベクトルを返す
    Point pr=project(c.p,l);
    Point e=(l.b-l.a)/(abs(l.b-l.a));
    DD base=sqrt(c.r*c.r-norm(pr-c.p));
    ret.push_back(pr-e*base);
    ret.push_back(pr+e*base);
    if(EQ(DistPL(c.p,l),c.r)) ret.pop_back(); //接するとき
    return ret;
}
//線分sと円cの交点
//交点がないときは空ベクトルを返す
//線分の端が交わる場合も交点とみなす
//s.aにより近い方がindexが小さい
vector<Point> crossPointSC(const Segment &s,const Circle &c){
    vector<Point> ret;
    if(DistPS(c.p,s)>c.r+EPS) return ret;
    auto koho=crossPointLC(s,c);
    for(auto p:koho){
        if(ccw(s.a,s.b,p)==0 or EQ(abs(p-s.a),0) or EQ(abs(p-s.b),0)) ret.push_back(p);
    }
    return ret;
}

//円aと円bの共通接線の数
//離れている:4 外接:3 交わる:2 内接:1 内包:0
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A
int intersect(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    if(GR(d,a.r+b.r)) return 4;
    if(EQ(d,a.r+b.r)) return 3;
    if(EQ(d,abs(a.r-b.r))) return 1;
    if(LS(d,abs(a.r-b.r))) return 0;
    return 2;
}

//円aと円bの交点
//交点がないときは空ベクトルを返す
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
vector<Point> crossPoint(const Circle &a,const Circle &b){
    vector<Point> ret;
    if(GR(abs(a.p-b.p),a.r+b.r)) return ret;
    DD d=abs(a.p-b.p);
    DD s=acosl((a.r*a.r+d*d-b.r*b.r)/(2*a.r*d)); //0~π
    DD t=arg(b.p-a.p);
    if(EQ(a.r+b.r,d)) ret.push_back(a.p+polar(a.r,t));
    else ret.push_back(a.p+polar(a.r,t+s)),ret.push_back(a.p+polar(a.r,t-s));
    return ret;
}

//点pから円cに接線を引いたときの接点
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F&lang=ja
vector<Point> TanLine(const Point &p,const Circle &c){
    vector<Point> ret;
    DD d=abs(p-c.p);
    if(LS(d,c.r)) return ret; //pがcの内部にある場合
    if(EQ(d,c.r)){
        ret.push_back(p);
        return ret; //円の線上にある場合
    } 
    return crossPoint(c,Circle(p,sqrt(d*d-c.r*c.r)));
}

//円a,bの共通接線
//https://www.slideshare.net/kujira16/ss-35861169
//Line.aは円aと接線の交点
//(接線と円bの交点)と(接線と円aの交点)が違う場合はLine.bは(接線と円bの交点)
//一致する場合は円aの中心からLine.aに向かうベクトルを反時計回りに90度回転したものを
//Line.aに足したもの
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2201
vector<Line> TanLine(const Circle &a,const Circle &b){
    DD d=abs(a.p-b.p);
    vector<Line> ret;
    //外接線
    if(intersect(a,b)>=2){
        if(EQ(a.r,b.r)){
            Point up=polar(a.r,arg(b.p-a.p)+PI/2);
            ret.emplace_back(a.p+up,b.p+up);
            ret.emplace_back(a.p-up,b.p-up);
        }else{
            Point q=(a.p*b.r-b.p*a.r)/(b.r-a.r);
            auto as=TanLine(q,a);
            auto bs=TanLine(q,b);
            assert(as.size()==2 and bs.size()==2);
            for(int i=0;i<2;i++){
                ret.emplace_back(as[i],bs[i]);
            }
        }
    }else if(intersect(a,b)==1){ //内接する場合
        Point dir;
        if(a.r>b.r) dir=polar(a.r,arg(b.p-a.p));
        else dir=polar(a.r,arg(a.p-b.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    //内接線
    if(GR(abs(a.p-b.p),a.r+b.r)){ //円が離れている場合
        Point q=a.p+(b.p-a.p)*a.r/(a.r+b.r);
        auto as=TanLine(q,a);
        auto bs=TanLine(q,b);
        assert(as.size()==2 and bs.size()==2);
        for(int i=0;i<2;i++){
            ret.emplace_back(as[i],bs[i]);
        }
    }else if(EQ(d,a.r+b.r)){ //円が接している場合
        Point dir=polar(a.r,arg(b.p-a.p));
        ret.emplace_back(a.p+dir,a.p+dir+rotate(dir,PI/2));
    }
    return ret;
}
//２つの円の共通部分の面積
//参考: https://tjkendev.github.io/procon-library/python/geometry/circles_intersection_area.html
//verify: https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6005736#1
DD Area(const Circle &c1,const Circle &c2){
    DD cd=abs(c1.p-c2.p);
    if(LE(c1.r+c2.r,cd)) return 0; //円が離れている

    if(LE(cd,abs(c1.r-c2.r))) //片方の円が他方を包んでいる
        return min(c1.r,c2.r)*min(c1.r,c2.r)*PI;

    DD theta1=acosl(cosine_formula(c1.r,cd,c2.r));
    DD theta2=acosl(cosine_formula(c2.r,cd,c1.r));

    return c1.r*c1.r*theta1+c2.r*c2.r*theta2-c1.r*cd*sin(theta1);
}


////////////////////////////
// 三角形
////////////////////////////

//ヘロンの公式　三角形の面積を返す
//三角形が成立するか(平行ではないか)を忘れずに
DD Heron(const DD ad,const DD bd,const DD cd){
    DD s=(ad+bd+cd)/2;
    return sqrt(s*(s-ad)*(s-bd)*(s-cd));
}
//三角形の外接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_C
Circle CircumscribedCircle(const Point &a,const Point &b,const Point &c){
    Point bc=(b+c)/(DD)2.0;
    Line aa(bc,bc+rotate(c-b,PI/2));
    Point ab=(a+b)/(DD)2.0;
    Line cc(ab,ab+rotate(b-a,PI/2));
    Point p=crossPoint(aa,cc);
    return Circle(p,abs(a-p));
}
//三角形の内接円
//isParallel()を使って三角形が成立するか(平行ではないか)を忘れずに
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_B
Circle InCircle(const Point &a,const Point &b,const Point &c){
    Line aa(a,a+polar((DD)1.0,(arg(b-a)+arg(c-a))/(DD)2.0));
    Line bb(b,b+polar((DD)1.0,(arg(a-b)+arg(c-b))/(DD)2.0));
    Point p=crossPoint(aa,bb);
    return Circle(p,DistPL(p,Line(a,b)));
}

////////////////////////////
// 多角形
////////////////////////////

//点pが多角形gに対してどの位置にあるか
//中:2 辺上:1 外:0
//凸多角形である必要ない
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
int contains(const Point &p,const vector<Point> &g){
    int n=(int)g.size();
    int x=false;
    for(int i=0;i<n;i++){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(EQ(cross(a,b),0) && dot(a,b)<EPS) return 1;
        if(a.Y>b.Y) swap(a,b);
        if(a.Y<EPS && EPS<b.Y && cross(a,b)>EPS) x=!x;
    }
    return (x?2:0);
}
//凸性判定
//多角形gは凸か？
//gは反時計回りでも時計回りでもいい
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
bool isConvex(const vector<Point> &g){
    int n=(int)g.size();
    if(n<=3) return true;
    int flag=0;
    int t;
    for(int i=0;i<n;i++){
        Point a(g[(i+1)%n]-g[i]),b(g[(i+2)%n]-g[i]);
        if(cross(a,b)>EPS) t=1;
        else if(cross(a,b)<-EPS) t=-1;
        else continue;
        if(flag==-t) return false;
        flag=t;
    }
    return true;
}

//凸包　アンドリューのアルゴリズム
//O(NlogN)
//反時計回りの多角形を返す
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
vector<Point> ConvexHull(vector<Point> s,const bool on_edge){
    int j;
    if(on_edge) j=-1;
    else j=1;
    int sz=(int)s.size();
    if(sz<3) return s;
    sort(s.begin(),s.end(),yx_sort);

    int n=0;
    vector<Point> res(2*sz);
    for(int i=0;i<sz;i++){
        while(n>=2 && cross(res[n-1]-res[n-2],s[i]-res[n-2])<EPS*j){
            n--;
        }
        res[n]=s[i];
        n++;
    }
    int t=n+1;
    for(int i=sz-2;i>=0;i--){
        while(n>=t && cross(res[n-1]-res[n-2],s[i]-res[n-2])<EPS*j){
            n--;
        }
        res[n]=s[i];
        n++;
    }
    res.resize(n-1);
    return res;
}

//多角形g(凸でなくてもいい)の符号付き面積
//反時計回りの多角形なら正の値を返す　時計回りなら負
//O(N)
//https://imagingsolution.net/math/calc_n_point_area/
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
DD Area(const vector<Point> &g){
    DD ret=0.0;
    int n=(int)g.size();
    for(int i=0;i<n;i++){
        ret+=cross(g[i],g[(i+1)%n]);
    }
    return ret/2.0;
}

//凸多角形gを直線lで切断
//直線の左側(向きを考慮)にできる凸多角形を返す
//多角形gが反時計回りならば、反時計回りで返す(時計回りなら時計回り)
//直線上の頂点を含む線分の交点は含めてない
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C
vector<Point> ConvexCut(const vector<Point> &g,const Line &l){
    vector<Point> ret;
    int gz=(int)g.size();
    for(int i=0;i<gz;i++){
        Point now=g[i],next=g[(i+1)%gz];
        if(ccw(l.a,l.b,now)!=-1) ret.push_back(now);
        if(EQ(DistPL(now,l),0) or EQ(DistPL(next,l),0)) continue;
        if(ccw(l.a,l.b,now)*ccw(l.a,l.b,next)<0){
            ret.push_back(crossPoint(Line(now,next),l));
        }
    }
    return ret;
}
//部品
inline DD calc(const Point &a,const Point &b,const DD &r,const bool triangle){
    if(triangle) return cross(a,b);
    else return r*r*arg(b/a);
}
//部品
DD calcArea(const DD &r,const Point &a,const Point &b){
    if(EQ(abs(a-b),0)) return 0;
    bool ina=(abs(a)<r+EPS);
    bool inb=(abs(b)<r+EPS);
    if(ina && inb) return cross(a,b);
    auto cr=crossPointSC(Segment(a,b),Circle(Point(0,0),r));
    if(cr.empty()) return calc(a,b,r,false);
    auto s=cr[0],t=cr.back();
    return calc(s,t,r,true)+calc(a,s,r,ina)+calc(t,b,r,inb);
}
//円と多角形の共通部分の面積
//多角形が反時計回りならば正の値を返す
//凸多角形でなくても大丈夫
//http://drken1215.hatenablog.com/entry/2020/02/02/091000
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H&lang=ja
DD Area(const Circle &c,const vector<Point> &g){
    DD ret=0.0;
    int gz=g.size();
    if(gz<=2) return ret;
    for(int i=0;i<gz;i++){
        Point a=g[i]-c.p,b=g[(i+1)%gz]-c.p;
        ret+=calcArea(c.r,g[i]-c.p,g[(i+1)%gz]-c.p);
    }
    return ret/2.0;
}

//点と多角形の距離
//点が多角形の中にあるなら0
DD Dist(const Point &a,const vector<Point> &b){
	if(b.size()==1) return abs(a-b[0]);
	if(contains(a,b)>=1) return 0.0L;
	DD ret=INF;
	for(int i=0;i<b.size();i++){
		chmin(ret,DistPS(a,Segment(b[i],b[(i+1)%b.size()])));
	}
	return ret;
}

//多角形と多角形の距離
//どちらかが内側に入っていたら0
//全ての線分の組み合わせの距離を求めて、その最小が答え
//O(size(a)*size(b))
//sizeが1の時は点との距離になる
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2827
DD Dist(const vector<Point> &a,const vector<Point> &b){
	DD ret=INF;
	if(a.size()==1) return Dist(a[0],b);
	if(b.size()==1) return Dist(b[0],a);

	if(contains(a[0],b)>=1) return 0.0L;
	if(contains(b[0],a)>=1) return 0.0L;

	for(int i=0;i<a.size();i++){
		for(int j=0;j<b.size();j++){
			Segment sa(a[i],a[(i+1)%a.size()]);
			Segment sb(b[j],b[(j+1)%b.size()]);
			chmin(ret,Dist(sa,sb));
		}
	}
	return ret;
}

////////////////////////////
// 最近(遠)点間距離
////////////////////////////
//部品
DD RecClosetPair(const vector<Point>::iterator it,const int n){
    if(n<=1) return INF;
    int m=n/2;
    DD x=it[m].X;
    DD d=min(RecClosetPair(it,m),RecClosetPair(it+m,n-m));
    inplace_merge(it,it+m,it+n,yx_sort);
    vector<Point> v;
    for(int i=0;i<n;i++){
        if(abs(it[i].X-x)>=d) continue;
        for(int j=0;j<v.size();j++){
            DD dy=it[i].Y-v[(int)v.size()-1-j].Y;
            if(dy>=d) break;
            DD dx=it[i].X-v[(int)v.size()-1-j].X;
            d=min(d,sqrt(dx*dx+dy*dy));
        }
        v.push_back(it[i]);
    }
    return d;
}
//最近点対の距離
//点が1つのときINFを返す
//O(NlogN)
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_5_A
DD ClosetPair(vector<Point> g){
    sort(g.begin(),g.end(),xy_sort);
    return RecClosetPair(g.begin(),g.size());
}

//最遠頂点間
//verify:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_B
DD Diameter(vector<Point> g){
    g=ConvexHull(g,1);
    int gz=g.size();
    int m=0,M=0;
    for(int i=1;i<gz;i++){
        if(g[i].Y<g[m].Y) m=i;
        if(g[i].Y>g[M].Y) M=i;
    }
    DD ret=0;
    int sm=m,sM=M;
    while(m!=sM || M!=sm){
        ret=max(ret,norm(g[m]-g[M]));
        if(cross(g[(m+1)%gz]-g[m],g[(M+1)%gz]-g[M])<0) m=(m+1)%gz;
        else M=(M+1)%gz;
    }
    return sqrt(ret);
}
//動的凸包
//辺上にある点は含めない
//verify:https://atcoder.jp/contests/geocon2013/tasks/geocon2013_c
struct DynamicConvex{
	set<Point> up,down;
	DynamicConvex(){}
 
	bool isContain(set<Point> &pol,Point p){
		if(pol.size()==0) return false;
		if(pol.size()==1){
			Point q=*begin(pol);
			return EQ(q.X,p.X) and GE(q.Y,p.Y);
		}
		assert(pol.size()>=2);
        auto left=begin(pol);
        auto right=(--end(pol));
        if(LS(p.X,left->X) or GR(p.X,right->X)) return false;
        
        
        auto q1=pol.upper_bound(Point(p.X,INF));
        if(q1==end(pol)){
            return GE(right->Y,p.Y);
        }
        auto q2=q1--; //q1が範囲外になるのは最初に弾いてる
        return GE(cross(p-*q1,*q2-*q1),0.0);
	}
    bool isContain(Point p){
        if(not isContain(up,p)) return false;
        if(not isContain(down,Point(p.X,-p.Y))) return false;
        return true;
    }
 
	void add(set<Point> &pol,Point p){
		if(pol.size()==0){
			pol.insert(p);
			return;
		}
		if(pol.size()==1){
            Point q=*begin(pol);
			if(EQ(q.X,p.X)){
                pol.clear();
                pol.insert(max(p,q));
			}else{
				pol.insert(p);
			}
            return;
		}
        assert(pol.size()>=2);
        if(isContain(pol,p)) return;
        //left
        auto q1=pol.upper_bound(Point(p.X,INF));
        if(q1!=begin(pol)){
            q1--;
            while(pol.size()>=1 and q1!=begin(pol)){
                auto q2=q1--;
                if(GR(cross(*q2-p,*q1-p),0)) break;
                pol.erase(q2);
            }
        }
        //right
        q1=pol.lower_bound(Point(p.X,-INF));
        if(q1!=end(pol)){
            while(pol.size()>1 and q1!=--end(pol)){
                auto q2=q1++;
                if(GR(cross(*q1-p,*q2-p),0.0)) break;
                pol.erase(q2);
            }
        }
        pol.insert(p);
	}
 
	void add(Point p){
		add(up,p);
		add(down,Point(p.X,-p.Y)); //upと同じように処理をしたいから
	}
};

//垂直二等分線
//p-↑-q こんなかんじ
//voronoiで使う
Line bisector(const Point &p, const Point &q) {
    Point c=(p+q)/DD(2.0);
    Point v=rotate(q-p,PI/2);
    v/=abs(v);
    return Line(c-v,c+v);
}

//ボロノイ図
//pol:全体 ps:点の集合 id:中心となる点の添字 pp:中心となる点
//計算量: pol.size()*ps.size()
//verify: https://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=6005648#1
vector<Point> voronoi(Polygon pol,const vector<Point> &ps,int id=-1,const Point pp=Point()){
    Point p;
    if(id!=-1) p=ps[id];
    else p=pp;
    for(size_t i=0;i<ps.size();i++){
        if(i==id) continue;
        Line l=bisector(p,ps[i]);
        pol=ConvexCut(pol,l);
    }
    return pol;
}



void solve(){
while(true){
    int N; cin>>N;
    if(N==0) return;
    Polygon P(N);
    for(int i=0;i<N;i++) cin>>P[i];

    DD ng=0,ok=1e5;
    int T=1000;
    while(T--){
        DD mid=(ok+ng)/2;
        auto pol=P;
        for(int i=0;i<N;i++){
            Point d=rotate(P[(i+1)%N]-P[i],PI/2);
            d/=abs(d);
            d*=mid;
            Line l(P[i]+d,P[(i+1)%N]+d);
            pol=ConvexCut(pol,l);
        }
        if(EQ(Area(pol),EPS) or pol.size()<=2) ok=mid;
        else ng=mid;
    }
    cout<<ok<<endl;
}
}

int main(){
    bin101();
    int T=1;
    //cin>>T;
    while(T--) solve();
}
accuracy: 1
time_ms: 3800
memory_kb: 3768
final_rank: 20

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

double eps = 1e-8;

struct point{
    double x,y;
    point() {}
    point(double x,double y): x(x), y(y) {}
    point& operator-=(const point &p){
        x -= p.x; y -= p.y;
        return *this;
    }
    point& operator+=(const point &p){
        x += p.x; y += p.y;
        return *this;
    }
    point& operator*=(double d){
        x *= d; y *= d;
        return *this;
    }
    point& operator/=(double d){
        x /= d; y /= d;
        return *this;
    }
    const point operator+ (const point& p) const;
    const point operator- (const point& p) const;
    const point operator* (double d) const;
    const point operator/ (double d) const;
};
const point point::operator+ (const point& p) const{
    point res(*this); return res += p;
}
const point point::operator- (const point& p) const{
    point res(*this); return res -= p;
}
const point point::operator* (double d) const{
    point res(*this); return res *= d;
}
const point point::operator/ (double d) const{
    point res(*this); return res /= d;
}

struct line{
    point A,B;
    line() {}
    line(point A, point B): A(A), B(B) {}
};
// 前のライブラリが一部残ってる
// 後で整備する
// A+B
point sum(point A,point B){
    A.x+=B.x; A.y+=B.y; return A;
}
// A-B
point sub(point A,point B){
    A.x-=B.x; A.y-=B.y; return A;
}
// A to B
point vec(line L){
    return sub(L.B,L.A);
}

double abs(point P){
    return sqrt(P.x*P.x+P.y*P.y);
}

double dist(point A,point B){
    return abs(sub(A,B));
}

double dot(point a,point b){
    return a.x*b.x+a.y*b.y;
}

double cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}

int ccw(point a,point b,point c){
    b={b.x-a.x,b.y-a.y};
    c={c.x-a.x,c.y-a.y};
    if(cross(b,c)>eps)return 1; // a,b,c反時計回り
    if(cross(b,c)<-eps)return -1; // a,b,c時計周り
    if(dot(b,c)<-eps)return 2; // c,a,b 一直線
    if((b.x*b.x+b.y*b.y)<(c.x*c.x+c.y*c.y))return -2; // a,b,c 一直線
    return 0; // a,c,b 一直線
}

// 反時計回りで凸多角形を与えるものとする
// 始点と終点を一致させた入力を与える
// AOJ 1283
bool point_in_polygon(point p, vector<point> polygon){
    int n = polygon.size();
    for(int i=0;i+1<n;i++){
        if(cross(p - polygon[i], polygon[i+1] - polygon[i]) > 0){
            return false;
        }
    }
    return true;
}
line parallel_line(line l, double d){
    point v = point(-(l.B - l.A).y, (l.B - l.A).x);
    v = v / abs(v);
    l.A += v * d;
    l.B += v * d;
    return l;
}
point line_intersection(line l1, line l2){
    return l1.A + vec(l1) * cross(l2.A - l1.A, vec(l2)) / cross(vec(l1), vec(l2));
}
// 交点の座標を返す
point Crosspoint(point a,point b,point c,point d){
    point cd={d.x-c.x,d.y-c.y};
    point ca={a.x-c.x,a.y-c.y};
    point cb={b.x-c.x,b.y-c.y};
    double d1=abs(cd.x*ca.y-cd.y*ca.x),d2=abs(cd.x*cb.y-cd.y*cb.x);
    double t=d1/(d1+d2);
    return {a.x+(b.x-a.x)*t,a.y+(b.y-a.y)*t};
}
vector<point> convex_cut(const vector<point> &g, const line &l){
    vector<point> Q;
    for(int i=0;i<g.size();i++){
        point A=g[i],B=g[(i+1)%g.size()];
        if(ccw(l.A,l.B,A)!=-1)Q.push_back(A);
        if(ccw(l.A,l.B,A)*ccw(l.A,l.B,B)<0)Q.push_back(Crosspoint(A,B,l.A,l.B));
    }
    return Q;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false); 
    int n;
    while(cin >> n,n){
        vector<point> v(n);
        for(int i=0;i<n;i++){
            cin >> v[i].x >> v[i].y;
        }
        v.push_back(v[0]);
        double l = 0, r = 1e6;
        auto check=[&](double mid)->bool{
            auto polygon = v;
            polygon.pop_back();
            vector<line> seg;
            for(int i=0;i<n;i++){
                seg.push_back(parallel_line(line(v[i], v[i+1]), mid));
            }
            for(auto &l:seg){
                polygon = convex_cut(polygon, l);
                if(polygon.size() <= 1)return false;
            }
            return true;
        };
        for(int _=0;_<120;_++){
            double mid = (l+r)/2.0;
            if(check(mid)){
                l = mid;
            }
            else{
                r = mid;
            }
        }
        printf("%.9f\n",l);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3524
final_rank: 5

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 998244353 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  x %= mod;
  if(x == 0) return 0;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;
  BIT(){}
  BIT(int n){
    N = n;
    node.resize(N+10);
  }
  void build(int n) {
    N = n;
    node.resize(N+10);
  }
  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = 1001;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};

using Point = complex< double >;
bool eq(double a, double b){ return fabs(a-b) < EPS; }
namespace std {
  bool operator<(const Point a, const Point b) {
    if(eq(a.real(),b.real())) return a.imag() < b.imag();
    return a.real() < b.real();
  }
}

istream &operator>> (istream &is, Point &p) {
  double a, b;
  is >> a >> b;
  p = Point(a, b);
  return is;
}

ostream &operator<< (ostream &os, Point &p) {
  return os << fixed << setprecision(10) << p.real() << " " << p.imag();
}

bool operator<(const Point &a, const Point &b) {
  return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
}

// rotate Φ(rad)
// x = r * cos(θ + Φ)
//   = r * cos(θ) * cos(Φ) - r * sin(θ) * sin(Φ)
//   = x * cos(Φ) - y * sin(Φ) (∵ cos(θ) = x/r, sin(θ) = y/r)  
Point rotate(double phi, const Point &p) {
  double x = p.real(), y = p.imag();
  return Point(x * cos(phi) - y * sin(phi), x * sin(phi) + y * cos(phi));
}

double radian_to_degree(double r) {
  return (r * 180.0 / PI);
}

double degree_to_radian(double d) {
  return (d * PI / 180.0);
}

struct Line{
  Point a, b;

  Line() = default;

  Line(Point a, Point b) : a(a), b(b){}

  Line(double A, double B, double C){
    //ax + by = c
    if(eq(A, 0)){
      a = Point(0, C/B), b = Point(1, C/B);
    }else if(eq(B, 0)){
      a = Point(C/A, 0), b = Point(C/A, 1);
    }else{
      a = Point(0, C/B), b = Point(C/A, 0);
    }
  }

  friend istream &operator>>(istream &is, Line &a) {
    return is >> a.a >> a.b;
  }
  friend ostream &operator<<(ostream &os, Line &a) {
    return os << a.a << " to " << a.b;
  }
};

struct Segment: Line {
  Segment() = default;

  Segment(Point a, Point b) : Line(a, b) {}
};

struct Circle {
  Point p;
  double r;

  Circle() = default;

  Circle(Point p, double r): p(p), r(r){}
};

using Points = vector<Point>;
using Polygon = vector<Point>;
using Segments = vector<Segment>;
using Lines = vector<Line>;
using Circles = vector<Circle>;

double cross(const Point &a, const Point &b) {
  return a.real() * b.imag() - a.imag() * b.real();
}

double dot(const Point& a, const Point &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}

//https://mathtrain.jp/projection
Point projection(const Line &l, const Point &p){
  double t = dot(p - l.a, l.a-l.b) / norm(l.a - l.b);
  return l.a + (l.a - l.b) * t;
}

Point projection(const Segment &l, const Point &p){
  double t = dot(p - l.a, l.b-l.a) / norm(l.a - l.b);
  return l.a + (l.b - l.a) * t;
}

Point reflection(const Line &l, const Point &p){
  return p + (projection(l, p) - p) * 2.0;
}

int ccw(const Point &a, const Point &b, const Point &c) {
  if(cross(b-a, c-a) > EPS) return 1;   // "COUNTER_CLOCKWISE"
  if(cross(b-a, c-a) < -EPS) return -1; // "CLOCKWISE"
  if(dot(b-a, c-a) < -EPS) return 2;    // "ONLINE_BACK" c-a-b
  if(norm(b-a) < norm(c-a) - EPS) return -2;  // "ONLINE_FRONT" a-b-c
  return 0;                         // "ON_SEGMENT" a-c-b
}

bool parallel(const Line &a, const Line &b){
  return eq(cross(a.a-a.b, b.a-b.b), 0.0);
}
bool orthogonal(const Line &a, const Line &b){
  return eq(dot(a.a-a.b, b.a-b.b), 0.0);
}
enum { OUT, ON, IN };

int contains(const Polygon& Q, const Point& p){
  bool in = false;
  for(int i=0; i<Q.size(); i++){
    Point a = Q[i] - p, b = Q[(i+1)%Q.size()]-p;
    if(a.imag() > b.imag()) swap(a, b);
    if(a.imag() <= 0 && 0 < b.imag() && cross(a, b) < 0) in = !in;
    if(cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}
bool intersect(const Segment &s, const Point &p){
  return ccw(s.a, s.b, p) == 0;
}

//直線の交差判定
bool intersect(const Line &a, const Line &b) {
  if(parallel(a, b)) return 0;
  return 1;
}

//線分が重なる/端点で交わるときtrue
bool intersect(const Segment &a, const Segment &b) {
  return ccw(a.a, a.b, b.a) * ccw(a.a, a.b, b.b) <= 0 && ccw(b.a, b.b, a.a) * ccw(b.a, b.b, a.b) <= 0;
}



Point crosspoint(const Line &a, const Line &b){
  double d = cross(b.b-b.a, a.b-a.a);
  if(eq(d, 0.0)) return Point(1e9, 1e9); 
  
  return a.a + (a.b - a.a) * cross(b.b-b.a, b.b-a.a) / d;
}

Point crosspoint(const Segment &a, const Segment &b){
  return crosspoint(Line(a.a, a.b), Line(b.a, b.b));
}
double distance(const Point &a, const Point &b){
  return abs(a - b);
}
double distance(const Line &l, const Point &p){
  return abs( cross(p - l.a, l.b-l.a) / abs(l.b-l.a) );
}
double distance(const Segment &s, const Point &p){
  Point r = projection(s, p);
  if(intersect(s, r)) return abs(r-p);
  return min(abs(s.a - p), abs(s.b - p));
}
// double distance(const Line &a, const Line &b){

// }
// double distance(const Line &a, const Segment &b){

// }
double distance(const Segment &a, const Segment &b) {
  return intersect(a, b) ? 0 : min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

/* 2円の交点 */
vector<Point> crosspointCC(Circle C1, Circle C2){
  vector<Point> ps;
  Point ab = C2.p - C1.p;
  double d = abs(ab);
  double rc = (C1.r * C1.r + d * d - C2.r * C2.r) / (2 * d);
  if(eq(d, 0) || C1.r < abs(rc)) return ps;

  double rs = sqrt(C1.r * C1.r - rc*rc);

  Point abN = ab * Point(0, rs/d);
  Point cp = C1.p + rc / d * ab;
  ps.push_back(cp + abN);
  if(!eq(norm(abN), 0))ps.push_back(cp-abN);
  return ps;
}

vector<Point> crosspointCL(Circle C, Line l){
  Point p = projection(l, C.p);

  Point e = (l.b-l.a)/abs(l.b-l.a);
  if(eq(distance(l, C.p), C.r)) {
    return vector<Point>{p, p};
  }
  double base = sqrt(C.r*C.r-norm(p-C.p));
  
  return vector<Point>{p+e*base, p-e*base};
}

/* 円同士の共通部分の面積を求める */
// verify: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_I date: 2020/10/11
long double AreaofCC(Circle& C1, Circle& C2){
  if(C1.r > C2.r) swap(C1, C2);
  long double nor = norm(C1.p - C2.p);
  long double dist = sqrtl(nor);
  
  if(C1.r + C2.r < dist+EPS) return 0;

  if(dist + C1.r < C2.r + EPS) return C1.r * C1.r * PI;

  long double theta1 = acosl((nor + C1.r*C1.r - C2.r * C2.r)/(2*C1.r*dist));

  long double theta2 = acosl((nor + C2.r*C2.r - C1.r * C1.r)/(2*C2.r*dist));
  
  return (theta1 - sinl(theta1+ theta1) *0.5) * C1.r * C1.r + (theta2 - sinl(theta2+theta2) *0.5) * C2.r * C2.r;
}


Polygon convex_hull(Polygon &p)
{
    int n = (int)p.size(), k = 0;
    if (n <= 2)
        return p;
    sort(p.begin(), p.end());
    vector<Point> ch(n * 2);

    for (int i = 0; i < n; ch[k++] = p[i++])
    {
        while (k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0)
            --k;
    }

    for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--])
    {
        while (k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0)
            --k;
    }
    ch.resize(k - 1);
    return ch;
}
double convex_diameter(const Polygon &p)
{
    int n = (int)p.size();
    if (n == 2)
        return abs(p[0] - p[1]);

    int is = 0, js = 0;
    for (int i = 1; i < n; ++i)
    {
        if (imag(p[i]) > imag(p[is]))
            is = i;
        if (imag(p[i]) < imag(p[js]))
            js = i;
    }

    double res = abs(p[is] - p[js]);
    int i, maxi, j, maxj;
    i = maxi = is;
    j = maxj = js;
    do
    {
        if (cross(p[(i + 1) % n] - p[i], p[(j + 1) % n] - p[j]) >= 0)
            j = (j + 1) % n;
        else
            i = (i + 1) % n;
        res = max(res, abs(p[i] - p[j]));
    } while (i != is || j != js);
    return res;
}

Polygon convex_cut(const Polygon &p, const Line l)
{
    Polygon ret;
    for (int i = 0; i < p.size(); ++i)
    {
        Point now = p[i], nxt = p[(i + 1) % p.size()];
        if (ccw(l.a, l.b, now) != -1) //交点が線分l上にあるとき
            ret.push_back(now);
        if (ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0)
        {
            ret.push_back(crosspoint(Line(now, nxt), l));
        }
    }
    return (ret);
}
double closestpair(Points &a, int l, int r){
  if(r-l<=1) return 1e20;
  int mid = (l+r)/2;

  double X = a[mid].real();
  double d = min(closestpair(a, l, mid), closestpair(a, mid, r));
  inplace_merge(a.begin()+l, a.begin()+mid, a.begin()+r, [](const Point& pa, const Point& pb){
    return pa.imag() < pb.imag();
  });

  Points b;
  for(int i=l; i<r; i++){
    if(abs(a[i].real()-X) >= d) continue;
    for(int j=b.size()-1; j>=0; j--){
      if(abs((a[i]-b[j]).imag()) >= d) break;
      d = min(d, abs(a[i]-b[j]));
    }
    b.push_back(a[i]);
  }
  return d;
}

/* 円の交差判定 */
/* verify: http://judge.u-aizu.ac.jp/onlinejudge/finder.jsp?course=CGL date:2020/10/11 */
int intersectionCC(Circle c1, Circle c2){
  if(c1.r > c2.r) swap(c1, c2);
  double d1 = abs(c1.p-c2.p); 
  double d2 = c1.r + c2.r;
  if(d1 > d2) return 4; /* 互いに交点を持たない */
  else if(d1 == d2) return 3; /* 外接する場合 */
  else{
    if(c2.r == c1.r + d1) return 1; /* 内接する場合 */
    else if(c2.r > c1.r + d1) return 0; /* 包含 */
    else return 2; /* 交点を2つ持つ */
  }
}

/* 点集合が反時計回りに与えられる場合のみ */
double Area(Points &g){
  double res = 0;
  int n = g.size();
  REP(i,n){
    res += cross(g[i], g[(i+1)%n]);
  }
  return res/2.0;
}

/* 内接円 */
/* verify: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_B&lang=ja date: 2020/10/11 */
pair<Point, double> incircle_of_a_Triangle(Points &p){

  double a = abs(p[1]-p[2]), b = abs(p[2]-p[0]), c = abs(p[0]-p[1]);
  double s = (a+b+c) / 2.0;
  double S = sqrtl(s*(s-a)*(s-b)*(s-c));
  double r = S/s; 
  
  Point pp = (a*p[0]+b*p[1]+c*p[2])/(a+b+c);
  return make_pair(pp, r);
} 

/* 外接円 */
pair<Point, double> circumscribed_circle_of_a_triangle(Points &p){

  Point m1((p[0]+p[1])/2.0), m2((p[1]+p[2])/2.0);
  Point v((p[1]-p[0]).imag(), (p[0]-p[1]).real()), w((p[1]-p[2]).imag(), (p[2]-p[1]).real());

  Line l1(m1, Point(v+m1)), l2(m2, Point(w+m2));

  Point x = crosspoint(l1, l2);
  double r = abs(x-p[0]);
  return make_pair(x, r);
}

/* ある点pを通る円cの接線 */
Points tangent_to_a_circle(Point p, Circle C){
  Points ps;
  double d = abs(C.p-p);
  if(eq(d,0)){
    ps.push_back(p);
  }else if(d>EPS){
    
    double d2 = sqrt(d*d-C.r*C.r);
    
    long double theta = acosl(d2/d);
    //cout << theta << endl;
    Point pp = C.p - p;
    Point p2 = rotate(-theta, pp);

    Point e = p2/abs(p2);
    Point ppp = e*d2;
    ps.push_back(p + ppp);
    p2 = rotate(theta, pp);
    e = p2/abs(p2);
    ppp = e*d2;
    ps.push_back(p + ppp);
    
  }
  return ps;
}

Lines tangent(Circle C1, Circle C2){
  Lines ls;
  if(C1.r < C2.r) swap(C1, C2);
  double d = norm(C1.p - C2.p);
  if(eq(d, 0)) return ls;
  Point u = (C2.p - C1.p) / sqrt(d);
  Point v = rotate(pi/2, u);

  for(double s: {-1, 1}) {
    double h = (C1.r + s * C2.r) / sqrt(d);
    if(eq(1-h*h, 0)) {
      ls.emplace_back(C1.p + u * C1.r, C1.p + (u+v) * C1.r);
    }else if(1-h*h>0){
      Point uu = u*h, vv = v*sqrt(1-h*h);
      ls.emplace_back(C1.p + (uu+vv) * C1.r, C2.p - (uu+vv) * C2.r * s);
      ls.emplace_back(C1.p + (uu-vv) * C1.r, C2.p - (uu-vv) * C2.r * s);
    }
  }
  return ls;
}
Line bisector(Point a, Point b){
    Point A = (a+b)*Point(0.5, 0); 
    return Line(A, A+(b-a)*Point(0, PI/2));
}

Polygon voronoi_cell(Polygon Q, Points P, int s){
    REP(i,P.size()){
        if(i!=s){
            Q = convex_cut(Q, bisector(P[s], P[i]));
        }
    }
    return Q;
}
Polygon py;
double xans, yans;
using D = double;
double f2(double x, double y) {

  if(contains(py, Point(x, y)) == OUT) {
    double mx = -1e9;
    REP(i,py.size()) {
      mx = max(mx, (-1) * distance(Segment(py[i], py[(i+1)%py.size()]), Point(x, y)));
    }
    return mx;
  }else{
    double mx = 1e9;
    REP(i,py.size()) {
      mx = min(mx, distance(Segment(py[i], py[(i+1)%py.size()]), Point(x, y)));
    }
    return mx;
  }
}
double f(double x) {
  D ymin = -1e5;
  D ymax = 1e5;
  while(ymax-ymin>0.000001) {
    D y1 = (ymin*2 + ymax) / 3;
    D y2 = (ymin + ymax*2) / 3;
    if(f2(x, y1) < f2(x, y2)) {
      ymin = y1;
      yans = y2;
    }else{
      ymax = y2;
      yans = y1;
    }
  }
  return f2(x, yans);
}
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  
  int n;
  while(cin >> n, n) {
    py.clear();
    xans = 0;
    yans = 0;
  REP(i,n) {
    Point p; cin >> p;
    py.push_back(p);
  }

  double xmin = -1e5;
  double xmax = 1e5;
  while(xmax-xmin>0.000001) {
    double x1 = (xmin*2 + xmax) / 3;
    double x2 = (xmin + xmax*2) / 3;
    if(f(x1) < f(x2)) {
      xmin = x1;
      xans = x2;
    }else{
      xmax = x2;
      xans = x1;
    }
  }
  double ans = 1e9;
    REP(i,py.size()) {
      ans = min(ans, distance(Segment(py[i], py[(i+1)%n]), Point(xans, yans)));
    }
    cout << ans << '\n';
  }
  return 0;
}
accuracy: 1
time_ms: 390
memory_kb: 3524
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

namespace geometry {
using Real = double;
constexpr Real EPS = 1e-8;
constexpr Real PI = 3.14159265358979323846L;

inline int sgn(Real x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }

inline int compare(Real a, Real b) { return sgn(a - b); }

inline bool equals(Real a, Real b) { return compare(a, b) == 0; }

struct Point {
    Real x, y;

    Point() {}

    Point(Real x, Real y) : x(x), y(y) {}

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

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

    Point& operator*=(const Real& k) {
        x *= k, y *= k;
        return *this;
    }

    Point& operator/=(const Real& k) {
        x /= k, y /= k;
        return *this;
    }

    Point operator+(const Point& p) const { return Point(*this) += p; }

    Point operator-(const Point& p) const { return Point(*this) -= p; }

    Point operator*(const Real& k) const { return Point(*this) *= k; }

    Point operator/(const Real& k) const { return Point(*this) /= k; }

    Point operator-() const { return Point(-x, -y); }

    bool operator==(const Point& p) const { return (compare(x, p.x) == 0 && compare(y, p.y) == 0); }

    bool operator!=(const Point& p) const { return !(*this == p); }

    bool operator<(const Point& p) const {
        return compare(x, p.x) < 0 || (compare(x, p.x) == 0 && compare(y, p.y) < 0);
    }

    bool operator>(const Point& p) const {
        return compare(x, p.x) > 0 || (compare(x, p.x) == 0 && compare(y, p.y) > 0);
    }

    friend std::istream& operator>>(std::istream& is, Point& p) { return is >> p.x >> p.y; }

    friend std::ostream& operator<<(std::ostream& os, const Point& p) { return os << p.x << ' ' << p.y; }

    Real norm() const { return x * x + y * y; }

    Real abs() const { return std::hypot(x, y); }

    Real arg() const { return std::atan2(y, x); }

    Point normal() const { return Point(-y, x); }

    Point unit() const { return *this / abs(); }

    Point rotate(Real theta) const {
        return Point(x * std::cos(theta) - y * std::sin(theta), x * std::sin(theta) + y * std::cos(theta));
    }
};

Point polar(const Real& r, const Real& theta) { return Point(cos(theta), sin(theta)) * r; }

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

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

Real distance(const Point& p, const Point& q) { return (p - q).abs(); }

struct Line {
    Point a, b;

    Line() {}

    Line(const Point& a, const Point& b) : a(a), b(b) {}

    Line(const Real& A, const Real& B, const Real& C) {  // Ax + By = c
        if (equals(A, 0)) {
            assert(!equals(B, 0));
            a = Point(0, C / B);
            b = Point(1, C / B);
        } else if (equals(B, 0)) {
            a = Point(C / A, 0);
            b = Point(C / A, 1);
        } else {
            a = Point(0, C / B);
            b = Point(C / A, 0);
        }
    }

    friend std::istream& operator>>(std::istream& is, Line& l) { return is >> l.a >> l.b; }

    friend std::ostream& operator<<(std::ostream& os, const Line& l) { return os << l.a << " to " << l.b; }

    Point diff() const { return b - a; }
};

struct Segment : Line {
    Segment() {}

    Segment(Point a, Point b) : Line(a, b) {}

    Real length() const { return diff().abs(); }
};

Point proj(const Line& l, const Point& p) {
    Point v = l.diff().unit();
    return l.a + v * dot(v, p - l.a);
}

Point refl(const Line& l, const Point& p) {
    Point h = proj(l, p);
    return h + (h - p);
}

bool orthogonal(const Line& l, const Line& m) { return equals(dot(l.diff(), m.diff()), 0); }

bool parallel(const Line& l, const Line& m) { return equals(cross(l.diff(), m.diff()), 0); }

enum Position { COUNTER_CLOCKWISE = +1, CLOCKWISE = -1, ONLINE_BACK = +2, ONLINE_FRONT = -2, ON_SEGMENT = 0 };

Position ccw(const Point& a, Point b, Point c) {
    b -= a, c -= a;
    if (sgn(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sgn(cross(b, c)) == -1) return CLOCKWISE;
    if (sgn(dot(b, c)) == -1) return ONLINE_BACK;
    if (compare(b.norm(), c.norm()) == -1) return ONLINE_FRONT;
    return ON_SEGMENT;
}

bool intersect(const Line& l, const Point& p) { return abs(ccw(l.a, l.b, p)) != 1; }

bool intersect(const Line& l, const Line& m) {
    Real A = cross(l.diff(), m.diff()), B = cross(l.diff(), l.b - m.a);
    if (equals(A, 0) && equals(B, 0)) return true;
    return !parallel(l, m);
}

bool intersect(const Line& l, const Segment& s) {
    return sgn(cross(l.diff(), s.a - l.a)) * sgn(cross(l.diff(), s.b - l.a)) <= 0;
}

bool intersect(const Segment& s, const Point& p) { return ccw(s.a, s.b, p) == ON_SEGMENT; }

bool intersect(const Segment& s, const Segment& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

Real distance(const Line& l, const Point& p) { return distance(p, proj(l, p)); }

Real distance(const Line& l, const Line& m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Line& l, const Segment& s) {
    return intersect(l, s) ? 0 : std::min(distance(l, s.a), distance(l, s.b));
}

Real distance(const Segment& s, const Point& p) {
    Point h = proj(s, p);
    return intersect(s, h) ? distance(p, h) : std::min(distance(p, s.a), distance(p, s.b));
}

Real distance(const Segment& s, const Segment& t) {
    if (intersect(s, t)) return 0;
    return std::min({distance(s, t.a), distance(s, t.b), distance(t, s.a), distance(t, s.b)});
}

Point crosspoint(const Line& l, const Line& m) {
    assert(intersect(l, m));
    Real A = cross(l.diff(), m.diff()), B = cross(l.diff(), l.b - m.a);
    if (equals(A, 0) && equals(B, 0)) return m.a;
    return m.a + m.diff() * B / A;
}

struct Polygon : std::vector<Point> {
    using std::vector<Point>::vector;

    Polygon(int n) : std::vector<Point>(n) {}

    std::vector<Segment> segments() const {
        assert(size() > 1);
        std::vector<Segment> segs;
        for (size_t i = 0; i < size(); i++) segs.emplace_back((*this)[i], (*this)[(i + 1) % size()]);
        return segs;
    }

    Real area() const {
        Real sum = 0;
        for (size_t i = 0; i < size(); i++) sum += cross((*this)[i], (*this)[(i + 1) % size()]);
        return std::abs(sum) / 2;
    }

    bool is_convex(bool accept_on_segment = true) const {
        int n = size();
        for (int i = 0; i < n; i++) {
            if (accept_on_segment) {
                if (ccw((*this)[i], (*this)[(i + 1) % n], (*this)[(i + 2) % n]) == CLOCKWISE) {
                    return false;
                }
            } else {
                if (ccw((*this)[i], (*this)[(i + 1) % n], (*this)[(i + 2) % n]) != COUNTER_CLOCKWISE) {
                    return false;
                }
            }
        }
        return true;
    }
};

Polygon convex_cut(const Polygon& convex, const Line& l) {
    assert(convex.is_convex());
    int n = convex.size();
    Polygon res;
    for (int i = 0; i < n; i++) {
        const Point& cur = convex[i];
        const Point& nxt = convex[(i + 1) % n];
        if (ccw(l.a, l.b, cur) != CLOCKWISE) res.emplace_back(cur);
        if (ccw(l.a, l.b, cur) * ccw(l.a, l.b, nxt) < 0) res.emplace_back(crosspoint(Segment(cur, nxt), l));
    }
    return res;
}

}  // namespace geometry

/**
 * @brief 2 次元幾何ライブラリ
 * @docs docs/geometry/geometry.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

using namespace geometry;

void solve(int n) {
    Polygon P(n);
    for (auto& p : P) cin >> p;

    auto check = [&](double x) {
        Polygon Q = P;
        for (int i = 0; i < n; i++) {
            Point to = P[(i + 1) % n] - P[i];
            Point move = to.normal().unit() * x;
            Segment seg(P[i] + move, P[(i + 1) % n] + move);
            Q = convex_cut(Q, seg);
        }
        return Q.empty();
    };

    double lb = 0, ub = 10000;
    for (int _ = 0; _ < 300; _++) {
        double mid = (lb + ub) / 2;
        (check(mid) ? ub : lb) = mid;
    }

    cout << ub << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    int n;
    while (cin >> n, n) solve(n);
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3496
final_rank: 3

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

#include <algorithm>
#include <cassert>
#include <cmath>
#include <iostream>
#include <tuple>
#include <vector>

namespace geometry {
using Real = double;
constexpr Real EPS = 1e-8;
constexpr Real PI = 3.14159265358979323846L;

inline int sgn(Real x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }

inline int compare(Real a, Real b) { return sgn(a - b); }

inline bool equals(Real a, Real b) { return compare(a, b) == 0; }

struct Point {
    Real x, y;

    Point() {}

    Point(Real x, Real y) : x(x), y(y) {}

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

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

    Point& operator*=(const Real& k) {
        x *= k, y *= k;
        return *this;
    }

    Point& operator/=(const Real& k) {
        x /= k, y /= k;
        return *this;
    }

    Point operator+(const Point& p) const { return Point(*this) += p; }

    Point operator-(const Point& p) const { return Point(*this) -= p; }

    Point operator*(const Real& k) const { return Point(*this) *= k; }

    Point operator/(const Real& k) const { return Point(*this) /= k; }

    Point operator-() const { return Point(-x, -y); }

    bool operator==(const Point& p) const { return (compare(x, p.x) == 0 && compare(y, p.y) == 0); }

    bool operator!=(const Point& p) const { return !(*this == p); }

    bool operator<(const Point& p) const {
        return compare(x, p.x) < 0 || (compare(x, p.x) == 0 && compare(y, p.y) < 0);
    }

    bool operator>(const Point& p) const {
        return compare(x, p.x) > 0 || (compare(x, p.x) == 0 && compare(y, p.y) > 0);
    }

    friend std::istream& operator>>(std::istream& is, Point& p) { return is >> p.x >> p.y; }

    friend std::ostream& operator<<(std::ostream& os, const Point& p) { return os << p.x << ' ' << p.y; }

    Real norm() const { return x * x + y * y; }

    Real abs() const { return std::hypot(x, y); }

    Real arg() const { return std::atan2(y, x); }

    Point normal() const { return Point(-y, x); }

    Point unit() const { return *this / abs(); }

    Point rotate(Real theta) const {
        return Point(x * std::cos(theta) - y * std::sin(theta), x * std::sin(theta) + y * std::cos(theta));
    }
};

Point polar(const Real& r, const Real& theta) { return Point(cos(theta), sin(theta)) * r; }

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

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

Real distance(const Point& p, const Point& q) { return (p - q).abs(); }

struct Line {
    Point a, b;

    Line() {}

    Line(const Point& a, const Point& b) : a(a), b(b) {}

    Line(const Real& A, const Real& B, const Real& C) {  // Ax + By = c
        if (equals(A, 0)) {
            assert(!equals(B, 0));
            a = Point(0, C / B);
            b = Point(1, C / B);
        } else if (equals(B, 0)) {
            a = Point(C / A, 0);
            b = Point(C / A, 1);
        } else {
            a = Point(0, C / B);
            b = Point(C / A, 0);
        }
    }

    friend std::istream& operator>>(std::istream& is, Line& l) { return is >> l.a >> l.b; }

    friend std::ostream& operator<<(std::ostream& os, const Line& l) { return os << l.a << " to " << l.b; }

    Point diff() const { return b - a; }
};

struct Segment : Line {
    Segment() {}

    Segment(Point a, Point b) : Line(a, b) {}

    Real length() const { return diff().abs(); }
};

Point proj(const Line& l, const Point& p) {
    Point v = l.diff().unit();
    return l.a + v * dot(v, p - l.a);
}

Point refl(const Line& l, const Point& p) {
    Point h = proj(l, p);
    return h + (h - p);
}

bool orthogonal(const Line& l, const Line& m) { return equals(dot(l.diff(), m.diff()), 0); }

bool parallel(const Line& l, const Line& m) { return equals(cross(l.diff(), m.diff()), 0); }

enum Position { COUNTER_CLOCKWISE = +1, CLOCKWISE = -1, ONLINE_BACK = +2, ONLINE_FRONT = -2, ON_SEGMENT = 0 };

Position ccw(const Point& a, Point b, Point c) {
    b -= a, c -= a;
    if (sgn(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sgn(cross(b, c)) == -1) return CLOCKWISE;
    if (sgn(dot(b, c)) == -1) return ONLINE_BACK;
    if (compare(b.norm(), c.norm()) == -1) return ONLINE_FRONT;
    return ON_SEGMENT;
}

bool intersect(const Line& l, const Point& p) { return abs(ccw(l.a, l.b, p)) != 1; }

bool intersect(const Line& l, const Line& m) {
    Real A = cross(l.diff(), m.diff()), B = cross(l.diff(), l.b - m.a);
    if (equals(A, 0) && equals(B, 0)) return true;
    return !parallel(l, m);
}

bool intersect(const Line& l, const Segment& s) {
    return sgn(cross(l.diff(), s.a - l.a)) * sgn(cross(l.diff(), s.b - l.a)) <= 0;
}

bool intersect(const Segment& s, const Point& p) { return ccw(s.a, s.b, p) == ON_SEGMENT; }

bool intersect(const Segment& s, const Segment& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

Real distance(const Line& l, const Point& p) { return distance(p, proj(l, p)); }

Real distance(const Line& l, const Line& m) { return intersect(l, m) ? 0 : distance(l, m.a); }

Real distance(const Line& l, const Segment& s) {
    return intersect(l, s) ? 0 : std::min(distance(l, s.a), distance(l, s.b));
}

Real distance(const Segment& s, const Point& p) {
    Point h = proj(s, p);
    return intersect(s, h) ? distance(p, h) : std::min(distance(p, s.a), distance(p, s.b));
}

Real distance(const Segment& s, const Segment& t) {
    if (intersect(s, t)) return 0;
    return std::min({distance(s, t.a), distance(s, t.b), distance(t, s.a), distance(t, s.b)});
}

Point crosspoint(const Line& l, const Line& m) {
    assert(intersect(l, m));
    Real A = cross(l.diff(), m.diff()), B = cross(l.diff(), l.b - m.a);
    if (equals(A, 0) && equals(B, 0)) return m.a;
    return m.a + m.diff() * B / A;
}

struct Circle {
    Point center;
    Real radius;

    Circle() {}

    Circle(const Point& center, const Real& radius) : center(center), radius(radius) {}

    friend std::istream& operator>>(std::istream& is, Circle& c) { return is >> c.center >> c.radius; }

    friend std::ostream& operator<<(std::ostream& os, const Circle& c) { return os << c.center << ' ' << c.radius; }
};

bool intersect(const Circle& c, const Line& l) { return compare(c.radius, distance(l, c.center)) >= 0; }

int intersect(const Circle& c, const Segment& s) {
    Point h = proj(s, c.center);
    if (compare(distance(c.center, h), c.radius) > 0) return 0;
    Real d1 = (c.center - s.a).abs(), d2 = (c.center - s.b).abs();
    if (compare(c.radius, d1) >= 0 && compare(c.radius, d2) >= 0) return 0;
    if (compare(c.radius, d1) * compare(c.radius, d2) < 0) return 1;
    if (sgn(dot(s.a - h, s.b - h)) < 0) return 2;
    return 0;
}

std::vector<Point> crosspoint(const Circle& c, const Line& l) {
    Point h = proj(l, c.center);
    Real d = c.radius * c.radius - (c.center - h).norm();
    if (sgn(d) < 0) return {};
    if (sgn(d) == 0) return {h};
    Point v = l.diff().unit() * sqrt(d);
    return {h - v, h + v};
}

std::vector<Point> crosspoint(const Circle& c, const Segment& s) {
    int num = intersect(c, s);
    if (num == 0) return {};
    auto res = crosspoint(c, Line(s.a, s.b));
    if (num == 2) return res;
    if (sgn(dot(s.a - res[0], s.b - res[0])) > 0) std::swap(res[0], res[1]);
    return {res[0]};
}

// requirement : c != d
std::vector<Point> crosspoint(const Circle& c1, const Circle& c2) {
    Real r1 = c1.radius, r2 = c2.radius;
    if (r1 < r2) return crosspoint(c2, c1);
    Real d = distance(c1.center, c2.center);
    if (compare(d, r1 + r2) > 0 || compare(d, r1 - r2) < 0) return {};
    Real alpha = std::acos((r1 * r1 + d * d - r2 * r2) / (2 * r1 * d));
    Real theta = (c2.center - c1.center).arg();
    Point p = c1.center + polar(r1, theta + alpha);
    Point q = c1.center + polar(r1, theta - alpha);
    if (p == q) return {p};
    return {p, q};
}

Line bisector(const Point& p, const Point& q) {
    Point c = (p + q) * 0.5;
    Point v = (q - p).normal();
    return Line(c - v, c + v);
}

Circle circumcircle(Point a, Point b, const Point& c) {
    Point center = crosspoint(bisector(a, c), bisector(b, c));
    return Circle(center, distance(c, center));
}

std::vector<Point> center_given_radius(const Point& a, const Point& b, const Real& r) {
    Point m = (b - a) * 0.5;
    Real d1 = m.abs();
    if (equals(d1, 0) || d1 > r) return {};
    Real d2 = sqrt(r * r - d1 * d1);
    Point n = m.normal() * d2 / d1;
    Point p = a + m - n, q = a + m + n;
    if (p == q) return {p};
    return {p, q};
}

int count_tangent(const Circle& c1, const Circle& c2) {
    Real r1 = c1.radius, r2 = c2.radius;
    if (r1 < r2) return count_tangent(c2, c1);
    Real d = distance(c1.center, c2.center);
    if (compare(d, r1 + r2) > 0) return 4;
    if (compare(d, r1 + r2) == 0) return 3;
    if (compare(d, r1 - r2) > 0) return 2;
    if (compare(d, r1 - r2) == 0) return 1;
    return 0;
}

std::vector<Point> tangent_to_circle(const Circle& c, const Point& p) {
    return crosspoint(c, Circle(p, sqrt((c.center - p).norm() - c.radius * c.radius)));
}

enum Contain { OUT, ON, IN };

struct Polygon : std::vector<Point> {
    using std::vector<Point>::vector;

    Polygon(int n) : std::vector<Point>(n) {}

    std::vector<Segment> segments() const {
        assert(size() > 1);
        std::vector<Segment> segs;
        for (size_t i = 0; i < size(); i++) segs.emplace_back((*this)[i], (*this)[(i + 1) % size()]);
        return segs;
    }

    Real area() const {
        Real sum = 0;
        for (size_t i = 0; i < size(); i++) sum += cross((*this)[i], (*this)[(i + 1) % size()]);
        return std::abs(sum) / 2;
    }

    bool is_convex(bool accept_on_segment = true) const {
        int n = size();
        for (int i = 0; i < n; i++) {
            if (accept_on_segment) {
                if (ccw((*this)[i], (*this)[(i + 1) % n], (*this)[(i + 2) % n]) == CLOCKWISE) {
                    return false;
                }
            } else {
                if (ccw((*this)[i], (*this)[(i + 1) % n], (*this)[(i + 2) % n]) != COUNTER_CLOCKWISE) {
                    return false;
                }
            }
        }
        return true;
    }
};

Contain contain(const Polygon& P, const Point& p) {
    bool in = false;
    for (size_t i = 0; i < P.size(); i++) {
        if (ccw(P[i], P[(i + 1) % P.size()], p) == ON_SEGMENT) return ON;
        Point a = P[i] - p, b = P[(i + 1) % P.size()] - p;
        if (a.y > b.y) std::swap(a, b);
        if (sgn(a.y) <= 0 && sgn(b.y) > 0 && sgn(cross(a, b)) < 0) in = !in;
    }
    return in ? IN : OUT;
}

Polygon convex_hull(Polygon& P, bool accept_on_segment = false) {
    int n = P.size(), k = 0;
    if (n <= 2) return P;
    std::sort(P.begin(), P.end());
    Polygon ch(n * 2);
    auto check = [&](int i) {
        if (accept_on_segment) return ccw(ch[k - 2], ch[k - 1], P[i]) == CLOCKWISE;
        return ccw(ch[k - 2], ch[k - 1], P[i]) != COUNTER_CLOCKWISE;
    };
    for (int i = 0; i < n; ch[k++] = P[i++]) {
        while (k >= 2 && check(i)) {
            k--;
        }
    }
    for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = P[i--]) {
        while (k >= t && check(i)) {
            k--;
        }
    }
    ch.resize(k - 1);
    int start = 0;
    for (int i = 1; i < k - 1; i++) {
        if (equals(ch[i].y, ch[start].y) ? ch[i].x < ch[start].x : ch[i].y < ch[start].y) {
            start = i;
        }
    }
    std::rotate(ch.begin(), ch.begin() + start, ch.end());
    return ch;
}

std::tuple<int, int, Real> convex_diameter(const Polygon& convex) {
    assert(convex.is_convex());
    int n = convex.size();
    Real max_dist = -1;
    std::pair<int, int> argmax = {-1, -1};
    for (int i = 0, j = 0; i < n; i++) {
        while (j + 1 < n && distance(convex[i], convex[j + 1]) > distance(convex[i], convex[j])) j++;
        double cur_dist = distance(convex[i], convex[j]);
        if (max_dist < cur_dist) {
            max_dist = cur_dist;
            argmax = {i, j};
        }
    }
    return {argmax.first, argmax.second, max_dist};
}

Polygon convex_cut(const Polygon& convex, const Line& l) {
    assert(convex.is_convex());
    int n = convex.size();
    Polygon res;
    for (int i = 0; i < n; i++) {
        const Point& cur = convex[i];
        const Point& nxt = convex[(i + 1) % n];
        if (ccw(l.a, l.b, cur) != CLOCKWISE) res.emplace_back(cur);
        if (ccw(l.a, l.b, cur) * ccw(l.a, l.b, nxt) < 0) res.emplace_back(crosspoint(Segment(cur, nxt), l));
    }
    return res;
}

Polygon voronoi(const Polygon& P, const std::vector<Point>& ps, size_t idx) {
    Polygon res = P;
    for (size_t i = 0; i < ps.size(); i++) {
        if (i == idx) continue;
        res = convex_cut(res, bisector(ps[idx], ps[i]));
    }
    return res;
}

}  // namespace geometry

/**
 * @brief 2 次元幾何ライブラリ
 * @docs docs/geometry/geometry.md
 */

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

using namespace geometry;

void solve(int n) {
    Polygon P(n);
    for (auto& p : P) cin >> p;

    auto check = [&](double x) {
        Polygon Q = P;
        for (int i = 0; i < n; i++) {
            Point to = P[(i + 1) % n] - P[i];
            Point move = to.normal().unit() * x;
            Segment seg(P[i] + move, P[(i + 1) % n] + move);
            Q = convex_cut(Q, seg);
        }
        return Q.empty();
    };

    double lb = 0, ub = 10000;
    for (int _ = 0; _ < 300; _++) {
        double mid = (lb + ub) / 2;
        (check(mid) ? ub : lb) = mid;
    }

    cout << ub << '\n';
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    int n;
    while (cin >> n, n) solve(n);
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3536
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

//geometry library by maine

//basic
using Real = double;
using Point = complex<Real>;
#define x real()
#define y imag()
const Real EPS = 1e-7, PI = acos(-1), INF = 1e10;

istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, Point p) {
    return os << fixed << setprecision(10) << p.x << " " << p.y;
}

Point operator*(const Point& p, const Real& d) { return Point(p.x * d, p.y * d); }

bool eq(const Real& r, const Real& s) { return abs(r - s) < EPS; }
bool eq(const Point& p, const Point& q) { return abs(p - q) < EPS; }

namespace std {
bool operator<(const Point& a, const Point& b) {
    return !eq(a.x, b.x) ? a.x < b.x : a.y < b.y;
}
}  // namespace std

Real get_angle(const Point& a, const Point& b, const Point& c) {
    return arg((c - a) / (b - a));
}

inline int inc(int i, int N) {
    return (i == N - 1 ? 0 : i + 1);
}
inline int dec(int i, int N) {
    return (i == 0 ? N - 1 : i - 1);
}

//unit vector
Point e(const Point& p) { return p / abs(p); }

//angle transformation
Real radian_to_degree(Real r) { return r * 180.0 / PI; }
Real degree_to_radian(Real d) { return d * PI / 180.0; }

//basic functions
Real dot(const Point& p, const Point& q) { return p.x * q.x + p.y * q.y; }
Real cross(const Point& p, const Point& q) { return p.x * q.y - p.y * q.x; }
Point rotate(const Real& theta, const Point& p) {
    return {cos(theta) * p.x - sin(theta) * p.y, sin(theta) * p.x + cos(theta) * p.y};
}
Point rotate90(const Point& p) {
    return {-p.y, p.x};
}

//structs : Line, Segment, Circle
struct Line {
    Point a, b;
    Line() = default;
    Line(Point a, Point b) : a(a), b(b) {}
    Point d() const { return e(b - a); }  //direction vector
    Point n() const {
        Point dd = d();
        return {dd.y, -dd.x};
    }  //normal vector
};
struct Segment : Line {
    Segment() = default;
    Segment(Point a, Point b) : Line(a, b) {}
};
struct Circle {
    Point p;
    Real r;
    Circle() = default;
    Circle(Point p, Real r) : p(p), r(r){};
};
using Points = vector<Point>;
using Polygon = vector<Point>;
using Polygons = vector<Polygon>;
using Lines = vector<Line>;
using Segments = vector<Segment>;
using Circles = vector<Circle>;

//happy functions
//https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C
int ccw(const Point& a, const Point& bb, const Point& cc) {
    Point b = bb - a, c = cc - a;
    if (cross(b, c) > EPS)
        return 1;  //COUNTER_CLOCKWISE
    if (cross(b, c) < -EPS)
        return -1;  //CLOCKWISE
    if (dot(b, c) < 0)
        return 2;  //ONLINE_BACK  c-a-b
    if (norm(b) < norm(c))
        return -2;  //ONLINE_FRONT a-b-c
    return 0;       //ON_SEGMENT   a-c-b
}

bool parallel(const Line& l, const Line& m) { return eq(cross(l.d(), m.d()), 0.0); }
bool orthogonal(const Line& l, const Line& m) { return eq(dot(l.d(), m.d()), 0.0); }
Point projection(const Line& l, const Point& p) { return l.a + (l.a - l.b) * (dot(p - l.a, l.a - l.b) / norm(l.a - l.b)); }
Point reflection(const Line& l, const Point& p) { return p + (projection(l, p) - p) * 2.0; }

//intersect
bool intersect(const Line& l, const Point& p) { return abs(ccw(l.a, l.b, p)) != 1; }
bool intersect(const Line& l, const Line& m) { return !parallel(l, m) || (parallel(l, m) && intersect(l, m.a)); }
bool intersect(const Segment& s, const Point& p) { return ccw(s.a, s.b, p) == 0; }
bool intersect(const Line& l, const Segment& s) { return cross(l.d(), s.a - l.a) * cross(l.d(), s.b - l.a) < EPS; }
bool intersect(const Segment& s, const Segment& t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}
bool intersect_onsegment(const Segment& s, const Point& p) { return intersect(s, p) && !eq(s.a, p) && !eq(s.b, p); }

//distance
Real distance(const Point& p, const Point& q) { return abs(p - q); }
Real distance(const Line& l, const Point& p) { return distance(p, projection(l, p)); }
Real distance(const Line& l, const Line& m) { return intersect(l, m) ? 0 : distance(l, m.a); }
Real distance(const Segment& s, const Point& p) {
    Point q = projection(s, p);
    return intersect(s, q) ? distance(p, q) : min(distance(s.a, p), distance(s.b, p));
}
Real distance(const Segment& s, const Segment& t) { return intersect(s, t) ? 0 : min({distance(s, t.a), distance(s, t.b), distance(t, s.a), distance(t, s.b)}); }
Real distance(const Line& l, const Segment& s) { return intersect(l, s) ? 0 : min(distance(l, s.a), distance(l, s.b)); }

//intersect circle
bool intersect(const Circle& c, const Point& p) { return eq(distance(c.p, p), c.r); }
bool intersect(const Circle& c, const Line& l) { return distance(l, c.p) <= c.r + EPS; }
int intersect(const Circle& c, const Segment& s) {
    if (!intersect(c, Line(s)))
        return 0;
    Real da = distance(c.p, s.a), db = distance(c.p, s.b);
    if (da < c.r + EPS && db < c.r + EPS)
        return 0;
    if (da > db)
        swap(da, db);
    if (da < c.r - EPS && db > c.r + EPS)
        return 1;
    if (intersect(s, projection(s, c.p)))
        return 2;
    return 0;
}
int intersect(Circle c1, Circle c2) {
    if (c1.r < c2.r)
        swap(c1, c2);
    Real d = distance(c1.p, c2.p);
    if (c1.r + c2.r < d)
        return 4;
    if (eq(c1.r + c2.r, d))
        return 3;
    if (c1.r - c2.r < d)
        return 2;
    if (eq(c1.r - c2.r, d))
        return 1;
    return 0;
}

//crosspoint
Point crosspoint(const Line& l, const Line& m) {
    Real A = cross(l.b - l.a, m.b - m.a);
    Real B = cross(l.b - l.a, l.b - m.a);
    if (eq(abs(A), 0.0) && eq(abs(B), 0.0))
        return m.a;
    return m.a + (m.b - m.a) * B / A;
}
Point crosspoint(const Segment& s, const Segment& t) { return crosspoint(Line(s), Line(t)); }
pair<Point, Point> crosspoint(const Circle& c, const Line& l) {
    Point p = projection(l, c.p);
    if (eq(distance(l, c.p), c.r))
        return {p, p};
    Real len = sqrt(c.r * c.r - norm(p - c.p));
    return {p - len * l.d(), p + len * l.d()};
}
pair<Point, Point> crosspoint(const Circle& c, const Segment& s) {
    Line l(s);
    if (intersect(c, s) == 2)
        return crosspoint(c, l);
    auto ret = crosspoint(c, l);
    if (dot(s.a - ret.first, s.b - ret.first) < 0)
        ret.second = ret.first;
    else
        ret.first = ret.second;
    return ret;
}
pair<Point, Point> crosspoint(const Circle& c1, const Circle& c2) {
    Real d = distance(c1.p, c2.p);
    Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    Real t = atan2(c2.p.y - c1.p.y, c2.p.x - c1.p.x);
    Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
    Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
    return {p1, p2};
}

//tangent
pair<Point, Point> tangent(const Circle& c, const Point& p) {
    return crosspoint(c, Circle(p, sqrt(norm(c.p - p) - c.r * c.r)));
}
Lines tangent(Circle c1, Circle c2) {
    Lines ret;
    if (c1.r < c2.r)
        swap(c1, c2);
    if (eq(c1.p, c2.p))
        return ret;
    Real g = norm(c1.p - c2.p);
    Point u = (c2.p - c1.p) / sqrt(g);
    Point v = rotate(PI / 2, u);
    for (int s : {-1, 1}) {
        Real h = (c1.r + s * c2.r) / sqrt(g);
        if (eq(1 - h * h, 0)) {
            ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
        } else if (1 - h * h > 0) {
            Point uu = u * h, vv = v * sqrt(1 - h * h);
            ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
            ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
        }
    }
    return ret;
}

//convex
//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/3/CGL_3_B
bool is_convex(const Polygon& P) {
    int N = (int)P.size();
    for (int i = 0; i < N; i++) {
        if (ccw(P[i], P[(i + 1) % N], P[(i + 2) % N]) == -1)
            return false;
    }
    return true;
}
//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/4/CGL_4_A
Polygon convex_hull(Points P) {
    int N = (int)P.size(), k = 0;
    if (N <= 2)
        return P;
    sort(begin(P), end(P));
    Points ret(2 * N);
    for (int i = 0; i < N; ret[k++] = P[i++]) {
        while (k >= 2 && cross(ret[k - 1] - ret[k - 2], P[i] - ret[k - 1]) < EPS)
            --k;
    }
    for (int i = N - 2, t = k + 1; i >= 0; ret[k++] = P[i--]) {
        while (k >= t && cross(ret[k - 1] - ret[k - 2], P[i] - ret[k - 1]) < EPS)
            --k;
    }
    ret.resize(k - 1);
    return ret;
}
//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/4/CGL_4_B
Real convex_diameter(const Polygon& P) {
    int N = (int)P.size();
    int is = 0, js = 0;
    for (int i = 1; i < N; i++) {
        if (P[i].y < P[is].y)
            is = i;
        if (P[i].y > P[js].y)
            js = i;
    }
    Real maxdist = norm(P[is] - P[js]);
    int maxi, maxj, i, j;
    maxi = i = is;
    maxj = j = js;
    do {
        if (cross(P[inc(i, N)] - P[i], P[inc(j, N)] - P[j]) >= 0)
            j = inc(j, N);
        else
            i = inc(i, N);
        if (norm(P[i] - P[j]) > maxdist) {
            maxdist = norm(P[i] - P[j]);
            maxi = i;
            maxj = j;
        }
    } while (i != is || j != js);
    maxi = maxi;
    maxj = maxj;
    return sqrt(maxdist);
}
//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/4/CGL_4_C
Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon ret;
    int N = (int)P.size();
    for (int i = 0; i < N; i++) {
        Point now = P[i], nxt = P[(inc(i, N))];
        if (ccw(l.a, l.b, now) != -1)
            ret.emplace_back(now);
        if (ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) == -1)
            ret.emplace_back(crosspoint(Line(now, nxt), l));
    }
    return ret;
}

//other
enum
{
    OUT,
    ON,
    IN
};

//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/3/CGL_3_C
int contains(const Polygon& Q, const Point& p) {
    bool in = false;
    int N = (int)Q.size();
    for (int i = 0; i < N; i++) {
        Point a = Q[i] - p, b = Q[(i + 1) % N] - p;
        if (a.y > b.y)
            swap(a, b);
        if (a.y <= 0 && 0 < b.y && cross(a, b) < 0)
            in = !in;
        if (cross(a, b) == 0 && dot(a, b) <= 0)
            return ON;
    }
    return in ? IN : OUT;
}

//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/3/CGL_3_A
Real area(const Polygon& P) {
    Real A = 0;
    for (int i = 0; i < (int)P.size(); i++) {
        A += cross(P[i], P[(i + 1) % P.size()]);
    }
    return A * 0.5;
}

//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/7/CGL_7_H
Real cross_area(const Circle& c, const Point& a, const Point& b) {
    Point va = c.p - a, vb = c.p - b;
    Real f = cross(va, vb), ret = 0.0;
    if (eq(f, 0.0))
        return ret;
    if (max(abs(va), abs(vb)) < c.r + EPS)
        return f;
    if (distance(Segment(a, b), c.p) > c.r - EPS)
        return c.r * c.r * arg(vb * conj(va));
    auto u = crosspoint(c, Segment(a, b));
    vector<Point> V{a, u.first, u.second, b};
    for (int i = 0; i < (int)V.size() - 1; i++) {
        ret += cross_area(c, V[i], V[i + 1]);
    }
    return ret;
}
Real area(const Polygon& p, const Circle& c) {
    int N = (int)p.size();
    if (N < 3)
        return 0.0;
    Real ret = 0;
    for (int i = 0; i < N; i++) {
        ret += cross_area(c, p[i], p[inc(i, N)]);
    }
    return ret / 2.0;
}

//https://onlinejudge.u-aizu.ac.jp/problems/CGL_5_A
Real closest_pair(Points& P, int left, int right) {
    if (right - left <= 1)
        return 1e18;
    int mid = (left + right) / 2;
    Real xx = P[mid].x;
    Real dist = min(closest_pair(P, left, mid), closest_pair(P, mid, right));
    inplace_merge(P.begin() + left, P.begin() + mid, P.begin() + right, [&](const Point& a, const Point& b) { return a.y < b.y; });
    Points memo;
    memo.reserve(right - left);
    for (int i = left; i < right; i++) {
        if (abs(P[i].x - xx) >= dist)
            continue;
        for (int j = (int)memo.size() - 1; j >= 0; j--) {
            if (P[i].y - memo[j].y >= dist)
                break;
            dist = min(dist, distance(P[i], memo[j]));
        }
        memo.emplace_back(P[i]);
    }
    return dist;
}
Real closest_pair(Points P) {
    sort(begin(P), end(P));
    return closest_pair(P, 0, (int)P.size());
}

//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/7/CGL_7_B
Circle incircle(Polygon P) {
    assert((int)P.size() == 3);
    Real l0 = distance(P[1], P[2]), l1 = distance(P[0], P[2]), l2 = distance(P[0], P[1]);
    Circle c;
    c.p = crosspoint(Line(P[0], (P[1] * l1 + P[2] * l2) / (l1 + l2)), Line(P[1], (P[0] * l0 + P[2] * l2) / (l0 + l2)));
    c.r = distance(Line(P[0], P[1]), c.p);
    return c;
}

//https://onlinejudge.u-aizu.ac.jp/courses/library/4/CGL/7/CGL_7_C
Circle circumcircle(Polygon P) {
    assert((int)P.size() == 3);
    Circle c;
    c.p = crosspoint(Line((P[0] + P[1]) / 2.0, (P[0] + P[1]) / 2.0 + rotate90(P[0] - P[1])),
        Line((P[0] + P[2]) / 2.0, (P[0] + P[2]) / 2.0 + rotate90(P[0] - P[2])));
    c.r = distance(c.p, P[0]);
    return c;
}

int main() {
    int N;
    while (cin >> N, N) {
        Polygon P(N);
        for (auto&& p : P) {
            cin >> p;
        }
        double ans = 0;
        for (int i = 0; i < N; i++) {
            for (int j = inc(i, N); j != i; j = inc(j, N)) {
                for (int k = inc(j, N); k != i; k = inc(k, N)) {
                    Line l{P[i], P[inc(i, N)]}, m{P[j], P[inc(j, N)]}, n{P[k], P[inc(k, N)]};
                    auto check = [&](Circle C) {
                        if (contains(P, C.p)) {
                            for (int q = 0; q < N; q++) {
                                Line w{P[q], P[inc(q, N)]};
                                if (C.r > distance(w, C.p) + EPS) {
                                    return false;
                                }
                            }
                            return true;
                        }
                        return false;
                    };
                    if (intersect(l, m) && intersect(m, n) && intersect(l, n)) {
                        Polygon Tri = {crosspoint(l, m), crosspoint(m, n), crosspoint(n, l)};
                        Circle C = incircle(Tri);
                        if (check(C))
                            ans = max(ans, C.r);
                    }
                    if (parallel(l, n)) {
                        Line mid{(l.a + n.b) / 2.0, (l.b + n.a) / 2.0};
                        Circle C;
                        C.r = distance(l, n) / 2.0;
                        for (int _ = -1; _ <= 1; _ += 2) {
                            C.p = crosspoint(mid, Line{m.a + m.n() * C.r * _, m.b + m.n() * C.r * _});
                            if (check(C))
                                ans = max(ans, C.r);
                        }
                    }
                }
            }
        }
        cout << fixed << setprecision(6) << ans << endl;
    }
}
accuracy: 1
time_ms: 830
memory_kb: 3600
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

namespace std {
bool operator<(const complex<long double> &a, const complex<long double> &b);
bool operator==(const complex<long double> &a, const complex<long double> &b);
bool cmp_y(const complex<long double> &a, const complex<long double> &b);
} // namespace std

namespace Geometry {
using R = long double; // Rにmint渡せるようにする
using P = complex<R>;
using L = pair<P, P>;
using G = vector<P>;
struct C {
    P c;
    R r;
    C() {}
    C(const P &a, const R &b) : c(a), r(b) {}
};
struct S : public L {
    S() {}
    S(const P &a, const P &b) : L(a, b) {}
};
const R EPS = 1e-8;
const R PI = atan(1) * 4;

inline int sgn(const R &r) { return (r > EPS) - (r < -EPS); }
inline R dot(const P &a, const P &b) {
    return real(a) * real(b) + imag(a) * imag(b);
}
inline R det(const P &a, const P &b) {
    return real(a) * imag(b) - imag(a) * real(b);
}
inline P rotate(const P &p, const R &arg) {
    return P(cos(arg) * p.real() - sin(arg) * p.imag(),
             sin(arg) * p.real() + cos(arg) * p.imag());
}
inline P vec(const L &l) { return l.second - l.first; }

// P,L,Sについて入力
inline istream &operator>>(istream &is, P &p) {
    R x, y;
    is >> x >> y;
    p = P(x, y);
    return is;
}
inline istream &operator>>(istream &is, L &l) {
    P a, b;
    is >> a >> b;
    l = L(a, b);
    return is;
}
inline istream &operator>>(istream &is, S &s) {
    P a, b;
    is >> a >> b;
    s = S(a, b);
    return is;
}

// 線分abから見たcの位置
enum CCW { LEFT = 1, RIGHT = 2, BACK = 4, FRONT = 8, ON_SEG = 16 };
int ccw(P a, P b, P c) {
    P p = (c - a) / (b - a);
    if (sgn(imag(p)) > 0)
        return LEFT;
    if (sgn(imag(p)) < 0)
        return RIGHT;
    if (sgn(real(p)) < 0)
        return BACK;
    if (sgn(real(p) - 1) > 0)
        return FRONT;
    return ON_SEG;
}

// 射影
P inline projection(const L &l, const P &p) {
    R t = dot(p - l.first, l.first - l.second) / norm(l.first - l.second);
    return l.first + t * (l.first - l.second);
}
// 反射
P inline reflection(const L &l, const P &p) {
    return p + (R)2 * (projection(l, p) - p);
}

// 垂直,平行
inline bool vertical(L a, L b) { return sgn(dot(vec(a), vec(b))) == 0; }
inline bool parallel(L a, L b) { return sgn(det(vec(a), vec(b))) == 0; }

// 交差判定
template <bool strict = false> inline bool intersect(const L &l1, const L &l2) {
    if (strict)
        return sgn(det(vec(l1), vec(l2))) != 0;
    return sgn(det(vec(l1), vec(l2))) != 0 || l1 == l2;
}
template <bool strict = false> inline bool intersect(const L &l, const S &s) {
    if (strict)
        det(s.first, vec(l)) * det(s.second, vec(l)) < 0;
    return det(s.first, vec(l)) * det(s.second, vec(l)) <= 0;
}
template <bool strict = false> inline bool intersect(const S &s1, const S &s2) {
    int ccw1 = ccw(s1.first, s1.second, s2.first) |
               ccw(s1.first, s1.second, s2.second);
    int ccw2 = ccw(s2.first, s2.second, s1.first) |
               ccw(s2.first, s2.second, s1.second);
    if (strict)
        return (ccw1 & ccw2) == (LEFT | RIGHT);
    return (ccw1 & ccw2) == (LEFT | RIGHT) || ((ccw1 | ccw2) & ON_SEG);
}
template <bool strict = false> inline bool intersect(const S &s, const P &p) {
    return ccw(s.first, s.second, p) == ON_SEG;
}
template <bool strict = false> inline bool intersect(const L &l, const P &p) {
    return ccw(l.first, l.second, p) == ON_SEG ||
           ccw(l.first, l.second, p) == FRONT ||
           ccw(l.first, l.second, p) == BACK;
}

// 距離
R dist(const S &s, const P &p) {
    P q = projection(s, p);
    if (sgn(dot(s.second - s.first, p - s.first)) <= 0)
        q = s.first;
    if (sgn(dot(s.first - s.second, p - s.second)) <= 0)
        q = s.second;
    return abs(p - q);
}
R dist(const S &a, const S &b) {
    if (intersect(a, b))
        return 0;
    return min({dist(a, b.first), dist(a, b.second), dist(b, a.first),
                dist(b, a.second)});
}
R dist(const L &l, const P &p) {
    P q = projection(l, p);
    return abs(p - q);
}

// 交点 交差判定を先にすること!!!
inline P crosspoint(const L &l1, const L &l2) {
    R ratio = det(vec(l2), l2.first - l1.first) / det(vec(l2), vec(l1));
    return l1.first + vec(l1) * ratio;
}

// 凸包 3点が一直線上に並ぶときに注意
// 凸包のうち一番左にある頂点の中で一番下の頂点から時計回り
G convex_hull(G ps) {
    int n = ps.size(), k = 0;
    sort(ps.begin(), ps.end());
    G r(2 * n);
    for (int i = 0; i < n; i++) {
        while (k > 1 && sgn(det(r[k - 1] - r[k - 2], ps[i] - r[k - 2])) < 0)
            k--;
        r[k++] = ps[i];
    }
    for (int i = n - 2, t = k; i >= 0; i--) {
        while (k > t && sgn(det(r[k - 1] - r[k - 2], ps[i] - r[k - 2])) < 0)
            k--;
        r[k++] = ps[i];
    }
    r.resize(k - 1);
    return r;
}

// 凸多角形polを直線lで切断して左側の多角形を返す
G convex_cut(const G &pol, const L &l) {
    G res;
    REP(i, pol.size()) {
        P a = pol[i], b = pol[(i + 1) % pol.size()];
        int da = sgn(det(l.first - a, l.second - a)),
            db = sgn(det(l.first - b, l.second - b));
        // 点aが直線lの左側
        if (da >= 0)
            res.emplace_back(a);
        // 辺(a,b)と直線lが交わる
        if (da * db < 0)
            res.emplace_back(crosspoint(L{a, b}, l));
    }
    return res;
}

// 1直線上に3点が並んでるような部分を消去 O(p.size())
G normalize_poligon(G p) {
    int n = p.size();
    REP(i, p.size()) {
        if (ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]) == ON_SEG) {
            p.erase(p.begin() + i);
            i--;
        }
    }
    return p;
}

// abとacがなす角の二等分線
L bisector_of_angle(P a, P b, P c) {
    b -= a;
    b /= abs(b);
    c -= a;
    c /= abs(c);
    P mid = (b + c) / P(2, 0);
    return L(a, a + mid);
}

// 点a,bの垂直二等分線 O(1)
L bisector(P a, P b) {
    const P mid = (a + b) / P(2, 0);
    return L{mid, mid + (b - a) * P(0, 1)};
}
// 多角形polと点集合vについてボロノイ図を計算
// 点v[s]が属する部分を返す O(pol.size * v.size())
G voronoi_cell(G pol, G v, int s) {
    pol = normalize_poligon(pol);
    REP(i, v.size()) if (i != s) {
        pol = convex_cut(pol, bisector(v[s], v[i]));
    }
    return pol;
}

// 面積 頂点が反時計回りに並んでいること
R area(const G &pol) {
    R ret = 0.0;
    REP(i, pol.size()) ret += det(pol[i], pol[(i + 1) % pol.size()]);
    return (ret / 2.0);
}

// 凸性の判定
bool isConvex(const G &pol) {
    REP(i, pol.size()) {
        if (sgn(det(pol[(i + 1) % pol.size()] - pol[i],
                    pol[(i + 2) % pol.size()] - pol[i])) < 0) {
            return false;
        }
    }
    return true;
}

// 多角形と点の内包
// 2→in 1→on 0→out
int inPolygon(const G &pol, const P &p) {
    bool in = false;
    for (int i = 0; i < pol.size(); ++i) {
        P a = pol[i] - p, b = pol[(i + 1) % pol.size()] - p;
        if (imag(a) > imag(b))
            swap(a, b);
        if (imag(a) <= 0 && 0 < imag(b) && sgn(det(a, b)) < 0) {
            in = !in;
        }
        if (sgn(det(a, b)) == 0 && sgn(dot(a, b)) <= 0)
            return 1;
    }
    return in ? 2 : 0;
}

// 3点が与えられたときに円を求める
// 3点が直線上に並んでいるときは{0, 0, -1}を返す
C calcCircle(R x1, R y1, R x2, R y2, R x3, R y3) {
    R a = x2 - x1, b = y2 - y1, c = x3 - x1, d = y3 - y1;
    if ((sgn(a) && sgn(d)) || (sgn(b) && sgn(c))) {
        R ox = x1 + (d * (a * a + b * b) - b * (c * c + d * d)) /
                        (a * d - b * c) / 2,
          oy;
        if (b)
            oy = (a * (x1 + x2 - ox - ox) + b * (y1 + y2)) / b / 2;
        else
            oy = (c * (x1 + x3 - ox - ox) + d * (y1 + y3)) / d / 2;
        R r1 = sqrt((ox - x1) * (ox - x1) + (oy - y1) * (oy - y1)),
          r2 = sqrt((ox - x2) * (ox - x2) + (oy - y2) * (oy - y2)),
          r3 = sqrt((ox - x3) * (ox - x3) + (oy - y3) * (oy - y3)),
          r = (r1 + r2 + r3) / 3;
        return {P{ox, oy}, r};
    }
    return {P{0, 0}, -1};
}
// 2点p1, p2を通り、半径がrの円を2つ返す
vector<C> calcCircle(P p1, P p2, R r) {
    if (abs(p1 - p2) > 2 * r)
        return {}; // 存在しない
    P p3 = {(p1.real() + p2.real()) / 2, (p1.imag() + p2.imag()) / 2};
    R l = abs(p1 - p3);
    P p1p2 = p2 - p1;
    R a = p1p2.real(), b = p1p2.imag();
    R dx1 = b * sqrt((r * r - l * l) / (a * a + b * b)),
      dy1 = a * sqrt((r * r - l * l) / (a * a + b * b));
    return {{{p3.real() + dx1, p3.imag() - dy1}, r},
            {{p3.real() - dx1, p3.imag() + dy1}, r}};
}

// 交差
int intersect(const C &c, const L &l) {
    R d = dist(l, c.c);
    if (sgn(c.r - d) > 0)
        return 2; // 交差している
    else if (sgn(c.r - d) == 0)
        return 1; // 接している
    return 0;     // 交差しない
}
int intersect(const C &a, const C &b) {
    R dist = norm(a.c - b.c), r1 = (a.r + b.r) * (a.r + b.r),
      r2 = (a.r - b.r) * (a.r - b.r);
    if (sgn(r1 - dist) < 0)
        return 4; // 円が離れている
    if (sgn(r1 - dist) == 0)
        return 3; // 外接
    if (sgn(r2 - dist) < 0 && sgn(dist - r1) < 0)
        return 2; // 交差
    if (sgn(dist - r2) == 0)
        return 1; // 内接
    return 0;     // 内部に含む
}

// 交点 交差の確認を先にすること！！！
vector<P> crosspoint(C c, L l) {
    R d = dist(l, c.c), r = c.r;
    P m = projection(l, c.c);
    P x = sqrt(r * r - d * d) * vec(l) / abs(vec(l));
    vector<P> ret(2, m);
    ret[0] -= x;
    ret[1] += x;

    if (ret[1] < ret[0])
        swap(ret[0], ret[1]);
    return ret;
}
// intersect=2 を確認すること
vector<P> crosspoint(C a, C b) {
    R d = abs(a.c - b.c);
    R t = (a.r * a.r - b.r * b.r + d * d) / 2 / d, h = sqrt(a.r * a.r - t * t);
    P m = t / abs(b.c - a.c) * (b.c - a.c) + a.c;
    P n(-(a.c - b.c).imag() / abs(a.c - b.c),
        (a.c - b.c).real() / abs(a.c - b.c));
    vector<P> ret(2, m);
    ret[0] -= h * n;
    ret[1] += h * n;
    return ret;
}

// 点aを通る接線を返す
// pl = ((a, 接線と円の交点), (a, 接線と円の交点))
pair<L, L> tangent(C c, P a) {
    pair<L, L> pl;
    if (sgn(abs(a - c.c) - c.r) == 0) { // 点aが円周上にあるとき 要verify
        auto normal = [](P a) {
            L vp({a * P(0, 1), a * P(0, -1)});
            return vp;
        };
        L l = normal(a - c.c); // 法線ベクトル
        l.first = a;
        l.second += a;
        pl.first = pl.second = l;
    } else if (sgn(abs(a - c.c) - c.r) > 0) { // 点aが円の外側にあるとき
        R xp = a.real() - c.c.real();
        R yp = a.imag() - c.c.imag();
        R A = sqrt(xp * xp + yp * yp - c.r * c.r);
        R B = xp * xp + yp * yp;
        P p1(c.r * (xp * c.r + yp * A) / B, c.r * (yp * c.r - xp * A) / B);
        P p2(c.r * (xp * c.r - yp * A) / B, c.r * (yp * c.r + xp * A) / B);
        pl = make_pair(L(a, p1 + c.c), L(a, p2 + c.c));
    } else { // 点 a が円の内側にあるとき
        pl.first = pl.second = L(P(INF, INF), P(INF, INF));
    }
    return pl;
}

// 2つの円の共通接線の計算に使用
// flag=true のとき内接線, falseのとき外接線
L common_tangent(const C &c1, const C &c2, bool flag) {
    R xp = c2.c.real() - c1.c.real();
    R yp = c2.c.imag() - c1.c.imag();
    R r = flag ? c1.r + c2.r : c1.r - c2.r;
    R A = sqrt(xp * xp + yp * yp - r * r);
    R B = xp * xp + yp * yp;
    P p1(c1.r * (xp * r + yp * A) / B, c1.r * (yp * r - xp * A) / B);
    P p2(c1.r * (xp * r - yp * A) / B, c1.r * (yp * r + xp * A) / B);
    p1 += c1.c;
    p2 += c1.c;
    return L(p1, p2);
}
// 2円の共通接線を返す
// vl = {(c1の接点, c2の接点), …, (c1の接点, c2の接点)}
vector<L> common_tangent(C c1, C c2) {
    vector<L> vl;
    int pos = intersect(c1, c2);
    // 2つの共通内接線を求める
    L pp1 = common_tangent(c1, c2, true);
    L pp2 = common_tangent(c2, c1, true);
    if (pos == 4) { // 2つの円が離れているとき
        vl.push_back(L(pp1.first, pp2.first));
        vl.push_back(L(pp1.second, pp2.second));
    } else if (pos == 3) { // 外接するとき
        vl.push_back(tangent(c1, pp1.first).first);
    }
    // 2つの共通外接線を求める
    pp1 = common_tangent(c1, c2, false);
    pp2 = common_tangent(c2, c1, false);
    if (pos >= 2) { // 2つの円が交わるとき
        vl.push_back(L(pp1.first, pp2.second));
        vl.push_back(L(pp1.second, pp2.first));
    } else if (pos == 1) { // 2つの円が内接するとき
        vl.push_back(tangent(c1, pp1.first).first);
    }
    return vl;
}

// 2円の共通面積を求める
// https://ferin-tech.hatenablog.com/entry/2020/03/15/220024
R common_area(C c1, C c2) {
    ll type = intersect(c1, c2);
    if (type >= 3)
        return 0;
    if (type <= 1) {
        ll r = min(c1.r, c2.r);
        return PI * r * r;
    }
    if (c1.r > c2.r)
        swap(c1, c2);
    vector<P> ps = crosspoint(c1, c2);
    R ang1 = acosl(dot(ps[0] - c1.c, ps[1] - c1.c) / (c1.r * c1.r));
    R ang2 = acosl(dot(ps[0] - c2.c, ps[1] - c2.c) / (c2.r * c2.r));
    if (ccw(ps[0], ps[1], c1.c) == ccw(ps[0], ps[1], c2.c))
        ang1 = max(ang1, 2 * PI - ang1);
    else
        ang1 = min(ang1, 2 * PI - ang1);
    ang2 = min(ang2, 2 * PI - ang2);
    return c1.r * c1.r * 0.5 * (ang1 - sinl(ang1)) +
           c2.r * c2.r * 0.5 * (ang2 - sinl(ang2));
}
} // namespace Geometry

namespace std {
bool operator<(const Geometry::P &a, const Geometry::P &b) {
    return Geometry::sgn(real(a - b)) ? real(a - b) < 0
                                      : Geometry::sgn(imag(a - b)) < 0;
}
bool operator==(const Geometry::P &a, const Geometry::P &b) {
    return Geometry::sgn(real(a - b)) == 0 && Geometry::sgn(imag(a - b)) == 0;
}
bool cmp_y(const Geometry::P &a, const Geometry::P &b) {
    return Geometry::sgn(imag(a - b)) ? imag(a - b) < 0
                                      : Geometry::sgn(real(a - b)) < 0;
}
} // namespace std

int main() {
    while (1) {
        int n;
        cin >> n;
        if (n == 0)
            break;
        Geometry::G poly;
        for (int i = 0; i < n; i++) {
            int x, y;
            cin >> x >> y;
            poly.emplace_back(x, y);
        }
        double l = 0, r = 10000;
        for (int i = 0; i < 200; i++) {
            double mid = (l + r) / 2;
            Geometry::G tmp = poly;
            for (int j = 0; j < n; j++) {
                Geometry::P v = poly[(j + 1) % n] - poly[j];
                v /= abs(v);
                v = Geometry::rotate(v, Geometry::PI / 2);
                Geometry::L l =
                    Geometry::L(poly[j] + v * Geometry::P(mid, 0),
                                poly[(j + 1) % n] + v * Geometry::P(mid, 0));
                tmp = Geometry::convex_cut(tmp, l);
            }
            if (tmp.size() > 0)
                l = mid;
            else
                r = mid;
        }
        cout << fixed << setprecision(6) << l << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 3584
final_rank: 8

code_snippet: #include<cstdio>
#include<vector>
#include<complex>
using namespace std;

using C = complex<double>;
#define cx real()
#define cy imag()
constexpr double EPS = 1e-6;

int n, x, y;
C c[101];

double dot(C a, C b) {
  return a.cx * a.cy + b.cx * b.cy;
}
double det(C a, C b) {
  return a.cx * b.cy - a.cy * b.cx;
}

double distance(C a, C b, C x) {
  C d = x - a;
  C e = b - a;
  return abs(det(d, e)) / abs(e);
}

bool isPointOnLineSegment(C a, C b, C c) {
  return abs(a-c) + abs(b-c) <= abs(a-b) + EPS;
}

bool eq(C a, C b) {
  C d = a - b;
  return abs(d.cx) < EPS && abs(d.cy) < EPS;
}

C intersectionLine(C a1, C a2, C b1, C b2) {
  C a = a2 - a1, b = b2 - b1;
  return a1 + a * det(b, b1 - a1) / det(b, a);
}

bool check_point(double len, C x, C from) {
  vector<C> vc;
  for (int i = 0; i < n; i++) {
    if (distance(c[i], c[i+1], x) < len - EPS) return false;
    C tmp = intersectionLine(from, x, c[i], c[i+1]);
    if (isPointOnLineSegment(c[i], c[i+1], tmp)) vc.push_back(tmp);
  }
  for (int i = 0; i < n; i++) {
    for (int j = i+1; j < n; j++) {
      if (isPointOnLineSegment(vc[i], vc[j], x)) return true;
    }
  }
  return false;
}

bool check(double len) {
  for (int i = 0; i < n; i++) {
    for (int j = i+1; j < n; j++) if (abs(det(c[i+1]-c[i], c[j+1]-c[j])) > EPS) {
      C inter = intersectionLine(c[i+1], c[i], c[j+1], c[j]);
      C a = c[i] - inter;
      if (abs(a) <= EPS) a = c[i+1] - inter;
      a /= abs(a);
      C b = c[j] - inter;
      if (abs(b) <= EPS) b = c[j+1] - inter;
      b /= abs(b);
      C x = a + b;
      x /= abs(x);
      C p = x / abs(det(x, b));
      if (check_point(len, inter + p * len, inter)) return true;
    }
  }
  return false;
}

double solve() {
  double lb = 0, ub = 10000;
  while (lb + EPS < ub) {
    double mid = (lb + ub) / 2;
    if (check(mid)) lb = mid;
    else ub = mid;
  }
  return lb;
}

int main() {
  while (scanf("%d", &n), n) {
    for (int i = 0; i < n; i++) scanf("%d%d", &x, &y), c[i] = C(x, y);
    c[n] = c[0];
    printf("%.6lf\n", solve());
  }
}
accuracy: 1
time_ms: 360
memory_kb: 2668
final_rank: 1

code_snippet: #line 1 "a.cpp"
using namespace std;
#line 1 "/home/kotatsugame/library/math/point.cpp"
#define _USE_MATH_DEFINES
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<iomanip>
const double EPS=1e-10;
bool eq(double a,double b){return abs(a-b)<EPS;}
struct Point{
	double x,y;
	Point(double x_=0,double y_=0):x(x_),y(y_){}
	Point operator-()const{return Point(-x,-y);}
	Point operator+(const Point&p)const{return Point(x+p.x,y+p.y);}
	Point operator-(const Point&p)const{return Point(x-p.x,y-p.y);}
	Point operator*(const double k)const{return Point(x*k,y*k);}
	Point operator/(const double k)const{return Point(x/k,y/k);}
	bool operator<(const Point&p)const{return eq(x,p.x)?y<p.y:x<p.x;}
	bool operator==(const Point&p)const{return eq(x,p.x)&&eq(y,p.y);}
};
istream&operator>>(istream&is,Point&p){return is>>p.x>>p.y;}
ostream&operator<<(ostream&os,const Point&p){return os<<fixed<<setprecision(9)<<p.x<<' '<<p.y;}
struct Line{
	Point p1,p2;
	Line(Point p1_=Point(),Point p2_=Point()):p1(p1_),p2(p2_){}
};
struct Segment:Line{
	Segment(Point p1_=Point(),Point p2_=Point()):Line(p1_,p2_){}
};
struct Circle{
	Point o;
	double r;
	Circle(Point o_=Point(),double r_=0):o(o_),r(r_){}
};
using Polygon=vector<Point>;
//function list begin
Point vec(const Line&);
double norm(const Point&);
double norm(const Line&);
double abs(const Point&);
double abs(const Line&);
double arg(const Point&);
double arg(const Line&);
double arg(const Point&,const Point&,const Point&);//a->b->c
int argtype(const Point&);//(-pi,0]->0,(0,pi]->1
bool argless(const Point&,const Point&);//sorting points with arg
double dot(const Point&,const Point&);
double cross(const Point&,const Point&);
Point polar(const double,const double);
Point rotate(const Point&,const double);
enum{ONLINE_FRONT=-2,CLOCKWISE=-1,ON_SEGMENT=0,COUNTER_CLOCKWISE=1,ONLINE_BACK=2};
int ccw(const Point&,const Point&);
int ccw(const Point&,const Point&,const Point&);
int ccw(const Line&,const Point&);
bool orthogonal(const Point&,const Point&);
bool orthogonal(const Line&,const Line&);
bool parallel(const Point&,const Point&);
bool parallel(const Line&,const Line&);
bool intersect(const Line&,const Point&);
bool intersect(const Line&,const Line&);
bool intersect(const Segment&,const Point&);
bool intersect(const Segment&,const Segment&);
bool intersect(const Line&,const Segment&);
bool intersect(const Segment&,const Line&);
bool intersect(const Circle&,const Point&);
int intersect(const Circle&,const Line&);//count contacts
int intersect(const Circle&,const Segment&);//count contacts
bool intersect(const Circle&,const Circle&);
int count_tangent(const Circle&,const Circle&);//count common tangents
double distance(const Point&,const Point&);
double distance(const Line&,const Point&);
double distance(const Line&,const Line&);
double distance(const Segment&,const Point&);
double distance(const Segment&,const Segment&);
double distance(const Line&,const Segment&);
double distance(const Segment&,const Line&);
double distance(const Circle&,const Point&);
double distance(const Circle&,const Line&);
double distance(const Circle&,const Segment&);
double distance(const Circle&,const Circle&);
Point projection(const Line&,const Point&);
Point reflection(const Line&,const Point&);
Point crosspoint(const Line&,const Line&);
pair<Point,Point>crosspoint(const Circle&,const Line&);
pair<Point,Point>crosspoint(const Circle&,const Segment&);
pair<Point,Point>crosspoint(const Circle&,const Circle&);
pair<Point,Point>tangent(const Circle&,const Point&);
vector<Line>tangent(const Circle&,const Circle&);
bool is_convex(const Polygon&);
Polygon convex_hull(Polygon,bool=false);
enum{OUT,ON,IN};
int contain(const Polygon&,const Point&);
int contain(const Circle&,const Point&);
int contain(const Circle&,const Segment&);
Polygon convex_cut(const Polygon&,const Line&);
double diameter(Polygon);
double area(const Polygon&);
double area(const Polygon&,const Line&);
double area(const Polygon&,const Circle&);
//function list end
Point vec(const Line&s){return s.p2-s.p1;}
double norm(const Point&p){return p.x*p.x+p.y*p.y;}
double norm(const Line&s){return norm(vec(s));}
double abs(const Point&p){return hypot(p.x,p.y);}
double abs(const Line&s){return abs(vec(s));}
double arg(const Point&p){return atan2(p.y,p.x);}
double arg(const Line&s){return arg(vec(s));}
double arg(const Point&a,const Point&b,const Point&c){
	double A=arg(b-a),B=arg(c-b);
	double theta=abs(A-B);
	return min(theta,2*M_PI-theta);
}
int argtype(const Point&a)
{
	return a.y<-EPS?0:a.y>EPS?1:a.x<0?1:0;
}
bool argless(const Point&a,const Point&b)
{
	int at=argtype(a),bt=argtype(b);
	return at!=bt?at<bt:ccw(a,b)>0;
}
double dot(const Point&a,const Point&b){return a.x*b.x+a.y*b.y;}
double cross(const Point&a,const Point&b){return a.x*b.y-a.y*b.x;}
Point polar(const double r,const double theta){return Point(cos(theta),sin(theta))*r;}
Point rotate(const Point&p,const double theta){
	return Point(p.x*cos(theta)-p.y*sin(theta),p.x*sin(theta)+p.y*cos(theta));
}
int ccw(const Point&a,const Point&b)
{
	return cross(a,b)>EPS?COUNTER_CLOCKWISE
		:cross(a,b)<-EPS?CLOCKWISE
		:dot(a,b)<0?ONLINE_BACK
		:norm(a)<norm(b)?ONLINE_FRONT
		:ON_SEGMENT;
}
int ccw(const Point&a,const Point&b,const Point&c){return ccw(b-a,c-a);}
int ccw(const Line&s,const Point&p){return ccw(s.p1,s.p2,p);}
bool orthogonal(const Point&a,const Point&b){return eq(dot(a,b),0);}
bool orthogonal(const Line&s,const Line&t){return orthogonal(vec(s),vec(t));}
bool parallel(const Point&a,const Point&b){return eq(cross(a,b),0);}
bool parallel(const Line&s,const Line&t){return parallel(vec(s),vec(t));}
bool intersect(const Line&s,const Point&p){return eq(cross(vec(s),p-s.p1),0);}
bool intersect(const Line&s,const Line&t){return !parallel(s,t)||intersect(s,t.p1);}
bool intersect(const Segment&s,const Point&p){return ccw(s,p)==ON_SEGMENT;}
bool intersect(const Segment&s,const Segment&t){
	return ccw(s,t.p1)*ccw(s,t.p2)<=0&&ccw(t,s.p1)*ccw(t,s.p2)<=0;
}
bool intersect(const Line&s,const Segment&t){
	return cross(vec(s),t.p1-s.p1)*cross(vec(s),t.p2-s.p1)<EPS;
}
bool intersect(const Segment&s,const Line&t){return intersect(t,s);}
bool intersect(const Circle&c,const Point&p){return eq(distance(c.o,p),c.r);}
int intersect(const Circle&c,const Line&s){
	double d=distance(s,c.o);
	return eq(d,c.r)?1:d<c.r?2:0;
}
int intersect(const Circle&c,const Segment&s){
	Point h=projection(s,c.o);
	double d1=distance(c.o,s.p1),d2=distance(c.o,s.p2);
	return distance(c.o,h)>c.r+EPS?0
		:d1<c.r-EPS&&d2<c.r-EPS?0
		:d1<c.r-EPS&&d2>c.r-EPS||d1>c.r-EPS&&d2<c.r-EPS?1
		:intersect(s,h)?eq(distance(c.o,h),c.r)?1:2
		:0;
}
bool intersect(const Circle&a,const Circle&b){
	int c=count_tangent(a,b);
	return 1<=c&&c<=3;
}
int count_tangent(const Circle&a,const Circle&b){
	double d=distance(a.o,b.o);
	return eq(d,a.r+b.r)?3:d>a.r+b.r?4:eq(d,abs(a.r-b.r))?1:d>abs(a.r-b.r)?2:0;
}
double distance(const Point&a,const Point&b){return abs(a-b);}
double distance(const Line&s,const Point&p){return distance(p,projection(s,p));}
double distance(const Line&s,const Line&t){return intersect(s,t)?0:distance(s,t.p1);}
double distance(const Segment&s,const Point&p){
	return distance(p,
		dot(vec(s),p-s.p1)<0?s.p1
		:dot(-vec(s),p-s.p2)<0?s.p2
		:projection(s,p)
	);
}
double distance(const Segment&s,const Segment&t){
	return intersect(s,t)?0:min({
		distance(s,t.p1),distance(s,t.p2),
		distance(t,s.p1),distance(t,s.p2)
	});
}
double distance(const Line&s,const Segment&t){
	return intersect(s,t)?0:min(distance(s,t.p1),distance(s,t.p2));
}
double distance(const Segment&s,const Line&t){return distance(t,s);}
double distance(const Circle&c,const Point&p){return abs(distance(c.o,p)-c.r);}
double distance(const Circle&c,const Line&s){return max(distance(s,c.o)-c.r,0.);}
double distance(const Circle&c,const Segment&s){
	return intersect(c,s)?0
		:contain(c,s)?c.r-max(distance(c.o,s.p1),distance(c.o,s.p2))
		:distance(s,c.o)-c.r;
}
double distance(const Circle&a,const Circle&b){return max(distance(a.o,b.o)-a.r-b.r,0.);}
Point projection(const Line&s,const Point&p){
	return s.p1+vec(s)*dot(p-s.p1,vec(s))/norm(s);
}
Point reflection(const Line&s,const Point&p){return projection(s,p)*2-p;}
Point crosspoint(const Line&s,const Line&t){
	double d1=cross(vec(s),t.p1-s.p1);
	double d2=-cross(vec(s),t.p2-s.p1);
	return t.p1+vec(t)*(d1/(d1+d2));
}
pair<Point,Point>crosspoint(const Circle&c,const Line&s){
	Point h=projection(s,c.o);
	Point e=vec(s)/abs(s)*sqrt(c.r*c.r-norm(h-c.o));
	return minmax(h-e,h+e);
}
pair<Point,Point>crosspoint(const Circle&c,const Segment&s){
	pair<Point,Point>p=crosspoint(c,Line(s));
	return intersect(c,s)==2?p
		:intersect(s,p.first)?make_pair(p.first,p.first)
		:make_pair(p.second,p.second);
}
pair<Point,Point>crosspoint(const Circle&a,const Circle&b){
	double d=distance(a.o,b.o);
	double alpha=acos((a.r*a.r+d*d-b.r*b.r)/(2*a.r*d));
	double theta=arg(b.o-a.o);
	return minmax(a.o+polar(a.r,theta+alpha),a.o+polar(a.r,theta-alpha));
}
pair<Point,Point>tangent(const Circle&c,const Point&p){
	return crosspoint(c,Circle(p,sqrt(norm(c.o-p)-c.r*c.r)));
}
vector<Line>tangent(const Circle&a,const Circle&b){
	vector<Line>ret;
	double g=distance(a.o,b.o);
	if(eq(g,0))return ret;
	Point u=(b.o-a.o)/g;
	Point v=rotate(u,M_PI/2);
	for(int s:{-1,1}){
		double h=(a.r+b.r*s)/g;
		if(eq(h*h,1))ret.emplace_back(a.o+(h>0?u:-u)*a.r,a.o+(h>0?u:-u)*a.r+v);
		else if(1-h*h>0){
			Point U=u*h,V=v*sqrt(1-h*h);
			ret.emplace_back(a.o+(U+V)*a.r,b.o-(U+V)*b.r*s);
			ret.emplace_back(a.o+(U-V)*a.r,b.o-(U-V)*b.r*s);
		}
	}
	return ret;
}
bool is_convex(const Polygon&P){
	for(int i=0;i<P.size();i++)
		if(ccw(P[i],P[(i+1)%P.size()],P[(i+2)%P.size()])==CLOCKWISE)return false;
	return true;
}
Polygon convex_hull(Polygon P,bool ONSEG){
	if(P.size()<=2)return P;
	sort(P.begin(),P.end());
	Polygon ret(2*P.size());
	int k=0,t;
	if(ONSEG){
		for(const Point&p:P){
			while(k>=2&&ccw(ret[k-2],ret[k-1],p)==CLOCKWISE)k--;
			ret[k++]=p;
		}
		t=k;
		for(int i=P.size()-2;i>=0;i--){
			while(k>=t+1&&ccw(ret[k-2],ret[k-1],P[i])==CLOCKWISE)k--;
			ret[k++]=P[i];
		}
	}
	else{
		for(const Point&p:P){
			while(k>=2&&ccw(ret[k-2],ret[k-1],p)!=COUNTER_CLOCKWISE)k--;
			ret[k++]=p;
		}
		t=k;
		for(int i=P.size()-2;i>=0;i--){
			while(k>=t+1&&ccw(ret[k-2],ret[k-1],P[i])!=COUNTER_CLOCKWISE)k--;
			ret[k++]=P[i];
		}
	}
	ret.resize(k-1);
	int mi=0;
	for(int i=1;i<k-1;i++)
		if(eq(ret[mi].y,ret[i].y)?ret[mi].x>ret[i].x:ret[mi].y>ret[i].y)mi=i;
	rotate(ret.begin(),ret.begin()+mi,ret.end());
	return ret;
}
int contain(const Polygon&P,const Point&p){
	bool in=false;
	for(int i=0;i<P.size();i++){
		Segment s(P[i],P[(i+1)%P.size()]);
		if(intersect(s,p))return ON;
		else{
			Point a=s.p1-p,b=s.p2-p;
			if(a.y>b.y)swap(a,b);
			if(a.y<EPS&&EPS<b.y&&cross(a,b)>EPS)in=!in;
		}
	}
	return in?IN:OUT;
}
int contain(const Circle&c,const Point&p){
	double d=distance(c.o,p);
	return eq(d,c.r)?ON:d<c.r?IN:OUT;
}
int contain(const Circle&c,const Segment&s){
	double d1=distance(c.o,s.p1),d2=distance(c.o,s.p2);
	return d1<c.r+EPS&&d2<c.r+EPS?eq(d1,c.r)||eq(d2,c.r)?ON:IN:OUT;
}
Polygon convex_cut(const Polygon&P,const Line&s){
	Polygon ret;
	for(int i=0;i<P.size();i++){
		Segment t(P[i],P[(i+1)%P.size()]);
		if(ccw(s,t.p1)!=CLOCKWISE)ret.push_back(t.p1);
		if(!parallel(s,t)&&!intersect(s,t.p1)
			&&!intersect(s,t.p2)&&intersect(s,t))ret.push_back(crosspoint(s,t));
	}
	return ret;
}
double diameter(Polygon P){
	if(!is_convex(P))P=convex_hull(P);
	int mi=0,Mi=0;
	for(int i=1;i<P.size();i++){
		if(P[i].x<P[mi].x)mi=i;
		if(P[i].x>P[Mi].x)Mi=i;
	}
	double ret=0;
	int sm=mi,sM=Mi;
	while(mi!=sM||Mi!=sm){
		ret=max(ret,norm(P[mi]-P[Mi]));
		if(cross(P[(mi+1)%P.size()]-P[mi],P[(Mi+1)%P.size()]-P[Mi])<0)mi=(mi+1)%P.size();
		else Mi=(Mi+1)%P.size();
	}
	return sqrt(ret);
}
double area(const Polygon&P){
	double ret=0;
	for(int i=0;i<P.size();i++)ret+=cross(P[i],P[(i+1)%P.size()]);
	return ret/2;
}
double area(const Polygon&P,const Line&s){return area(convex_cut(P,s));}
double area(const Polygon&P,const Circle&c){
	double ret=0;
	for(int i=0;i<P.size();i++)
	{
		Segment s(P[i],P[(i+1)%P.size()]);
		if(contain(c,s))ret+=cross(s.p1-c.o,s.p2-c.o);
		else if(!intersect(c,s)){
			double a=arg(s.p2-c.o)-arg(s.p1-c.o);
			if(a>M_PI)a-=2*M_PI;
			if(a<-M_PI)a+=2*M_PI;
			ret+=c.r*c.r*a;
		}
		else
		{
			pair<Point,Point>p=crosspoint(c,s);
			Point tmp[4]={s.p1,p.first,p.second,s.p2};
			if(intersect(c,Segment(s.p1,p.first))==2)swap(tmp[1],tmp[2]);
			for(int j=0;j<3;j++)
			{
				Segment t(tmp[j],tmp[j+1]);
				if(contain(c,t))ret+=cross(t.p1-c.o,t.p2-c.o);
				else{
					double a=arg(t.p2-c.o)-arg(t.p1-c.o);
					if(a>M_PI)a-=2*M_PI;
					if(a<-M_PI)a+=2*M_PI;
					ret+=c.r*c.r*a;
				}
			}
		}
	}
	return ret/2;
}
#line 3 "a.cpp"
int N;
Polygon P;
main()
{
	while(cin>>N,N)
	{
		P=Polygon(N);
		for(int i=0;i<N;i++)cin>>P[i];
		double L=0,R=5e4;
		for(int c=0;c<50;c++)
		{
			double r=(L+R)/2;
			vector<Line>A(N);
			for(int i=0;i<N;i++)
			{
				Line s=Line(P[i],P[(i+1)%N]);
				Point a=vec(s);
				a=a/abs(a)*r;
				A[i]=Line(s.p1+rotate(a,M_PI/2),s.p2+rotate(a,M_PI/2));
			}
			bool ok=false;
			for(int i=0;i<N;i++)for(int j=i+1;j<N;j++)
			{
				Line a=A[i],b=A[j];
				if(!parallel(a,b))
				{
					Point p=crosspoint(a,b);
					if(!contain(P,p))continue;
					bool now=true;
					for(int i=0;i<N;i++)
					{
						Segment s(P[i],P[(i+1)%N]);
						if(distance(s,p)<r-EPS)
						{
							now=false;
							break;
						}
					}
					if(now)ok=true;
				}
			}
			if(ok)L=r;
			else R=r;
		}
		cout<<fixed<<setprecision(16)<<R<<endl;
	}
}
accuracy: 1
time_ms: 1290
memory_kb: 3516
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i = 0; i < (n);i++)
#define FOR(i,m,n) for(int i = (m);i<(n);i++)
#define all(x) (x).begin(),(x).end()
//#define int long long
template <typename T1, typename T2> inline void chmin(T1 & a, T2 b) { if (a > b) a = b; }
template <typename T1, typename T2> inline void chmax(T1& a, T2 b) { if (a < b) a = b; }

//#define TEST

#ifdef TEST
void debug_out(){cerr<<endl;}
template<typename Head,typename... Tail>
void debug_out(Head H,Tail... T){
    cerr<< " "<<(H);
    debug_out(T...);
}
#define DEBUG(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define DEBUG(...) 42
#endif


const double PI = acos(-1);
const double EPS = 1e-8;

typedef complex<double> point;

point operator*(const point &p, const double &d) {
    return point(real(p) * d, imag(p) * d);
}
namespace std {
    bool operator<(const point &a, const point &b) {
        return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
    }
}  // namespace std

//直線or線分
struct Line : public vector<point> {
    Line(const point &a, const point &b) {
        push_back(a);
        push_back(b);
    }
};
typedef vector<Line> Lines;

point direction(const point &p) {  //同じ向きの単位ベクトル
    return p / abs(p);
}
point orthogonal(const point &p) {  //法線ベクトル
    return point(-imag(p), real(p));
}
double cross(const point &a, const point &b) {
    return real(a) * imag(b) - imag(a) * real(b);
}
double dot(const point &a, const point &b) {
    return real(a) * real(b) + imag(a) * imag(b);
}
int ccw(point a, point b, point c) {
    b = b - a;
    c = c - a;
    if (cross(b, c) > EPS) return +1;   // counter clockwise
    if (cross(b, c) < -EPS) return -1;  // clockwise
    if (dot(b, c) < -EPS) return +2;    // c--a--b on line
    if (norm(b) < norm(c)) return -2;   // a--b--c on line
    return 0;
}

//交差判定
bool intersectLL(const Line &l1, const Line &l2) {
    return abs(cross(l1[1] - l1[0], l2[1] - l2[0])) > EPS ||  // non-parallel
           abs(cross(l1[1] - l1[0], l2[0] - l1[0])) < EPS;    // same line
}
bool intersectLS(const Line &l, const Line &s) {
    return cross(l[1] - l[0], s[0] - l[0]) *  // s[0] is left of l
               cross(l[1] - l[0], s[1] - l[0]) <
           EPS;  // s[1] is right of l
}
bool intersectLP(const Line &l, const point &p) {
    return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
//端点に乗ってたらfalse
bool intersectSP_without_endpoint(const Line &s, const point &p) {
    if (abs(s[0] - p) < EPS || abs(s[1] - p) < EPS) return false;
    return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS;  // triangle inequality
}

bool intersectSP(const Line &s, const point &p) {
    // verified on 2020/04/03
    // https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
    return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS;  // triangle inequality
}
bool isOnSegment(const Line &s, const Line &t) {
    if (intersectSP(s, t[0]) || intersectSP(s, t[1]) || intersectSP(t, s[0]) ||
        intersectSP(t, s[1]))
        return true;
    else
        return false;
}
bool isSamePoint(const point &p1, const point &p2) { return abs(p1 - p2) < EPS; }
bool connectSS(const Line &s, const Line &t) {
    REP(i, 2) REP(j, 2) {
        if (s[i] == t[j]) return true;
    }
    return false;
}
bool intersectSS(const Line &s, const Line &t) {
    return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
           ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点が線分上に乗っている場合はfalseにする
bool intersectSS_strict(const Line &s, const Line &t) {
    if (isOnSegment(s, t)) return false;
    return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
           ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}

//距離,交点
//射影 直線lにpから下した垂線との交点
point projection(
    const Line &l,
    const point &
        p) {  // verified on 2020/04/03
              // https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
    double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
    return l[0] + (l[0] - l[1]) * t;
}
//射影 直線lを対象軸としてpと線対称にある点
point reflection(const Line &l, const point &p) { return p + (projection(l, p) - p) * 2; }
double distancePP(const point &a, const point &b) { return sqrt(norm(a - b)); }
double distanceLP(const Line &l, const point &p) { return abs(p - projection(l, p)); }
double distanceLL(const Line &l, const Line &m) {
    return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const Line &l, const Line &s) {
    if (intersectLS(l, s)) return 0;
    return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const Line &s, const point &p) {
    const point r = projection(s, p);
    if (intersectSP(s, r)) return abs(r - p);
    return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const Line &s, const Line &t) {
    // verified on 2020/04/03
    // https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
    if (intersectSS(s, t)) return 0;
    return min({distanceSP(s, t[0]), distanceSP(s, t[1]), distanceSP(t, s[0]),
                distanceSP(t, s[1])});
}
point crosspoint(const Line &l, const Line &m) {
    double A = cross(l[1] - l[0], m[1] - m[0]);
    double B = cross(l[1] - l[0], l[1] - m[0]);
    if (abs(A) < EPS && abs(B) < EPS) return m[0];  // same line
    if (abs(A) < EPS) assert(false);                // Precondition not satisfied
    return m[0] + B / A * (m[1] - m[0]);
}

struct Polygon : public vector<point> {
    // 0->OUT, 1->ON, 2->IN
    int contains(const point &p) {
        bool in = false;
        int N = this->size();
        for (int i = 0; i < N; i++) {
            point a = this->at(i) - p;
            point b = this->at((i + 1) % N) - p;
            if (imag(a) > imag(b)) {
                std::swap(a, b);
            }
            if (imag(a) <= 0 && 0 < imag(b))
                if (cross(a, b) < 0) in = !in;
            if (cross(a, b) == 0 && dot(a, b) <= 0) return 1;
        }
        return in ? 2 : 0;
    }
    double area(){
        double A = 0;
        int N = this->size();
        REP(i,N){
            A+=cross(this->at(i),this->at((i+1)%N));
        }
        return A*0.5;
    }
};

const double INF = 1e9;

bool solve(){
    int N;cin>>N;
    if(N==0)return false;
    Polygon poly;
    vector<Line>segs;
    double minx=INF,maxx=-INF;
    REP(i,N){
        int x,y;cin>>x>>y;
        poly.emplace_back(x,y);
        chmin(minx,x);
        chmax(maxx,x);
    }
    REP(i,N){
        segs.emplace_back(poly[i],poly[(i+1)%N]);
    }

    auto calc=[&](point p){
        if(!poly.contains(p))return -INF;
        double ret = INF;
        for(auto &seg:segs){
            ret=min(ret,distanceSP(seg,p));
        }
        return ret;
    };
    auto ternary_search=[&](double x)->double{
        vector<double>ys;
        Line li(point(x,0),point(x,10000));
        for(auto seg:segs){
            if(intersectSS(li,seg))ys.push_back(crosspoint(li,seg).imag());
        }
        sort(all(ys));
        if(ys.size()<1)return -INF;
        double l = ys[0],r=*ys.rbegin();
        REP(_,100){
            double m1 = (l+l+r)/3,m2=(l+r+r)/3;
            point p1(x,m1),p2(x,m2);
            if(calc(p1)>calc(p2))r=m2;
            else l = m1;
        }
        return calc(point(x,l));
    };
    double ans = -INF;
    double l=minx,r=maxx;
    REP(_,100){
        double m1=(l+l+r)/3,m2=(l+r+r)/3;
        double res1=ternary_search(m1),res2=ternary_search(m2);
        DEBUG(m1,m2,res1,res2);
        if(ternary_search(m1)>ternary_search(m2))r=m2;
        else l=m1;
    }
    ans = ternary_search(l);
    cout<<setprecision(10)<<fixed<<ans<<endl;
    return true;
}

signed main(){
    while(solve());
}
accuracy: 1
time_ms: 1960
memory_kb: 3336
final_rank: 17