Problem:
Problem G:
Magical Island 2
まだ魔法があたりまえのように存在した時代である．ある魔導士の一族は，魔力によって作られた正方形の形の島に住んでいた．
ある時，この島に危機が訪れた．帝国が大陸間弾道魔導ミサイルを開発し，この島を照準に合わせてきたのである．この世界の魔法は地属性，水属性，火属性，風属性などに分類でき，魔導ミサイルもその四つの属性のいずれかに属していた．島の四隅にはそれぞれ地の水晶，水の水晶，火の水晶，風の水晶が配置されていて，水晶に魔力を送り込むことで対応する属性の魔法攻撃を防ぐことがきでる．
魔導士達は帝国が開発した大陸間弾道魔導ミサイルによる攻撃をかろうじて退けることができた．しかし，帝国は新たに闇属性に属する大陸間弾道魔導ミサイルを開発し，再びこの島に攻撃を仕掛けてきた．闇属性に属する魔法はこの島に設置されている水晶で防ぐことはできない．そこで魔導士達は秘術としてこの島に伝えられる光属性の防御陣を用いてミサイルを防ぐ事にした．
この光属性の防御陣はある特定の形状をした魔法陣を大地に描くことにより発動する． 魔法陣は半径
R
の円周を
M
等分し
K
個おきに直線で結んだ図形である．魔法陣は任意の大きさで描くことができるが魔法の発動には方角が重要なので，一つの角が真北を向くように描かなければならない．防御陣の効果が及ぶ範囲は描かれた魔法陣の内部（境界を含む）と一致する．またこの魔法の詠唱に必要なエネルギーは描いた魔法陣の半径
R
と等しい．
図G-1は
M
= 4，
K
= 1 の場合である．灰色の部分が魔方陣の効果が及ぶ領域である． 図G-2は
M
= 6，
K
= 2 の場合である．図のように複数の図形が生じる場合は，それらの図形のいずれかに含まれていれば防御陣としての効果が及ぶ．
図G-1:
M
= 4 ，
K
= 1 の場合 小さい丸が集落を表す
図G-2:
M
= 6 ，
K
= 2 の場合
あなたの仕事は，集落の位置，および
M
と
K
の値が与えられたときに，全ての集落をカバーするために必要となるエネルギーの最低量を求めるプログラムを書くことである．
Input
入力は複数のデータセットからなる． 各データセットは以下の形式で与えられる．
N
M
K
x
1
y
1
x
2
y
2
...
x
N
y
N
最初の一行は 3 つの整数
N
,
M
,
K
からなる．
N
は集落の数を表す．
M
,
K
については問題文に記したとおりである． 2 ≤
N
≤ 50， 3 ≤
M
≤ 50， 1 ≤
K
≤ (
M
- 1) / 2を仮定してよい．
続く
N
行は集落の位置を表す． 各行は二つの整数
x
i
と
y
i
からなる．
x
i
と
y
i
は
i
番目の集落のx座標とy座標を表す． -1000 ≤
x
i
，
y
i
≤ 1000 を仮定して良い．y軸の正方向が北を指す.
入力の終わりはスペースで区切られた3個のゼロからなる．
Output
各データセットに対し，魔法陣の最小の半径
R
を1行に出力せよ． 出力する値は10
-6
以下の誤差を含んでいても構わない．値は小数点以下何桁表示しても構わない．
Sample Input
4 4 1
1 0
0 1
-1 0
0 -1
5 6 2
1 1
4 4
2 -4
-4 2
1 5
0 0 0
Output for the Sample Input
1.000000000
6.797434948

Submitted solutions:

code_snippet: #include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  inline P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &vil, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = vil[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(vil[i], vil[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, vil[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> vil(n);
    REP(i, n) cin >> vil[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, vil, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 40) {
        R m = (l + r) * (R).5;
        if (check(temp, m, vil, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 1740
memory_kb: 4244
final_rank: 12

code_snippet: #include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &shoolack, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = shoolack[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(shoolack[i], shoolack[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, shoolack[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> shoolack(n);
    REP(i, n) cin >> shoolack[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, shoolack, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 50) {
        R m = (l + r) * (R).5;
        if (check(temp, m, shoolack, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 1840
memory_kb: 4432
final_rank: 17

code_snippet: #include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &shoolack, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = shoolack[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(shoolack[i], shoolack[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, shoolack[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> shoolack(n);
    REP(i, n) cin >> shoolack[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, shoolack, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 50) {
        R m = (l + r) * (R).5;
        if (check(temp, m, shoolack, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 1800
memory_kb: 4416
final_rank: 15

code_snippet: #pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &shoolack, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = shoolack[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(shoolack[i], shoolack[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, shoolack[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> shoolack(n);
    REP(i, n) cin >> shoolack[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, shoolack, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 50) {
        R m = (l + r) * (R).5;
        if (check(temp, m, shoolack, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 2000
memory_kb: 4216
final_rank: 13

code_snippet: #pragma GCC optimize("O3")
#pragma GCC target("sse4")
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &shoolack, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = shoolack[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(shoolack[i], shoolack[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, shoolack[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> shoolack(n);
    REP(i, n) cin >> shoolack[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, shoolack, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 50) {
        R m = (l + r) * (R).5;
        if (check(temp, m, shoolack, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 2090
memory_kb: 4272
final_rank: 16

code_snippet: #pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#include <algorithm>
#include <assert.h>
#include <bitset>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <valarray>
#include <vector>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
#define REP(i, x) for (int i = 0; i < (int)(x); i++)
#define REPS(i, x) for (int i = 1; i <= (int)(x); i++)
#define RREP(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define RREPS(i, x) for (int i = ((int)(x)); i > 0; i--)
#define FOR(i, c)                                                              \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define RFOR(i, c)                                                             \
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a, b) make_pair(a, b)
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end());
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &t) {
  os << "[";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "]";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const set<T> &t) {
  os << "{";
  FOR(it, t) {
    if (it != t.begin())
      os << ",";
    os << *it;
  }
  os << "}";
  return os;
}
template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> &t) {
  return os << "(" << t.first << "," << t.second << ")";
}
template <class S, class T>
pair<S, T> operator+(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first + t.first, s.second + t.second);
}
template <class S, class T>
pair<S, T> operator-(const pair<S, T> &s, const pair<S, T> &t) {
  return pair<S, T>(s.first - t.first, s.second - t.second);
}
namespace geom {
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
enum { TRUE = 1, FALSE = 0, BORDER = -1 };
typedef int BOOL;
typedef double R;
const R INF = 1e8;
R EPS = 1e-6;
const R PI = 3.1415926535897932384626;
inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
inline BOOL less(const R &x, const R &y) { return sig(x - y) ? x < y : BORDER; }
typedef complex<R> P;
inline R norm(const P &p) { return p.X * p.X + p.Y * p.Y; }
inline R inp(const P &a, const P &b) { return (conj(a) * b).X; }
inline R outp(const P &a, const P &b) { return (conj(a) * b).Y; }
inline P unit(const P &p) { return p / abs(p); }
inline P proj(const P &s, const P &t) { return t * inp(s, t) / norm(t); }
inline int ccw(const P &s, const P &t, const P &p, int adv = 0) {
  int res = sig(outp(t - s, p - s));
  if (res || !adv)
    return res;
  if (sig(inp(t - s, p - s)) < 0)
    return -2;
  if (sig(inp(s - t, p - t)) < 0)
    return 2;
  return 0;
}
struct L : public vector<P> {
  L(const P &p1, const P &p2) {
    this->push_back(p1);
    this->push_back(p2);
  }
  L() {}
  P dir() const { return at(1) - at(0); }
  BOOL online(const P &p) const { return !sig(outp(p - at(0), dir())); }
};
struct S : public L {
  S(const P &p1, const P &p2) : L(p1, p2) {}
  S() {}
  BOOL online(const P &p) const {
    if (!sig(norm(p - at(0))) || !sig(norm(p - at(1))))
      return BORDER;
    return !sig(outp(p - at(0), dir())) && inp(p - at(0), dir()) > -EPS &&
                   inp(p - at(1), -dir()) > -EPS
               ? TRUE
               : FALSE;
    return !sig(abs(at(0) - p) + abs(at(1) - p) - abs(at(0) - at(1)));
  }
};
P crosspoint(const L &l, const L &m);
struct G : public vector<P> {
  G(size_type size = 0) : vector(size) {}
  S edge(int i) const { return S(at(i), at(i + 1 == size() ? 0 : i + 1)); }
};
inline BOOL intersect(const S &s, const L &l) {
  return (sig(outp(l.dir(), s[0] - l[0])) * sig(outp(l.dir(), s[1] - l[0])) <=
          0);
}
inline P crosspoint(const L &l, const L &m) {
  R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
  if (!sig(abs(A)) && !sig(abs(B)))
    return m[0];
  if (abs(A) < EPS)
    assert(false);
  return m[0] + B / A * (m[1] - m[0]);
}
struct Arrangement {
  struct AEdge {
    int u, v, t;
    R cost;
    AEdge(int u = 0, int v = 0, int t = 0, R cost = 0)
        : u(u), v(v), t(t), cost(cost) {}
  };
  typedef vector<vector<AEdge>> AGraph;
  vector<P> p;
  AGraph g;
  Arrangement() {}
  Arrangement(vector<S> seg) {
    int m = seg.size();
    REP(i, m) {
      p.push_back(seg[i][0]);
      p.push_back(seg[i][1]);
      REP(j, i)
      if (sig(outp(seg[i].dir(), seg[j].dir())) &&
          intersect(seg[i], seg[j]) == TRUE)
          p.push_back(crosspoint(seg[i], seg[j]));
    }
    sort(ALL(p));
    UNIQUE(p);
    int n = p.size();
    g.resize(n);
    REP(i, m) {
      S &s = seg[i];
      vector<pair<R, int>> ps;
      REP(j, n) if (s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
      sort(ALL(ps));
      REP(j, (int)ps.size() - 1) {
        const int u = ps[j].second;
        const int v = ps[j + 1].second;
        g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
        g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
      }
    }
  }
  int getIdx(P q) {
    auto it = lower_bound(ALL(p), q);
    if (it == p.end() || *it != q)
      return -1;
    return it - p.begin();
  }
};
struct DualGraph {
  struct DEdge {
    int u, v, f, l;
    R a;
    DEdge(int u, int v, R a) : u(u), v(v), f(0), l(0) {
      while (PI < a)
        a -= 2 * PI;
      while (a < -PI)
        a += 2 * PI;
      this->a = a;
    }
    bool operator==(const DEdge &opp) const { return v == opp.v; }
    bool operator<(const DEdge &opp) const { return a > opp.a; }
    bool operator<(const R &opp) const { return a > opp; }
    friend ostream &operator<<(ostream &os, const DEdge &t) {
      return os << "(" << t.u << "," << t.v << "," << t.a * 180 / PI << ")";
    }
  };
  int n;
  vector<P> p;
  vector<vector<DEdge>> g;
  DualGraph(const vector<P> &p) : p(p), g(p.size()), n(p.size()) {}
  void add_edge(const int s, const int t) {
    R a = arg(p[t] - p[s]);
    g[s].emplace_back(s, t, a);
    g[t].emplace_back(t, s, a > 0 ? a - PI : a + PI);
  }
  void add_polygon(int s, G &t, R a) {
    auto e = lower_bound(ALL(g[s]), a - EPS);
    if (e == g[s].end())
      e = g[s].begin();
    if (e->f)
      return;
    e->f = 1;
    t.push_back(p[s]);
    add_polygon(e->v, t, e->a > 0 ? e->a - PI : e->a + PI);
  }
  G dual() {
    REP(i, n) {
      sort(ALL(g[i]));
      UNIQUE(g[i]);
    }
    int s = min_element(ALL(p)) - p.begin();
    G poly;
    add_polygon(s, poly, -PI * (R).5);
    return poly;
  }
};
#undef SELF
#undef at
} // namespace geom
using namespace geom;
namespace std {
bool operator<(const P &a, const P &b) {
  return sig(a.X - b.X) ? a.X < b.X : a.Y + EPS < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
istream &operator>>(istream &is, P &p) {
  R x, y;
  is >> x >> y;
  p = P(x, y);
  return is;
}
} // namespace std
int n, m, k;
struct MSQ : public G {
  MSQ() {}
  vector<P> p;
  vector<S> s;
  int m, k;
  MSQ(int m, int k) : m(m), k(k) {
    REP(i, m) p.push_back(polar((R)1, 2 * PI * i / m + PI * (R).5));
    REP(i, m) s.emplace_back(p[i], p[(i + k) % m]);
    Arrangement a(s);
    DualGraph dg(a.p);
    REP(i, a.g.size()) REP(j, a.g[i].size()) {
      int u = a.g[i][j].u;
      int v = a.g[i][j].v;
      if (u < v)
        dg.add_edge(u, v);
    }
    (G &)(*this) = dg.dual();
    reverse(this->begin(), this->end());
  }
  void copy(R r, P c, MSQ &msq) const {
    msq.resize(size());
    msq.p.resize(p.size());
    msq.s.resize(s.size());
    msq.m = m;
    msq.k = k;
    REP(i, size()) msq[i] = at(i) * r + c;
    REP(i, p.size()) msq.p[i] = p[i] * r + c;
    REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i + k) % m]);
  }
  S segment(int i) const { return s[i]; }
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
  const int n = msq.size();
  int a = 0, b = n;
  const P pg = p - g;
  while (a + 1 < b) {
    int c = (a + b) / 2;
    if (outp(msq[a] - g, pg) > 0 && outp(msq[c] - g, pg) < 0)
      b = c;
    else
      a = c;
  }
  b %= n;
  if (outp(msq[a] - p, msq[b] - p) < -EPS)
    return 0;
  return 1;
}
bool check(const MSQ &temp, R r, const vector<P> &shoolack, int i, int j) {
  MSQ msq;
  L l = temp.segment(j);
  P gp = shoolack[i] - l[0] * r;
  temp.copy(r, gp, msq);
  vector<P> p;
  P b(-INF, -INF), u(+INF, +INF);
  REP(i, n) {
    L l2(shoolack[i], shoolack[i] + l.dir());
    int f = 0;
    P ll(INF, INF), rr(-INF, -INF);
    REP(j, m) {
      const S s = msq.segment(j);
      if (intersect(s, l2)) {
        if (sig(outp(s.dir(), l2.dir()))) {
          const P q = crosspoint(s, l2) - l2[0];
          p.push_back(q);
          ll = min(ll, q);
          rr = max(rr, q);
        }
        f = 1;
      }
    }
    u = min(rr, u);
    b = max(ll, b);
    if (!f)
      return false;
  }
  FOR(q, p) {
    if (*q < b || u < *q)
      continue;
    if ([&]() {
          REP(i, n) if (!convex_contains(msq, gp, shoolack[i] + *q)) return 0;
          return 1;
        }())
      return true;
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  while (cin >> n >> m >> k, n) {
    MSQ temp(m, k);
    vector<P> shoolack(n);
    REP(i, n) cin >> shoolack[i];
    R best = 2000;
    REP(i, n) REP(j, m) {
      if (!check(temp, best - EPS, shoolack, i, j))
        continue;
      R l = EPS, r = best;
      REP(itr, 50) {
        R m = (l + r) * (R).5;
        if (check(temp, m, shoolack, i, j))
          r = m;
        else
          l = m;
      }
      best = r;
    }
    printf("%.10f\n", (double)best);
  }
  return 0;
}
accuracy: 1
time_ms: 3340
memory_kb: 4424
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};


int N,M,K;
Point point[55];
Polygon STAR,rev_STAR;


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

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

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}


int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}



Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && 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);
}


bool is_OK(int p_id,int edge_id,double R){

	Polygon work_STAR = STAR;
	for(int i = 0; i < work_STAR.size(); i++){

		work_STAR[i] = work_STAR[i]*R;
	}

	Polygon work_REV = rev_STAR;
	for(int i = 0; i < work_REV.size(); i++){

		work_REV[i] = work_REV[i]*R;
	}

	int SIZE = work_REV.size();

	Line base_line = Line(work_REV[edge_id]+point[p_id],work_REV[(edge_id+1)%SIZE]+point[p_id]);

	vector<Point> P;

	for(int i = 0; i < N; i++){
		for(int k = 0; k < SIZE; k++){
			Line work_line = Line(work_REV[k]+point[i],work_REV[(k+1)%SIZE]+point[i]);

			if(!is_Cross(base_line,work_line))continue;

			P.push_back(calc_Cross_Point(base_line,work_line));
		}
	}

	for(int i = 0; i < P.size(); i++){
		bool FLG = true;
		for(int k = 0; k < N; k++){
			if(contains(work_STAR,point[k]-P[i]) == 0){

				FLG = false;
				break;
			}
		}
		if(FLG)return true;
	}

	return false;
}


void func(){

	STAR.clear();
	rev_STAR.clear();

	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&point[i].x,&point[i].y);
	}

	Point center = Point(0,0);
	Point tmp_p = Point(0,1);
	double tmp_rad = (2*M_PI)/M;

	vector<Point> vec;

	for(int i = 0; i < M; i++){

		vec.push_back(rotate(center,tmp_p,tmp_rad*i));
	}

	for(int i = 0; i < vec.size(); i++){

		STAR.push_back(vec[i]);

		if(K >= 2){
			Line line1 = Line(vec[i],vec[(i+K)%M]);
			Line line2 = Line(vec[(i+1)%M],vec[(i+1-K+M)%M]);

			STAR.push_back(calc_Cross_Point(line1,line2));
		}
	}

	tmp_p = Point(0,-1);
	vec.clear();

	for(int i = 0; i < M; i++){

		vec.push_back(rotate(center,tmp_p,tmp_rad*i));
	}

	for(int i = 0; i < vec.size(); i++){

		rev_STAR.push_back(vec[i]);

		if(K >=2){
			Line line1 = Line(vec[i],vec[(i+K)%M]);
			Line line2 = Line(vec[(i+1)%M],vec[(i+1-K+M)%M]);

			rev_STAR.push_back(calc_Cross_Point(line1,line2));
		}
	}

	double ans = 5000;

	for(int i = 0; i < N; i++){
		for(int k = 0; k < STAR.size(); k++){
			if(is_OK(i,k,ans)){
				double left = 0,right = ans;
				double mid = (left+right)/2;

				while(left+EPS < right){
					if(is_OK(i,k,mid)){

						ans = mid;
						right = mid-EPS;

					}else{

						left = mid+EPS;
					}
					mid = (left+right)/2;
				}
			}
		}
	}
	printf("%.10lf\n",ans);
}


int main(){

	while(true){

		scanf("%d %d %d",&N,&M,&K);
		if(N == 0 && M == 0 && K == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 7100
memory_kb: 3604
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <complex>
#include <cmath>
#include <array>
using namespace std;

const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

//(0,0)-center
bool in_convex(const P &p, const VP &poly){
	int n = poly.size();
	int a = 0, b = n;
	while(a+1 < b){
		int c = (a + b)/2;
		if(cross(poly[a], poly[c]) > 0){
			if(cross(poly[a], p)>0 && cross(poly[c], p)<0) b = c;
			else a = c;
		}else{
			if(cross(poly[a], p)<0 && cross(poly[c], p)>0) a = c;
			else b = c;
		}
	}
	b %= n;
	if(cross(poly[b] -poly[a], p -poly[a]) > -EPS) return true;
	return false;
}

VP makeMagicCircle(int m, int k){
	VP v(m);
	for(int i=0; i<m; i++){
		v[i] = rotate(P(0, 1), 2*PI *i/m);
	}
	VP ret;
	for(int i=0; i<m; i++){
		ret.push_back(v[i]);
		if(k >= 2){
			ret.push_back(crosspointLL(L(v[i], v[(i+k)%m]), L(v[(i+1)%m], v[(i+1-k+m)%m])));
		}
	}
	return ret;
}
bool canEnclose(int pidx, int eidx, double scale, const VP &v, const VP &poly){
	int n = v.size();
	int m = poly.size();
	L edge(-scale *poly[eidx] +v[pidx], -scale *poly[(eidx+1)%m] +v[pidx]);
	for(int pidx2=0; pidx2<n; pidx2++){
		VP cand;
		for(int i=0; i<m; i++){
			L e(-scale *poly[i] +v[pidx2], -scale *poly[(i+1)%m] +v[pidx2]);
			if(!isParallel(e, edge) && intersectSS(e, edge)){
				cand.push_back(crosspointLL(e, edge));
			}
		}
		
		for(int i=0; i<(int)cand.size(); i++){
			VP mc = poly;
			for(int j=0; j<m; j++){
				mc[j] = scale *poly[j];
			}
			bool enclose = true;
			for(int j=0; j<n; j++){
				if(!in_convex(v[j]-cand[i], mc)){
					enclose = false;
					break;
				}
			}
			if(enclose) return true;
		}
	}
	return false;
}
double solve(int m, int k, const VP &v){
	double ret = 2000;
	VP poly = makeMagicCircle(m, k);
	for(int i=0; i<(int)v.size(); i++){
		for(int j=0; j<(int)poly.size(); j++){
			if(canEnclose(i, j, ret, v, poly)){
				double lb = 0, ub = ret;
				while(ub-lb > 1e-6){
					double mid = (lb + ub)/2;
					if(canEnclose(i, j, mid, v, poly)){
						ub = mid;
					}else{
						lb = mid;
					}
				}
				ret = (lb + ub)/2;
			}
		}
	}
	return ret;
}

int main(){
	cout << fixed;
	cout << setprecision(10);
	while(1){
		int n,m,k;
		cin >> n >> m >> k;
		if(n==0) break;
		
		VP v(n);
		for(int i=0; i<n; i++){
			int x,y;
			cin >> x >> y;
			v[i] = P(x, y);
		}
		cout << solve(m, k, v) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 4210
memory_kb: 3508
final_rank: 18

code_snippet: #include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
 
#define rep(i,n) for(int i=0;i<(n);i++)
 
using namespace std;
 
const double EPS=1e-7;
const double PI=acos(-1);
 
template<class T>
struct point{
    T x,y;
    point operator+(const point &a)const{ return (point){x+a.x,y+a.y}; }
    point operator-(const point &a)const{ return (point){x-a.x,y-a.y}; }
};
 
template<class T>
point<T> operator*(T c,const point<T> &a){ return (point<T>){c*a.x,c*a.y}; }
 
bool operator==(const point<double> &a,const point<double> &b){
    return abs(a.x-b.x)<EPS && abs(a.y-b.y)<EPS;
}
 
template<class T>
double abs(const point<T> &a){ return sqrt(a.x*a.x+a.y*a.y); }
 
template<class T>
T cross(const point<T> &a,const point<T> &b){ return a.x*b.y-a.y*b.x; }
 
point<double> rot(const point<double> &a,double theta){
    return (point<double>){a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)};
}
 
template<class T>
double arg(const point<T> &a){
    double t=atan2(a.y,a.x);
    return t<0?t+2*PI:t;
}
 
template<class T>
struct segment{ point<T> a,b; };
 
enum{CCW=1,CW=-1,ON=0};
int ccw(const point<double> &a,const point<double> &b,const point<double> &c){
    double rdir=cross(b-a,c-a);
    if(rdir> EPS) return CCW;
    if(rdir<-EPS) return CW;
    return ON;
}
 
template<class T>
double dist(const point<T> &a,const point<T> &b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
 
bool cover(const segment<double> &S,const point<double> &p){
    return dist(S.a,p)+dist(p,S.b)<dist(S.a,S.b)+EPS;
}
 
bool intersect(const segment<double> &S1,const segment<double> &S2){
    if(max(S1.a.x,S1.b.x)+EPS<min(S2.a.x,S2.b.x)
    || max(S1.a.y,S1.b.y)+EPS<min(S2.a.y,S2.b.y)
    || max(S2.a.x,S2.b.x)+EPS<min(S1.a.x,S1.b.x)
    || max(S2.a.y,S2.b.y)+EPS<min(S1.a.y,S1.b.y)) return false;
    return ccw(S1.a,S1.b,S2.a)*ccw(S1.a,S1.b,S2.b)<=0
        && ccw(S2.a,S2.b,S1.a)*ccw(S2.a,S2.b,S1.b)<=0;
}
 
point<double> get_intersect(const segment<double> &S1,const segment<double> &S2){
    double a1=cross(S1.b-S1.a,S2.b-S2.a);
    double a2=cross(S1.b-S1.a,S1.b-S2.a);
    if(abs(a1)<EPS){
        if(cover(S1,S2.a)) return S2.a;
        if(cover(S1,S2.b)) return S2.b;
        if(cover(S2,S1.a)) return S1.a;
        return S1.b;
    }
    return S2.a+a2/a1*(S2.b-S2.a);
}
 
int n,m,K;
point<double> P[50]; // ???
 
point<double> star[50]; // ???????????¨??? m ??????????????????
 
vector< pair<double,double> > in; // ?????????????????¨??????????????????????????????????????±. ??????????????????????????????????????? <?§????,????????????????????¢>
point<double> in2[100]; // ?\???§?¨???§???????????? in ?????´?????§?¨??????´???????????? ( ?????????????????? )
 
void get_intersect(const point<double> *G1,const point<double> *G2,int &sz,point<double> *res){
    segment<double> S1[50],S2[50]; // ?????????
    rep(i,m){
        S1[i].a=G1[i];
        S1[i].b=G1[(i+K)%m];
        S2[i].a=G2[i];
        S2[i].b=G2[(i+K)%m];
    }
    rep(i,m) rep(j,m) if(intersect(S1[i],S2[j])) res[sz++]=get_intersect(S1[i],S2[j]);
}
 
bool cover(double R,const point<double> &cen,const point<double> &p){
    if(p==cen) return true;
 
    double phi=arg(p-cen),d=dist(p,cen);
    if(d>R+EPS) return false;
 
    if(phi<in[0].first+EPS) phi+=2*PI;
    int i=upper_bound(in.begin(),in.end(),make_pair(phi,0.0))-in.begin()-1;
    return ccw(R*in2[i],R*in2[(i+1)%in.size()],p-cen)!=CW;
}
 
// p1, p2 : ???????¢????????????????????????????
bool check(double R,const point<double> &p1,const point<double> &p2){
    point<double> G1[50],G2[50]; // ?????????????????¢?????????, ???????????? p1, p2 ??????????????\???????????????????§????????????????
    rep(k,m){
        point<double> p=R*(point<double>){star[k].x,-star[k].y};
        G1[k]=p+p1;
        G2[k]=p+p2;
    }
 
    int sz=0;
    static point<double> Q[50*50]; // ???????????????????£????
    get_intersect(G1,G2,sz,Q);
    Q[sz++]=(point<double>){0,0}; // ???????????\???????????¨?????????
 
    rep(k,sz){
        bool ok=true;
        rep(l,n) if(!cover(R,Q[k],P[l])) { ok=false; break; }
        if(ok) return true;
    }
    return false;
}
 
int main(){
    for(;scanf("%d%d%d",&n,&m,&K),n;){
        rep(i,n) scanf("%lf%lf",&P[i].x,&P[i].y);
 
        rep(i,m) star[i]=rot((point<double>){1,0},2*i*PI/m+PI/2);
 
        in.clear();
        rep(i,m){
            in.push_back(make_pair(arg(star[i]),abs(star[i])));
            if(K>1){
                segment<double> S1={star[i],star[(i+K)%m]};
                segment<double> S2={star[(i+1)%m],star[(i+1-K+m)%m]};
                point<double> p=get_intersect(S1,S2);
                in.push_back(make_pair(arg(p),abs(p)));
            }
        }
        sort(in.begin(),in.end());
        rep(i,in.size()){
            in2[i].x=in[i].second*cos(in[i].first);
            in2[i].y=in[i].second*sin(in[i].first);
        }
 
        double ans=1e4;
        // p, q ????????? R1 ??????????¢??????¨???????????¨??§????????¨?????????, ?????? R2(>R1) ??????????¢????????????¨??§????????????????????????????????????(??¨??????)?????§??????????§£???
        rep(i,n) for(int j=i+1;j<n;j++) { // ???????¢????????????????????±??????????
            if(!check(ans+EPS,P[i],P[j])) continue; // ?§£??????????????????????????????????????§????????¢?´¢?????????
 
            double lo=0,hi=ans;
            while(hi-lo>1e-6){
                double mi=(lo+hi)/2;
                if(check(mi,P[i],P[j])) hi=mi; else lo=mi;
            }
            ans=(lo+hi)/2;
        }
 
        printf("%.9f\n",ans);
    }
 
    return 0;
}
accuracy: 1
time_ms: 3120
memory_kb: 3144
final_rank: 11

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e+10;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline double ABS(double a){return max(a,-a);}
struct Pt {
	double x, y;
	Pt() {}
	Pt(double x, double y) : x(x), y(y) {}
	Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
	Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
	Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
	Pt operator-() const { return Pt(-x, -y); }
	Pt operator*(const double &k) const { return Pt(x * k, y * k); }
	Pt operator/(const double &k) const { return Pt(x / k, y / k); }
	double ABS() const { return sqrt(x * x + y * y); }
	double abs2() const { return x * x + y * y; }
	double arg() const { return atan2(y, x); }
	double dot(const Pt &a) const { return x * a.x + y * a.y; }
	double det(const Pt &a) const { return x * a.y - y * a.x; }
};
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
	int s = sig((b - a).det(c - a));
	if (s) return s;
	if (sig((b - a).dot(c - a)) < 0) return -2; // c-a-b
	if (sig((a - b).dot(c - b)) < 0) return +2; // a-b-c
	return 0;
}
int iLL(Pt a, Pt b, Pt c, Pt d) {
	if (sig((b - a).det(d - c))) return 1; // intersect
	if (sig((b - a).det(c - a))) return 0; // parallel
	return -1; // correspond
}
bool iLS(Pt a, Pt b, Pt c, Pt d) {
	return (sig(tri(a, b, c)) * sig(tri(a, b, d)) <= 0);
}
bool iSS(Pt a, Pt b, Pt c, Pt d) {
	return (iSP(a, b, c) * iSP(a, b, d) <= 0 && iSP(c, d, a) * iSP(c, d, b) <= 0);
}
bool iSSstrict(Pt a, Pt b, Pt c, Pt d) {
	return (sig(tri(a, b, c)) * sig(tri(a, b, d)) < 0 && sig(tri(c, d, a)) * sig(tri(c, d, b)) < 0);
}
Pt pLL(Pt a, Pt b, Pt c, Pt d) {
	b = b - a; d = d - c; return a + b * (c - a).det(d) / b.det(d);
}
double dLP(Pt a, Pt b, Pt c) {
	return ABS(tri(a, b, c)) / (b - a).ABS();
}
bool intri(Pt a,Pt b,Pt c,Pt d){
	return iSP(a,d,b)>=0&&iSP(b,d,c)>=0&&iSP(c,d,a)>=0;
}
Pt p[60];
int A,B,C;
int check(int at,int s,double r){
	Pt vec=Pt(cos(-PI/2-PI*2/B*s),sin(-PI/2-PI*2/B*s))*r;
	Pt vec2=Pt(cos(-PI/2-PI*2/B*(s+C)),sin(-PI/2-PI*2/B*(s+C)))*r;
	pair<Pt,Pt> l1=make_pair(p[at]+vec,p[at]+vec2);
	vector<Pt>hb;
	
	double SL=-9999999;
	double SR=9999999;
	for(int i=0;i<A;i++){
		if(at==i)continue;
		double R=-99999999;
		double L=99999999;
		for(int j=0;j<B;j++){
			vec=Pt(cos(-PI/2-PI*2/B*j),sin(-PI/2-PI*2/B*j))*r;
			vec2=Pt(cos(-PI/2-PI*2/B*(j+C)),sin(-PI/2-PI*2/B*(j+C)))*r;
			pair<Pt,Pt>l2=make_pair(p[i]+vec,p[i]+vec2);
			int q=iLL(l1.first,l1.second,l2.first,l2.second);
			if(q==1&&iSS(l1.first,l1.second,l2.first,l2.second)){
				Pt sp=pLL(l1.first,l1.second,l2.first,l2.second);
				L=min(L,sp.x*114.514+sp.y);
				R=max(R,sp.x*114.514+sp.y);
		
				if(sp.ABS()<100000000&&((p[0]-sp).ABS())<r+EPS){
					hb.push_back(sp);
				}
			}
			if(q==-1){L=-99999999;R=99999999;}
		}
		SR=min(SR,R);
		SL=max(SL,L);
	}
	Pt pb=pLL(Pt(1,0),Pt(cos(PI*2*C/B),sin(PI*2*C/B)),Pt(0,0),Pt(cos(PI/B),sin(PI/B)))*r;
	double ml=pb.ABS();
	
	for(int i=0;i<hb.size();i++){
		if(SL<SR&&hb[i].x*114.514+hb[i].y+EPS<SL)continue;
		if(SL<SR&&hb[i].x*114.514+hb[i].y>SR+EPS)continue;
		
		bool dame=false;
		for(int j=0;j<A;j++){
			double dis=(hb[i]-p[j]).ABS();
			if(dis<ml+EPS)continue;
			if(dis>r+EPS){dame=true;break;}
			double th=(p[j]-hb[i]).arg()-PI/2;
			if(th<EPS)th+=2*PI;
			double nx=PI*2/B*((int)(th*B/PI/2));
		//	if(nx+EPS>th+PI*2)nx-=PI*2;
			double sa=ABS(nx-th);
			sa=min(sa,ABS(PI*2/B-sa));
			//Pt pa=pLL(Pt(1,0),Pt(cos(PI*2*C/B),sin(PI*2*C/B)),Pt(0,0),Pt(cos(sa),sin(sa)))*r;
			if(iSSstrict(Pt(1,0),Pt(cos(PI*2*C/B),sin(PI*2*C/B)),Pt(0,0),Pt(cos(sa),sin(sa))*(dis/r-EPS))){
			//pa.ABS()+EPS<(hb[i]-p[j]).ABS()){
				dame=true;break;
			}
		}
		if(!dame){return 1;}
	}
	return 0;
}
int main(){
	int a,b,c;
	while(scanf("%d%d%d",&a,&b,&c),a){
		A=a;B=b;C=c;
		for(int i=0;i<a;i++){
			double X,Y;scanf("%lf%lf",&X,&Y);
			p[i]=Pt(X,Y);
		}
		double ret=2000;
		double kakai=0;
		for(int i=0;i<a;i++)for(int j=i+1;j<a;j++)kakai=max(kakai,(p[i]-p[j]).ABS()/2);
		vector<pair<int,int> > rp;
		for(int i=0;i<a;i++)for(int j=0;j<b;j++)rp.push_back(make_pair(i,j));
		//random_shuffle(rp.begin(),rp.end());
		for(int x=0;x<rp.size();x++){
			if(a==50&&b==50&&c==24&&rand()%15==0)continue;
			int i=rp[x].first;
			int j=rp[x].second;
			if(check(i,j,ret-1e-7)){
				double left=kakai;
				double right=ret;
				for(int k=0;k<50;k++){
					double M=(left+right)/2;
					if(check(i,j,M))right=M;
					else left=M;
					if(right-left<1e-8)break;
				}
				ret=min(ret,left);
			}
			//printf("%Lf\n",ret);
		}
		printf("%.12f\n",ret);
	}
}
accuracy: 1
time_ms: 7960
memory_kb: 1264
final_rank: 14

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
vector<P> vil;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	const S &segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, const R &r, const int &i, const int &j){
	MSQ msq;
	P gp = vil[i] - temp.segment(j)[0]*r;
	temp.copy(r, gp, msq);
	const S &l = msq.segment(j);
	vector<P> p;
	P b(0), u = l.dir();
	if(u < b) swap(b, u);
	RREP(i, n){
		S l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S &s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f || u < b) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vil = vector<P>(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2000
memory_kb: 1648
final_rank: 1

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
vector<P> vil;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, int i, int j){
	MSQ msq;
	P gp = vil[i] - temp.segment(j)[0]*r;
	temp.copy(r, gp, msq);
	L l = msq.segment(j);
	vector<P> p;
	P b(0), u = l.dir();
	if(u < b) swap(b, u);
	RREP(i, n){
		S l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f || u < b) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vil = vector<P>(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2490
memory_kb: 1648
final_rank: 3

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	P gp = vil[i] - temp.segment(j)[0]*r;
	temp.copy(r, gp, msq);
	L l = msq.segment(j);
	vector<P> p;
	P b(0), u = l.dir();
	if(u < b) swap(b, u);
	REP(i, n){
		S l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f || u < b) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2500
memory_kb: 1648
final_rank: 4

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	P gp = vil[i] - temp.segment(j)[0]*r;
	temp.copy(r, gp, msq);
	L l = msq.segment(j);
	vector<P> p;
	P b(0), u = l.dir();
	if(u < b) swap(b, u);
	REP(i, n){
		S l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2680
memory_kb: 1648
final_rank: 7

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		S l2(vil[i], vil[i] + msq.segment(j).dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
					const P q = crosspoint(s, l2) - l2[0];
					p.push_back(q);
					ll = min(ll, q);
					rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2640
memory_kb: 1652
final_rank: 5

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		S l2(vil[i], vil[i] + msq.segment(j).dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				if(sig(outp(s.dir(), l2.dir()))){
					const P q = crosspoint(s, l2) - l2[0];
					p.push_back(q);
					ll = min(ll, q);
					rr = max(rr, q);
				}
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2680
memory_kb: 1648
final_rank: 7

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		L l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				if(sig(outp(s.dir(), l2.dir()))){
					const P q = crosspoint(s, l2) - l2[0];
					p.push_back(q);
					ll = min(ll, q);
					rr = max(rr, q);
				}
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2670
memory_kb: 1648
final_rank: 6

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		L l2(vil[i], vil[i] + l.dir());
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
			}
		}
		u = min(rr, u);
		b = max(ll, b);
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 3750
memory_kb: 1648
final_rank: 10

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		L l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				const P q = crosspoint(s, l2) - l2[0];
				p.push_back(q);
				ll = min(ll, q);
				rr = max(rr, q);
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		REP(i, n)REP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2720
memory_kb: 1524
final_rank: 2

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
  
#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
  
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}
  
namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2; // s-t-p
		return 0;							  // s-p-t
	}
	  
	  
	struct L : public vector<P>{  // line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		inline P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > -EPS && inp(p-at(1), -dir()) > -EPS ? TRUE: FALSE;
			return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};
  
	inline BOOL intersect(const S &s, const L &l){
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false);
		return m[0] + B / A * (m[1] - m[0]);
	}
	  
	struct Arrangement{
		struct AEdge{
			int u, v, t;
			R cost;
			AEdge(int u=0, int v=0, int t=0, R cost=0)
				:u(u), v(v), t(t), cost(cost){}
		};
		typedef vector<vector<AEdge>> AGraph;
		vector<P> p;
		AGraph g;
		Arrangement(){}
		Arrangement(vector<S> seg){
			int m = seg.size();
			REP(i, m){
				p.push_back(seg[i][0]);
				p.push_back(seg[i][1]);
				REP(j, i) if(sig(outp(seg[i].dir(), seg[j].dir())) && intersect(seg[i], seg[j]) == TRUE)
					p.push_back(crosspoint(seg[i], seg[j]));
			}
			sort(ALL(p)); UNIQUE(p);
			int n=p.size();
			g.resize(n);
			REP(i, m){
				S &s = seg[i];
				vector<pair<R, int>> ps;
				REP(j, n) if(s.online(p[j])) ps.emplace_back(norm(p[j] - s[0]), j);
				sort(ALL(ps));
				REP(j, (int)ps.size()-1){
					const int u=ps[j].second;
					const int v=ps[j+1].second;
					g[u].emplace_back(u, v, 0, abs(p[u] - p[v]));
					g[v].emplace_back(v, u, 0, abs(p[u] - p[v]));
				}
			}
		}
		  
		int getIdx(P q){
			auto it = lower_bound(ALL(p), q);
			if(it == p.end() || *it != q) return -1;
			return it - p.begin();
		}
	};
  
	struct DualGraph{
		struct DEdge{
			int u, v, f, l;
			R a;
			DEdge(int u, int v, R a):u(u),v(v),f(0),l(0){
				while(PI < a) a -= 2*PI;
				while(a < -PI) a += 2*PI;
				this->a = a;
			}
			bool operator==(const DEdge &opp) const{
				return v==opp.v;
			}
			bool operator<(const DEdge &opp) const{
				return a>opp.a;
			}
			bool operator<(const R &opp) const{
				return a>opp;
			}
			friend ostream& operator<<(ostream &os, const DEdge &t) { return os<<"("<<t.u<<","<<t.v<<","<<t.a*180/PI<<")";}
		};
		  
		int n;
		vector<P> p;
		vector<vector<DEdge>> g;
		DualGraph(const vector<P> &p):p(p),g(p.size()),n(p.size()){}
		void add_edge(const int s, const int t){
			R a = arg(p[t]-p[s]);
			g[s].emplace_back(s, t, a);
			g[t].emplace_back(t, s, a > 0 ? a-PI : a+PI);
		}
		void add_polygon(int s, G &t, R a){
			auto e = lower_bound(ALL(g[s]), a-EPS);
			if(e == g[s].end()) e = g[s].begin();
			if(e->f) return;
			e->f = 1;
			t.push_back(p[s]);
			add_polygon(e->v, t, e->a > 0 ? e->a-PI : e->a+PI);
		}
		  
		G dual(){
			REP(i, n){
				sort(ALL(g[i]));
				UNIQUE(g[i]);
			}
			int s = min_element(ALL(p)) - p.begin();
			G poly;
			add_polygon(s, poly, -PI*(R).5);
			return poly;
		}
	};
  
#undef SELF
#undef at
}
  
using namespace geom;
  
namespace std{
	bool operator<(const P &a, const P &b){return sig(a.X-b.X) ? a.X < b.X : a.Y+EPS < b.Y;}
	bool operator==(const P &a, const P &b){return abs(a-b) < EPS;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
  
int n, m, k;
struct MSQ : public G{
	MSQ(){}
	vector<P> p;
	vector<S> s;
	int m, k;
	MSQ(int m, int k):m(m), k(k){
		REP(i, m) p.push_back(polar((R)1, 2*PI*i/m + PI*(R).5));
		REP(i, m) s.emplace_back(p[i], p[(i+k)%m]);
		Arrangement a(s);
		DualGraph dg(a.p);
		REP(i, a.g.size())REP(j, a.g[i].size()){
			int u = a.g[i][j].u;
			int v = a.g[i][j].v;
			if(u < v) dg.add_edge(u, v);
		}
		(G &)(*this) = dg.dual();
		reverse(this->begin(), this->end());
	}
	void copy(R r, P c, MSQ &msq)const {
		msq.resize(size());
		msq.p.resize(p.size());
		msq.s.resize(s.size());
		msq.m = m;
		msq.k = k;
		REP(i, size())   msq[i] = at(i)*r + c;
		REP(i, p.size()) msq.p[i] = p[i]*r + c;
		REP(i, s.size()) msq.s[i] = S(msq.p[i], msq.p[(i+k)%m]);
	}
	S segment(int i)const {
		return s[i];
	}
};
int convex_contains(const MSQ &msq, const P &g, const P &p) {
	const int n = msq.size();
	int a = 0, b = n;
	const P pg = p-g;
	while (a+1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (outp(msq[a]-g, pg) > 0 && outp(msq[c]-g, pg) < 0) b = c;
		else  a = c;
	}
	b %= n;
	if (outp(msq[a] - p, msq[b] - p) < -EPS) return 0;
	return 1;
}
bool check(const MSQ & temp, R r, const vector<P> &vil, int i, int j){
	MSQ msq;
	L l = temp.segment(j);
	P gp = vil[i] - l[0]*r;
	temp.copy(r, gp, msq);
	vector<P> p;
	P b(0), u = msq.segment(j)[1];
	if(u < b) swap(b, u);
	REP(i, n){
		L l2(vil[i], vil[i] + l.dir());
		int f = 0;
		P ll(INF, INF), rr(-INF, -INF);
		REP(j, m){
			const S s = msq.segment(j);
			if(intersect(s, l2)){
				if(sig(outp(s.dir(), l2.dir()))){
					const P q = crosspoint(s, l2) - l2[0];
					p.push_back(q);
					ll = min(ll, q);
					rr = max(rr, q);
				}
				f = 1;
			}
		}
		u = min(rr, u);
		b = max(ll, b);
		if(!f) return false;
	}
	FOR(q, p){
		if(*q < b || u < *q) continue;
		if([&](){
			REP(i, n) if(!convex_contains(msq, gp, vil[i] + *q)) return 0;
			return 1;
		}()) return true;
	}
	return false;
}
  
int main(){
	ios::sync_with_stdio(false);
	while(cin >> n >> m >> k, n){
		MSQ temp(m, k);
		vector<P> vil(n);
		REP(i, n) cin >> vil[i];
		R best = 2000;
		RREP(i, n)RREP(j, m){
			if(!check(temp, best-EPS, vil, i, j)) continue;
			R l=1., r = best;
			while(r-l>1e-6){
				R m = (l+r)*(R).5;
				if(check(temp, m, vil, i, j)) r = m;
				else l = m;
			}
			best = r;
		}
		printf("%.10f\n", (double)best);
	}
	return 0;
}
accuracy: 1
time_ms: 2720
memory_kb: 1648
final_rank: 9