Problem:
Problem I: Explosion
Problem
大魔王めぐみんは地上に生存する$N$人の勇者を倒そうと考えている。
めぐみんは$M$回まで爆発魔法を唱えることができる。
爆発魔法は任意の座標を中心に半径$r$以内に存在している勇者を消滅させる魔法である。
勇者はとても痩せているため大きさは考慮しなくてよい。
$M$回の爆発魔法は全て同じ大きさの半径で唱えるものとする。
勇者を全滅させるのに必要最小限の半径の魔法を使うことにした。
爆発魔法の半径の大きさを最小化せよ。
Input
$N$ $M$
$x_1$ $y_1$
...
$x_N$ $y_N$
入力は以下の形式で与えられる。
1行目に 勇者の数 $N$ 、唱える爆発の数 $M$ が整数で与えられる。
2行目以降にそれぞれの勇者$i$の座標 $x_i$ $,$ $y_i$ が整数で与えられる。
Constraints
入力は以下の条件を満たす。
$1 \leq M \leq N \leq 14$
$0 \leq x_i $,$ y_i \leq 10^5$
Output
爆発魔法の半径の最小値を実数で出力せよ。
$10^{-3}$を超える絶対誤差を含んではならない。
Sample Input 1
5 2
0 0
5 5
10 10
100 100
200 200
Sample Output 1
70.710678118755
Sample Input 2
10 5
321 675
4312 6534
312 532
412 6543
21 43
654 321
543 0
32 5
41 76
5 1
Sample Output 2
169.824909833728
Sample Input 3
14 3
312 342
4893 432
321 4
389 4
23 543
0 0
1 1
2 2
432 12
435 32
1 5
2 10
100 100
20 50
Sample Output 3
218.087711712613
Sample Input 4
5 2
0 0
0 0
0 0
0 0
0 0
Sample Output 4
0.000000000001

Submitted solutions:

code_snippet: // AOJ #3034
// Explosion 2025.2.6

#include <bits/stdc++.h>
using namespace std;
 
struct Point { double x, y; };
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N, M;
    cin >> N >> M;
    vector<Point> pts(N);
    for (int i = 0; i < N; i++){
        cin >> pts[i].x >> pts[i].y;
    }

    if(M >= N){
        cout << fixed << setprecision(12) << 0.0 << endl;
        return 0;
    }
    
    double eps = 1e-9;
    // 上界の設定：入力点間の最大距離
    double high = 0.0;
    for (int i = 0; i < N; i++){
        for (int j = i+1; j < N; j++){
            double dx = pts[i].x - pts[j].x;
            double dy = pts[i].y - pts[j].y;
            double d = sqrt(dx*dx + dy*dy);
            high = max(high, d);
        }
    }
    // N==1 の場合 high==0 のはず．
 
    // 二分探索のための関数：r で全員を M 回以内の爆発でカバーできるか
    auto canCover = [&](double r) -> bool {
        vector<int> candidateMasks;
 
        // (1) 各勇者の座標を中心にする候補
        for (int i = 0; i < N; i++){
            int mask = 0;
            for (int j = 0; j < N; j++){
                double dx = pts[j].x - pts[i].x;
                double dy = pts[j].y - pts[i].y;
                if (sqrt(dx*dx + dy*dy) <= r + eps)
                    mask |= (1 << j);
            }
            candidateMasks.push_back(mask);
        }
 
        // (2) 各2点間の円の交点を候補とする
        for (int i = 0; i < N; i++){
            for (int j = i+1; j < N; j++){
                double dx = pts[j].x - pts[i].x;
                double dy = pts[j].y - pts[i].y;
                double d = sqrt(dx*dx + dy*dy);
                if (d > 2*r + eps) continue;
 
                double mx = (pts[i].x + pts[j].x) / 2.0;
                double my = (pts[i].y + pts[j].y) / 2.0;
                double h = sqrt(max(0.0, r*r - (d/2.0)*(d/2.0)));
                double ux = -dy / d;
                double uy = dx / d;
 
                for (int sign = -1; sign <= 1; sign += 2){
                    double cx = mx + sign * h * ux;
                    double cy = my + sign * h * uy;
                    int mask = 0;
                    for (int k = 0; k < N; k++){
                        double dx2 = pts[k].x - cx;
                        double dy2 = pts[k].y - cy;
                        if(sqrt(dx2*dx2 + dy2*dy2) <= r + eps)
                            mask |= (1 << k);
                    }
                    candidateMasks.push_back(mask);
                }
            }
        }
 
        int FULL = (1 << N) - 1;
        vector<int> dp(1 << N, INT_MAX);
        dp[0] = 0;
        for (int mask = 0; mask < (1 << N); mask++){
            if(dp[mask] == INT_MAX) continue;
            for (int cmask : candidateMasks){
                int newMask = mask | cmask;
                dp[newMask] = min(dp[newMask], dp[mask] + 1);
            }
        }
        return dp[FULL] <= M;
    };
 
    double lo = 0.0, hi = high;
    for (int iter = 0; iter < 60; iter++){
        double mid = (lo + hi) / 2.0;
        if (canCover(mid)) hi = mid;
        else lo = mid;
    }
    cout << fixed << setprecision(12) << hi << endl;
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3596
final_rank: 1

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

// #define int long long
#define rep(i, n) for (long long i = (long long)(0); i < (long long)(n); ++i)
#define reps(i, n) for (long long i = (long long)(1); i <= (long long)(n); ++i)
#define rrep(i, n) for (long long i = ((long long)(n)-1); i >= 0; i--)
#define rreps(i, n) for (long long i = ((long long)(n)); i > 0; i--)
#define irep(i, m, n) for (long long i = (long long)(m); i < (long long)(n); ++i)
#define ireps(i, m, n) for (long long i = (long long)(m); i <= (long long)(n); ++i)
#define SORT(v, n) sort(v, v + n);
#define REVERSE(v, n) reverse(v, v+n);
#define vsort(v) sort(v.begin(), v.end());
#define all(v) v.begin(), v.end()
#define mp(n, m) make_pair(n, m);
#define cout(d) cout<<d<<endl;
#define coutd(d) cout<<std::setprecision(10)<<d<<endl;
#define cinline(n) getline(cin,n);
#define replace_all(s, b, a) replace(s.begin(),s.end(), b, a);
#define PI (acos(-1))
#define FILL(v, n, x) fill(v, v + n, x);
#define sz(x) long long(x.size())

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vs = vector<string>;
using vpll = vector<pair<ll, ll>>;
using vtp = vector<tuple<ll,ll,ll>>;
using vb = vector<bool>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const ll INF = 1e9;
const ll MOD = 1e9+7;
const ll LINF = 1e18;

// https://drken1215.hatenablog.com/entry/2020/01/13/230900

/* 幾何ライブラリ */
using DD = double;
const DD EPS = 1e-10;        // to be set appropriately
DD torad(int deg) {return (DD)(deg) * PI / 180;}
DD todeg(DD ang) {return ang * 180 / PI;}

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream& operator << (ostream &s, const Point &p) {return s << '(' << p.x << ", " << p.y << ')';}
};
inline Point operator + (const Point &p, const Point &q) {return Point(p.x + q.x, p.y + q.y);}
inline Point operator - (const Point &p, const Point &q) {return Point(p.x - q.x, p.y - q.y);}
inline Point operator * (const Point &p, DD a) {return Point(p.x * a, p.y * a);}
inline Point operator * (DD a, const Point &p) {return Point(a * p.x, a * p.y);}
inline Point operator * (const Point &p, const Point &q) {return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x);}
inline Point operator / (const Point &p, DD a) {return Point(p.x / a, p.y / a);}
inline Point conj(const Point &p) {return Point(p.x, -p.y);}
inline Point rot(const Point &p, DD ang) {return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y);}
inline Point rot90(const Point &p) {return Point(-p.y, p.x);}
inline DD cross(const Point &p, const Point &q) {return p.x * q.y - p.y * q.x;}
inline DD dot(const Point &p, const Point &q) {return p.x * q.x + p.y * q.y;}
inline DD norm(const Point &p) {return dot(p, p);}
inline DD abs(const Point &p) {return sqrt(dot(p, p));}
inline DD amp(const Point &p) {DD res = atan2(p.y, p.x); if (res < 0) res += PI*2; return res;}
inline bool eq(const Point &p, const Point &q) {return abs(p - q) < EPS;}
inline bool operator < (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y);}
inline bool operator > (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y);}
inline Point operator / (const Point &p, const Point &q) {return p * conj(q) / norm(q);}

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream& operator << (ostream &s, const Line &l) {return s << '{' << l[0] << ", " << l[1] << '}';}
};

// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b-a, c-a) > EPS) return 1;
    if (cross(b-a, c-a) < -EPS) return -1;
    return 0;
}

// 円や直線の交点
vector<Point> crosspoint(const Line &l, const Line &m) {
    vector<Point> res;
    DD d = cross(m[1] - m[0], l[1] - l[0]);
    if (abs(d) < EPS) return vector<Point>();
    res.push_back(l[0] + (l[1] - l[0]) * cross(m[1] - m[0], m[1] - l[0]) / d);
    return res;
}

// 外心
Point gaisin(Point a, Point b, Point c) {
    Line ab((a+b)/2, (a+b)/2 + rot90(a-b));
    Line bc((b+c)/2, (b+c)/2 + rot90(b-c));
    return crosspoint(ab, bc)[0];
}

// 最小包含円
double minimum_bounding_circle(vector<Point>& v){
  ll n=v.size();
  if(n<=1) return 0;
  
  vector<Point> cond; // 候補
  rep(i,n) irep(j,i+1,n){
    cond.push_back((v[i]+v[j])/2);
    irep(k,j+1,n){
      if(simple_ccw(v[i],v[j],v[k])==0) continue;
      auto p=gaisin(v[i],v[j],v[k]);
      cond.push_back(p);
    }
  }
  
  double res=INF;
  for(auto e: cond){
    double tmp=0;
    rep(i,n) chmax(tmp,abs(e-v[i]));
    chmin(res,tmp);
  }
  
  return res;
}

const ll maxn=1<<14;
double dp1[maxn];     // 最小包含円の半径
double dp2[15][maxn]; // i個の円で集合sを包含するときの最大の円の半径の最小値

signed main()
{
  cin.tie( 0 ); ios::sync_with_stdio( false );
  
  ll n,m; cin>>n>>m;
  vector<Point> v;
  set<Point> exist;
  rep(i,n){
    ll x,y; cin>>x>>y;
    Point p=Point(x,y);
    if(exist.count(p)) continue;
    v.push_back(p);
    exist.insert(p);
  }
  n=v.size();
  
  if(n<=m){
    cout<<0<<endl;
    return 0;
  }
  
  rep(s,1<<n){
    vector<Point> points;
    rep(i,n) if(s>>i&1) points.push_back(v[i]);
    double r=minimum_bounding_circle(points);
    dp1[s]=r;
  }
  
  // NOTE: ここでINF初期化する理由
  // 以下のループの中で、以下の様にdp2の遷移を行っている
  // dp[i][_]が求まっているとして、i+1個の円で集合sを包含するときの円の最小値は、
  // sをbitとbit2の2つの集合に分けて、bitはi個の円、bit2は1個の円で包含することを考える
  // すると遷移は、chmin(dp2[i+1][s],max(dp2[i][bit],dp1[bit2])) と表される
  // このとき、i=0の場合において遷移の過程でdp2[i][bit]が未定義の場合が有り得る
  // dp2[0][1]は0個の円で1個の点を包含する訳だが不可能である(そもそもdp2[0][_]には遷移元が存在しない)
  // この場合dpテーブルを更新しないためにINF初期化する必要がある
  // memo: 一方、dp2[2][1]など、点より多い円で包含する場合は遷移の過程でテーブルが埋められるので問題ない
  // 例えば、dp2[2][1]はmax(dp2[1][0],dp1[1])から更新されるが、dp2[1][0]はmax(dp2[0][0],dp1[0])から0と初期化されるはずである
  rep(i,m+1) rep(s,1<<n) dp2[i][s]=INF;
  dp2[0][0]=0;
  rep(i,m){
    rep(bit,1<<n){
      ll rem=((1<<n)-1)-bit; // 2^n における、集合bitの補集合
      
      // bitの補集合remの、部分集合全てについてのループ
      for(ll bit2=rem; bit2>=0 ;bit2--){
        bit2&=rem;
        
        // NOTE: ここでやっていること
        // まず、max(dp2[i][bit],dp1[bit2])について
        // dp2[i][bit]はi個の円で集合bitを覆うとき、その円の中でも最大のものが最小となるときの半径が格納されている
        // dp1[bit2]は集合bit2の最小包含円の半径である
        // よってmax()は、i+1個の円でbit, bit2を覆うときの最大の円の半径を取ってきている
        // 上記で求めた最大の半径をmax_valueとして、素直にdp2の遷移を実装した結果が以下となる
        // chmin(dp2[i+1][bit|bit2],max_value)
        chmin(dp2[i+1][bit|bit2], max(dp2[i][bit],dp1[bit2]));
      }
    }
  }
  
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp1[s]<<endl;
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp2[m][s]<<endl;
  
  cout<<std::setprecision(10)<<dp2[m][(1<<n)-1]<<endl;
  
}
accuracy: 1
time_ms: 200
memory_kb: 5088
final_rank: 8

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

// #define int long long
#define rep(i, n) for (long long i = (long long)(0); i < (long long)(n); ++i)
#define reps(i, n) for (long long i = (long long)(1); i <= (long long)(n); ++i)
#define rrep(i, n) for (long long i = ((long long)(n)-1); i >= 0; i--)
#define rreps(i, n) for (long long i = ((long long)(n)); i > 0; i--)
#define irep(i, m, n) for (long long i = (long long)(m); i < (long long)(n); ++i)
#define ireps(i, m, n) for (long long i = (long long)(m); i <= (long long)(n); ++i)
#define SORT(v, n) sort(v, v + n);
#define REVERSE(v, n) reverse(v, v+n);
#define vsort(v) sort(v.begin(), v.end());
#define all(v) v.begin(), v.end()
#define mp(n, m) make_pair(n, m);
#define cout(d) cout<<d<<endl;
#define coutd(d) cout<<std::setprecision(10)<<d<<endl;
#define cinline(n) getline(cin,n);
#define replace_all(s, b, a) replace(s.begin(),s.end(), b, a);
#define PI (acos(-1))
#define FILL(v, n, x) fill(v, v + n, x);
#define sz(x) long long(x.size())

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vs = vector<string>;
using vpll = vector<pair<ll, ll>>;
using vtp = vector<tuple<ll,ll,ll>>;
using vb = vector<bool>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const ll INF = 1e9;
const ll MOD = 1e9+7;
const ll LINF = 1e18;

// https://drken1215.hatenablog.com/entry/2020/01/13/230900

/* 幾何ライブラリ */
using DD = double;
const DD EPS = 1e-10;        // to be set appropriately
DD torad(int deg) {return (DD)(deg) * PI / 180;}
DD todeg(DD ang) {return ang * 180 / PI;}

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream& operator << (ostream &s, const Point &p) {return s << '(' << p.x << ", " << p.y << ')';}
};
inline Point operator + (const Point &p, const Point &q) {return Point(p.x + q.x, p.y + q.y);}
inline Point operator - (const Point &p, const Point &q) {return Point(p.x - q.x, p.y - q.y);}
inline Point operator * (const Point &p, DD a) {return Point(p.x * a, p.y * a);}
inline Point operator * (DD a, const Point &p) {return Point(a * p.x, a * p.y);}
inline Point operator * (const Point &p, const Point &q) {return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x);}
inline Point operator / (const Point &p, DD a) {return Point(p.x / a, p.y / a);}
inline Point conj(const Point &p) {return Point(p.x, -p.y);}
inline Point rot(const Point &p, DD ang) {return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y);}
inline Point rot90(const Point &p) {return Point(-p.y, p.x);}
inline DD cross(const Point &p, const Point &q) {return p.x * q.y - p.y * q.x;}
inline DD dot(const Point &p, const Point &q) {return p.x * q.x + p.y * q.y;}
inline DD norm(const Point &p) {return dot(p, p);}
inline DD abs(const Point &p) {return sqrt(dot(p, p));}
inline DD amp(const Point &p) {DD res = atan2(p.y, p.x); if (res < 0) res += PI*2; return res;}
inline bool eq(const Point &p, const Point &q) {return abs(p - q) < EPS;}
inline bool operator < (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y);}
inline bool operator > (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y);}
inline Point operator / (const Point &p, const Point &q) {return p * conj(q) / norm(q);}

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream& operator << (ostream &s, const Line &l) {return s << '{' << l[0] << ", " << l[1] << '}';}
};

// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b-a, c-a) > EPS) return 1;
    if (cross(b-a, c-a) < -EPS) return -1;
    return 0;
}

// 円や直線の交点
vector<Point> crosspoint(const Line &l, const Line &m) {
    vector<Point> res;
    DD d = cross(m[1] - m[0], l[1] - l[0]);
    if (abs(d) < EPS) return vector<Point>();
    res.push_back(l[0] + (l[1] - l[0]) * cross(m[1] - m[0], m[1] - l[0]) / d);
    return res;
}

// 外心
Point gaisin(Point a, Point b, Point c) {
    Line ab((a+b)/2, (a+b)/2 + rot90(a-b));
    Line bc((b+c)/2, (b+c)/2 + rot90(b-c));
    return crosspoint(ab, bc)[0];
}

// 最小包含円
double minimum_bounding_circle(vector<Point>& v){
  ll n=v.size();
  if(n<=1) return 0;
  
  vector<Point> cond; // 候補
  rep(i,n) irep(j,i+1,n){
    cond.push_back((v[i]+v[j])/2);
    irep(k,j+1,n){
      if(simple_ccw(v[i],v[j],v[k])==0) continue;
      auto p=gaisin(v[i],v[j],v[k]);
      cond.push_back(p);
    }
  }
  
  double res=INF;
  for(auto e: cond){
    double tmp=0;
    rep(i,n) chmax(tmp,abs(e-v[i]));
    chmin(res,tmp);
  }
  
  return res;
}

const ll maxn=1<<14;
double dp1[maxn]; // 最小包含円の半径
double dp2[15][maxn]; // i個の円で集合sを包含するときの最大の円の半径の最小値

signed main()
{
  cin.tie( 0 ); ios::sync_with_stdio( false );
  
  ll n,m; cin>>n>>m;
  vector<Point> v;
  set<Point> exist;
  rep(i,n){
    ll x,y; cin>>x>>y;
    Point p=Point(x,y);
    if(exist.count(p)) continue;
    v.push_back(p);
    exist.insert(p);
  }
  n=v.size();
  
  if(n<=m){
    cout<<0<<endl;
    return 0;
  }
  
  rep(s,1<<n){
    vector<Point> points;
    rep(i,n) if(s>>i&1) points.push_back(v[i]);
    double r=minimum_bounding_circle(points);
    dp1[s]=r;
  }
  
  rep(i,m+1) rep(s,1<<n) dp2[i][s]=INF;
  dp2[0][0]=0;
  rep(i,m){
    rep(bit,1<<n){
      ll rem=((1<<n)-1)-bit;
      for(ll bit2=rem; bit2>=0 ;bit2--){
        bit2&=rem;
        chmin(dp2[i+1][bit|bit2], max(dp2[i][bit],dp1[bit2]));
      }
    }
  }
  
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp1[s]<<endl;
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp2[m][s]<<endl;
  
  cout<<std::setprecision(10)<<dp2[m][(1<<n)-1]<<endl;
  
  
}
accuracy: 1
time_ms: 200
memory_kb: 5048
final_rank: 6

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

// #define int long long
#define rep(i, n) for (long long i = (long long)(0); i < (long long)(n); ++i)
#define reps(i, n) for (long long i = (long long)(1); i <= (long long)(n); ++i)
#define rrep(i, n) for (long long i = ((long long)(n)-1); i >= 0; i--)
#define rreps(i, n) for (long long i = ((long long)(n)); i > 0; i--)
#define irep(i, m, n) for (long long i = (long long)(m); i < (long long)(n); ++i)
#define ireps(i, m, n) for (long long i = (long long)(m); i <= (long long)(n); ++i)
#define SORT(v, n) sort(v, v + n);
#define REVERSE(v, n) reverse(v, v+n);
#define vsort(v) sort(v.begin(), v.end());
#define all(v) v.begin(), v.end()
#define mp(n, m) make_pair(n, m);
#define cout(d) cout<<d<<endl;
#define coutd(d) cout<<std::setprecision(10)<<d<<endl;
#define cinline(n) getline(cin,n);
#define replace_all(s, b, a) replace(s.begin(),s.end(), b, a);
#define PI (acos(-1))
#define FILL(v, n, x) fill(v, v + n, x);
#define sz(x) long long(x.size())

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vs = vector<string>;
using vpll = vector<pair<ll, ll>>;
using vtp = vector<tuple<ll,ll,ll>>;
using vb = vector<bool>;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

const ll INF = 1e9;
const ll MOD = 1e9+7;
const ll LINF = 1e18;

// https://drken1215.hatenablog.com/entry/2020/01/13/230900

/* 幾何ライブラリ */
using DD = double;
const DD EPS = 1e-10;        // to be set appropriately
DD torad(int deg) {return (DD)(deg) * PI / 180;}
DD todeg(DD ang) {return ang * 180 / PI;}

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream& operator << (ostream &s, const Point &p) {return s << '(' << p.x << ", " << p.y << ')';}
};
inline Point operator + (const Point &p, const Point &q) {return Point(p.x + q.x, p.y + q.y);}
inline Point operator - (const Point &p, const Point &q) {return Point(p.x - q.x, p.y - q.y);}
inline Point operator * (const Point &p, DD a) {return Point(p.x * a, p.y * a);}
inline Point operator * (DD a, const Point &p) {return Point(a * p.x, a * p.y);}
inline Point operator * (const Point &p, const Point &q) {return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x);}
inline Point operator / (const Point &p, DD a) {return Point(p.x / a, p.y / a);}
inline Point conj(const Point &p) {return Point(p.x, -p.y);}
inline Point rot(const Point &p, DD ang) {return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y);}
inline Point rot90(const Point &p) {return Point(-p.y, p.x);}
inline DD cross(const Point &p, const Point &q) {return p.x * q.y - p.y * q.x;}
inline DD dot(const Point &p, const Point &q) {return p.x * q.x + p.y * q.y;}
inline DD norm(const Point &p) {return dot(p, p);}
inline DD abs(const Point &p) {return sqrt(dot(p, p));}
inline DD amp(const Point &p) {DD res = atan2(p.y, p.x); if (res < 0) res += PI*2; return res;}
inline bool eq(const Point &p, const Point &q) {return abs(p - q) < EPS;}
inline bool operator < (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y);}
inline bool operator > (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y);}
inline Point operator / (const Point &p, const Point &q) {return p * conj(q) / norm(q);}

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream& operator << (ostream &s, const Line &l) {return s << '{' << l[0] << ", " << l[1] << '}';}
};

// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b-a, c-a) > EPS) return 1;
    if (cross(b-a, c-a) < -EPS) return -1;
    return 0;
}

// 円や直線の交点
vector<Point> crosspoint(const Line &l, const Line &m) {
    vector<Point> res;
    DD d = cross(m[1] - m[0], l[1] - l[0]);
    if (abs(d) < EPS) return vector<Point>();
    res.push_back(l[0] + (l[1] - l[0]) * cross(m[1] - m[0], m[1] - l[0]) / d);
    return res;
}

// 外心
Point gaisin(Point a, Point b, Point c) {
    Line ab((a+b)/2, (a+b)/2 + rot90(a-b));
    Line bc((b+c)/2, (b+c)/2 + rot90(b-c));
    return crosspoint(ab, bc)[0];
}

// 最小包含円
double minimum_bounding_circle(vector<Point>& v){
  ll n=v.size();
  if(n<=1) return 0;
  
  vector<Point> cond; // 候補
  rep(i,n) irep(j,i+1,n){
    cond.push_back((v[i]+v[j])/2);
    irep(k,j+1,n){
      if(simple_ccw(v[i],v[j],v[k])==0) continue;
      auto p=gaisin(v[i],v[j],v[k]);
      cond.push_back(p);
    }
  }
  
  double res=INF;
  for(auto e: cond){
    double tmp=0;
    rep(i,n) chmax(tmp,abs(e-v[i]));
    chmin(res,tmp);
  }
  
  return res;
}

const ll maxn=1<<14;
double dp1[maxn]; // 最小包含円の半径
double dp2[15][maxn]; // i個の円で集合sを包含するときの最大の円の半径の最小値

signed main()
{
  cin.tie( 0 ); ios::sync_with_stdio( false );
  
  ll n,m; cin>>n>>m;
  vector<Point> v;
  set<Point> exist;
  rep(i,n){
    ll x,y; cin>>x>>y;
    Point p=Point(x,y);
    if(exist.count(p)) continue;
    v.push_back(p);
    exist.insert(p);
  }
  n=v.size();
  
  if(n<=m){
    cout<<0<<endl;
    return 0;
  }
  
  rep(s,1<<n){
    vector<Point> points;
    rep(i,n) if(s>>i&1) points.push_back(v[i]);
    double r=minimum_bounding_circle(points);
    dp1[s]=r;
  }
  
  rep(i,m+1) rep(s,1<<n) dp2[i][s]=INF;
  dp2[0][0]=0;
  rep(i,m){
    rep(bit,1<<n){
      ll rem=((1<<n)-1)-bit;
      for(ll bit2=rem; ;bit2=(bit2-1)&rem){
        chmin(dp2[i+1][bit|bit2], max(dp2[i][bit],dp1[bit2]));
        if(!bit2) break;
      }
    }
  }
  
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp1[s]<<endl;
  // rep(s,1<<n) cout<<std::setprecision(10)<<dp2[m][s]<<endl;
  
  cout<<std::setprecision(10)<<dp2[m][(1<<n)-1]<<endl;
  
  
}
accuracy: 1
time_ms: 200
memory_kb: 5108
final_rank: 9

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



#define EPS 0.0000001

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;
	}

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

int N,M;
int POW[15];
double dp[15][1 << 15];
double NUM = 20000000;
Point point[15];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//交点を求める関数
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(x1 != x2){
		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_minus(Point a,Point b){
    Point ret;

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

    return ret;
}

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;
}

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

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;
}

//線分ではなく直線と点の距離
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);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}

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]);
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d",&N,&M);

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

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

	for(int i = 0; i <= M; i++){
		for(int state = 0; state < POW[N]; state++){

			dp[i][state] = BIG_NUM;
		}
	}

	vector<int> V;


	Line line1,line2;
	Point center;

	for(int state = 1; state < POW[N]; state++){

		V.clear();

		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				V.push_back(loop);
			}
		}

		if(V.size() == 1){

			dp[1][state] = 0;
			//printf("dp[1][%d]:%.3lf\n",state,dp[1][state]);
			continue;

		}else if(V.size() == 2){

			dp[1][state] = calc_dist(point[V[0]],point[V[1]])/2;

			int work_state = state;

			center = Point((point[V[0]].x+point[V[1]].x)/2,(point[V[0]].y+point[V[1]].y)/2);

			for(int k = 0; k < N; k++){
				if(k == V[0] || k == V[1])continue;

				if(calc_dist(center,point[k]) <= dp[1][state]){

					work_state += POW[k];
				}
			}

			dp[1][work_state] = min(dp[1][work_state],dp[1][state]);

			continue;
		}

		//3点以上

		//2点を直径とする
		for(int a = 0; a < V.size()-1; a++){
			for(int b = a+1; b < V.size(); b++){

				center = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);

				double tmp_dist = calc_dist(point[V[a]],point[V[b]])/2;

				bool FLG = true;
				for(int k = 0; k < V.size(); k++){

					if(k == a || k == b)continue;

					if(calc_dist(center,point[V[k]]) > tmp_dist){
						FLG = false;
						break;
					}
				}

				if(FLG){

					dp[1][state] = min(dp[1][state],tmp_dist);
				}
			}
		}

		//3点を通る
		for(int a = 0; a < V.size()-2; a++){
			for(int b = a+1; b < V.size()-1; b++){
				for(int c = b+1; c < V.size(); c++){

					double slope1 = calc_slope(Line(point[V[a]],point[V[b]]));
					double slope2 = calc_slope(Line(point[V[b]],point[V[c]]));

					if(fabs(slope1-slope2) < EPS){ //一直線上

						continue;

					}else{

						Point mid1 = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);
						Point mid2 = Point((point[V[b]].x+point[V[c]].x)/2,(point[V[b]].y+point[V[c]].y)/2);

						if(fabs(slope1-DBL_MAX) < EPS){ //垂直

							line1.p[0] = Point(-NUM,mid1.y);
							line1.p[1] = Point(NUM,mid1.y);

						}else if(fabs(slope1) < EPS){ //水平

							line1.p[0] = Point(mid1.x,NUM);
							line1.p[1] = Point(mid1.x,-NUM);

						}else{

							slope1 = (-1.0)/slope1;

							line1.p[0] = Point(mid1.x-NUM,mid1.y-NUM*slope1);
							line1.p[1] = Point(mid1.x+NUM,mid1.y+NUM*slope1);
						}

						if(fabs(slope2-DBL_MAX) < EPS){ //垂直

							line2.p[0] = Point(-NUM,mid2.y);
							line2.p[1] = Point(NUM,mid2.y);

						}else if(fabs(slope2) < EPS){ //水平

							line2.p[0] = Point(mid2.x,NUM);
							line2.p[1] = Point(mid2.x,-NUM);

						}else{

							slope2 = (-1.0)/slope2;

							line2.p[0] = Point(mid2.x-NUM,mid2.y-NUM*slope2);
							line2.p[1] = Point(mid2.x+NUM,mid2.y+NUM*slope2);
						}

						center =  calc_Cross_Point(line1,line2);
					}


					double tmp_dist = calc_dist(center,point[V[a]]);

					bool FLG = true;
					for(int k = 0; k < V.size(); k++){

						if(k == a || k == b || k == c)continue;

						if(calc_dist(center,point[V[k]]) > tmp_dist){

							FLG = false;
							break;
						}
					}

					if(FLG){

						dp[1][state] = min(dp[1][state],tmp_dist);
					}
				}
			}

		}
	}


	int tmp_state;

	for(int state = 1; state < POW[N]-1; state++){

		V.clear();
		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				//Do nothing

			}else{

				V.push_back(loop);
			}
		}

		for(int i = 1; i <= M-1; i++){
			if(fabs(dp[i][state]-BIG_NUM) < EPS)continue;

			for(int a = 1; a < POW[V.size()]; a++){ //足し合わせる状態

				tmp_state = 0;

				for(int loop = 0; loop < V.size(); loop++){
					if(a & POW[loop]){

						tmp_state += POW[V[loop]];
					}
				}

				dp[i+1][state+tmp_state] = min(dp[i+1][state+tmp_state],max(dp[i][state],dp[1][tmp_state]));
			}
		}
	}

	double ans = BIG_NUM;
	for(int i = 1; i <= M; i++){

		ans = min(ans,dp[i][POW[N]-1]);
	}

	printf("%.10lf\n",ans);

	return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 4832
final_rank: 10

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

#define EPS 0.00001

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;
	}

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

int N,M;
int POW[15];
double dp[15][1 << 15];
double NUM = 20000000;
Point point[15];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//交点を求める関数
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(x1 != x2){
		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_minus(Point a,Point b){
    Point ret;

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

    return ret;
}

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;
}

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

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;
}

//線分ではなく直線と点の距離
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);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}

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]);
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d",&N,&M);

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

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

	for(int i = 0; i <= M; i++){
		for(int state = 0; state < POW[N]; state++){

			dp[i][state] = BIG_NUM;
		}
	}

	vector<int> V;


	Line line1,line2;
	Point center;

	for(int state = 1; state < POW[N]; state++){

		V.clear();

		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				V.push_back(loop);
			}
		}

		if(V.size() == 1){

			dp[1][state] = 0;
			//printf("dp[1][%d]:%.3lf\n",state,dp[1][state]);
			continue;

		}else if(V.size() == 2){

			dp[1][state] = calc_dist(point[V[0]],point[V[1]])/2;

			int work_state = state;

			center = Point((point[V[0]].x+point[V[1]].x)/2,(point[V[0]].y+point[V[1]].y)/2);

			for(int k = 0; k < N; k++){
				if(k == V[0] || k == V[1])continue;

				if(calc_dist(center,point[k]) <= dp[1][state]){

					work_state += POW[k];
				}
			}

			dp[1][work_state] = min(dp[1][work_state],dp[1][state]);

			continue;
		}

		//3点以上

		//2点を直径とする
		for(int a = 0; a < V.size()-1; a++){
			for(int b = a+1; b < V.size(); b++){

				center = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y,point[V[b]].y)/2);

				double tmp_dist = calc_dist(center,point[V[a]]);

				bool FLG = true;
				for(int k = 0; k < V.size(); k++){

					if(k == a || k == b)continue;

					if(calc_dist(center,point[V[k]]) > tmp_dist+EPS){
						FLG = false;
						break;
					}
				}

				if(FLG){

					dp[1][state] = min(dp[1][state],tmp_dist);
				}
			}
		}

		//3点を通る
		for(int a = 0; a < V.size()-2; a++){
			for(int b = a+1; b < V.size()-1; b++){
				for(int c = b+1; c < V.size(); c++){

					double slope1 = calc_slope(Line(point[V[a]],point[V[b]]));
					double slope2 = calc_slope(Line(point[V[b]],point[V[c]]));

					if(fabs(slope1-slope2) < EPS){ //一直線上

						continue;

					}else{

						Point mid1 = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);
						Point mid2 = Point((point[V[b]].x+point[V[c]].x)/2,(point[V[b]].y+point[V[c]].y)/2);

						if(fabs(slope1-DBL_MAX) < EPS){ //垂直

							line1.p[0] = Point(-NUM,mid1.y);
							line1.p[1] = Point(NUM,mid1.y);

						}else if(fabs(slope1) < EPS){ //水平

							line1.p[0] = Point(mid1.x,NUM);
							line1.p[1] = Point(mid1.x,-NUM);

						}else{

							slope1 = (-1.0)/slope1;

							line1.p[0] = Point(mid1.x-NUM,mid1.y-NUM*slope1);
							line1.p[1] = Point(mid1.x+NUM,mid1.y+NUM*slope1);
						}

						if(fabs(slope2-DBL_MAX) < EPS){ //垂直

							line2.p[0] = Point(-NUM,mid2.y);
							line2.p[1] = Point(NUM,mid2.y);

						}else if(fabs(slope2) < EPS){ //水平

							line2.p[0] = Point(mid2.x,NUM);
							line2.p[1] = Point(mid2.x,-NUM);

						}else{

							slope2 = (-1.0)/slope2;

							line2.p[0] = Point(mid2.x-NUM,mid2.y-NUM*slope2);
							line2.p[1] = Point(mid2.x+NUM,mid2.y+NUM*slope2);
						}

						/*if(!is_Cross(line1,line2)){

							printf("交わらない!! V[a]:%d V[b]:%d V[c]:%d\n",V[a],V[b],V[c]);
							printf("slope1:%.1lf slope2:%.1lf\n",slope1,slope2);
							return 0;
						}*/

						center =  calc_Cross_Point(line1,line2);
					}


					double tmp_dist = calc_dist(center,point[V[a]]);

					bool FLG = true;
					for(int k = 0; k < V.size(); k++){

						if(k == a || k == b || k == c)continue;

						if(calc_dist(center,point[V[k]]) > tmp_dist+EPS){

							FLG = false;
							break;
						}
					}

					if(FLG){

						dp[1][state] = min(dp[1][state],tmp_dist);
					}
				}
			}

		}

	/*	if(fabs(dp[1][state]-BIG_NUM) < EPS){

			printf("BUG!! state:%d\n",state);
			return 0;
		}*/


		//printf("dp[1][%d]:%.3lf\n",state,dp[1][state]);
	}

	int tmp_state;

	for(int state = 1; state < POW[N]-1; state++){

		V.clear();
		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				//Do nothing

			}else{

				V.push_back(loop);
			}
		}

		for(int i = 1; i <= M-1; i++){
			if(fabs(dp[i][state]-BIG_NUM) < EPS)continue;

			for(int a = 1; a < POW[V.size()]; a++){ //足し合わせる状態

				tmp_state = 0;

				for(int loop = 0; loop < V.size(); loop++){
					if(a & POW[loop]){

						tmp_state += POW[V[loop]];
					}
				}

				dp[i+1][state+tmp_state] = min(dp[i+1][state+tmp_state],max(dp[i][state],dp[1][tmp_state]));
			}
		}
	}

	double ans = BIG_NUM;
	for(int i = 1; i <= M; i++){

		ans = min(ans,dp[i][POW[N]-1]);
	}

	printf("%.10lf\n",ans);

	return 0;
}
accuracy: 0.6545454545454545
time_ms: 360
memory_kb: 3688
final_rank: 16

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#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;
	}

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

int N,M;
int POW[15];
double dp[15][1 << 15];
double NUM = 200000;
Point point[15];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//交点を求める関数
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(x1 != x2){
		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_minus(Point a,Point b){
    Point ret;

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

    return ret;
}

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;
}

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

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;
}

//線分ではなく直線と点の距離
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);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}

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]);
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d",&N,&M);

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

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

	for(int i = 0; i <= M; i++){
		for(int state = 0; state < POW[N]; state++){

			dp[i][state] = BIG_NUM;
		}
	}

	vector<int> V;


	Line line1,line2;
	Point center;

	for(int state = 1; state < POW[N]; state++){

		V.clear();

		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				V.push_back(loop);
			}
		}

		if(V.size() == 1){

			dp[1][state] = 0;
			continue;

		}else if(V.size() == 2){

			dp[1][state] = calc_dist(point[V[0]],point[V[1]])/2;
			continue;
		}

		//3点以上

		//2点を直径とする
		for(int a = 0; a < V.size()-1; a++){
			for(int b = a+1; b < V.size(); b++){

				center = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y,point[V[b]].y)/2);

				double tmp_dist = calc_dist(center,point[V[a]]);

				bool FLG = true;
				for(int k = 0; k < V.size(); k++){

					if(k == a || k == b)continue;

					if(calc_dist(center,point[V[k]]) > tmp_dist+EPS){
						FLG = false;
						break;
					}
				}

				if(FLG){

					dp[1][state] = min(dp[1][state],tmp_dist);
				}
			}
		}

		//3点を通る
		for(int a = 0; a < V.size()-2; a++){
			for(int b = a+1; b < V.size()-1; b++){
				for(int c = b+1; c < V.size(); c++){

					double slope1 = calc_slope(Line(point[V[a]],point[V[b]]));
					double slope2 = calc_slope(Line(point[V[b]],point[V[c]]));

					if(fabs(slope1-slope2) < EPS){ //一直線上

						continue;

					}else{

						Point mid1 = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);
						Point mid2 = Point((point[V[b]].x+point[V[c]].x)/2,(point[V[b]].y+point[V[c]].y)/2);

						if(fabs(slope1-DBL_MAX) < EPS){ //垂直

							line1.p[0] = Point(-NUM,mid1.y);
							line1.p[1] = Point(NUM,mid1.y);

						}else if(fabs(slope1) < EPS){ //水平

							line1.p[0] = Point(mid1.x,NUM);
							line1.p[1] = Point(mid1.x,-NUM);

						}else{

							slope1 = (-1.0)/slope1;

							line1.p[0] = Point(mid1.x-NUM,mid1.y-NUM*slope1);
							line1.p[1] = Point(mid1.x+NUM,mid1.y+NUM*slope1);
						}

						if(fabs(slope2-DBL_MAX) < EPS){ //垂直

							line2.p[0] = Point(-NUM,mid2.y);
							line2.p[1] = Point(NUM,mid2.y);

						}else if(fabs(slope2) < EPS){ //水平

							line2.p[0] = Point(mid2.x,NUM);
							line2.p[1] = Point(mid2.x,-NUM);

						}else{

							slope2 = (-1.0)/slope2;

							line2.p[0] = Point(mid2.x-NUM,mid2.y-NUM*slope2);
							line2.p[1] = Point(mid2.x+NUM,mid2.y+NUM*slope2);
						}

						center =  calc_Cross_Point(line1,line2);
					}


					double tmp_dist = calc_dist(center,point[V[a]]);

					bool FLG = true;
					for(int k = 0; k < V.size(); k++){

						if(k == a || k == b || k == c)continue;

						if(calc_dist(center,point[V[k]]) > tmp_dist+EPS){

							FLG = false;
							break;
						}
					}

					if(FLG){

						dp[1][state] = min(dp[1][state],tmp_dist);
					}
				}
			}
		}
	}

	int tmp_state;

	for(int state = 1; state < POW[N]-1; state++){

		V.clear();
		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				//Do nothing

			}else{

				V.push_back(loop);
			}
		}

		for(int i = 1; i <= M-1; i++){
			if(fabs(dp[i][state]-BIG_NUM) < EPS)continue;

			for(int a = 1; a < POW[V.size()]; a++){ //足し合わせる状態

				tmp_state = 0;

				for(int loop = 0; loop < V.size(); loop++){
					if(a & POW[loop]){

						tmp_state += POW[V[loop]];
					}
				}

				dp[i+1][state+tmp_state] = min(dp[i+1][state+tmp_state],max(dp[i][state],dp[1][tmp_state]));
			}
		}
	}

	double ans = BIG_NUM;
	for(int i = 1; i <= M; i++){

		ans = min(ans,dp[i][POW[N]-1]);
	}

	printf("%.10lf\n",ans);

	return 0;
}
accuracy: 0.16363636363636364
time_ms: 350
memory_kb: 3800
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#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;
	}

	double x,y;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};

int N,M;
int POW[15];
double dp[15][1 << 15];
double NUM = 200000;
Point point[15];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//交点を求める関数
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(x1 != x2){
		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_minus(Point a,Point b){
    Point ret;

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

    return ret;
}

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;
}

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

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;
}

//線分ではなく直線と点の距離
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);
}

//線分と線分の距離
double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}

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]);
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 15; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d",&N,&M);

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

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

	for(int i = 0; i <= M; i++){
		for(int state = 0; state < POW[N]; state++){

			dp[i][state] = BIG_NUM;
		}
	}

	vector<int> V;


	Line line1,line2;
	Point center;

	for(int state = 1; state < POW[N]; state++){

		V.clear();

		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				V.push_back(loop);
			}
		}

		if(V.size() == 1){

			dp[1][state] = 0;
			continue;

		}else if(V.size() == 2){

			dp[1][state] = calc_dist(point[V[0]],point[V[1]])/2;
			continue;
		}

		//3点以上
		for(int a = 0; a < V.size()-2; a++){
			for(int b = a+1; b < V.size()-1; b++){
				for(int c = b+1; c < V.size(); c++){

					double slope1 = calc_slope(Line(point[V[a]],point[V[b]]));
					double slope2 = calc_slope(Line(point[V[b]],point[V[c]]));

					if(fabs(slope1-slope2) < EPS){ //一直線上

						double dist1 = calc_dist(point[V[a]],point[V[b]]);
						double dist2 = calc_dist(point[V[a]],point[V[c]]);
						double dist3 = calc_dist(point[V[b]],point[V[c]]);

						if(dist1 > dist2 && dist1 > dist3){

							center = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);

						}else if(dist2 > dist1 && dist2 > dist3){

							center = Point((point[V[a]].x+point[V[c]].x)/2,(point[V[a]].y+point[V[c]].y)/2);

						}else{

							center = Point((point[V[b]].x+point[V[c]].x)/2,(point[V[b]].y+point[V[c]].y)/2);
						}

					}else{

						Point mid1 = Point((point[V[a]].x+point[V[b]].x)/2,(point[V[a]].y+point[V[b]].y)/2);
						Point mid2 = Point((point[V[b]].x+point[V[c]].x)/2,(point[V[b]].y+point[V[c]].y)/2);

						if(fabs(slope1-DBL_MAX) < EPS){ //垂直

							line1.p[0] = Point(-NUM,mid1.y);
							line1.p[1] = Point(NUM,mid1.y);

						}else if(fabs(slope1) < EPS){ //水平

							line1.p[0] = Point(mid1.x,NUM);
							line1.p[1] = Point(mid1.x,-NUM);

						}else{

							slope1 = (-1.0)/slope1;

							line1.p[0] = Point(mid1.x-NUM,mid1.y-NUM*slope1);
							line1.p[1] = Point(mid1.x+NUM,mid1.y+NUM*slope1);
						}

						if(fabs(slope2-DBL_MAX) < EPS){ //垂直

							line2.p[0] = Point(-NUM,mid2.y);
							line2.p[1] = Point(NUM,mid2.y);

						}else if(fabs(slope2) < EPS){ //水平

							line2.p[0] = Point(mid2.x,NUM);
							line2.p[1] = Point(mid2.x,-NUM);

						}else{

							slope2 = (-1.0)/slope2;

							line2.p[0] = Point(mid2.x-NUM,mid2.y-NUM*slope2);
							line2.p[1] = Point(mid2.x+NUM,mid2.y+NUM*slope2);
						}

						center =  calc_Cross_Point(line1,line2);
					}


					double tmp_dist = calc_dist(center,point[V[a]]);

					bool FLG = true;
					for(int k = 0; k < V.size(); k++){

						if(calc_dist(center,point[V[k]]) > tmp_dist+EPS){

							FLG = false;
							break;
						}
					}

					if(FLG){

						dp[1][state] = min(dp[1][state],tmp_dist);
					}
				}
			}
		}

		//printf("dp[1][%d]:%.1lf\n",state,dp[1][state]);
	}

	int tmp_state;

	for(int state = 1; state < POW[N]-1; state++){

		V.clear();
		for(int loop = 0; loop < N; loop++){
			if(state & POW[loop]){

				//Do nothing

			}else{

				V.push_back(loop);
			}
		}

		for(int i = 1; i <= M-1; i++){
			if(fabs(dp[i][state]-BIG_NUM) < EPS)continue;

			for(int a = 1; a < POW[V.size()]; a++){ //足し合わせる状態

				tmp_state = 0;

				for(int loop = 0; loop < V.size(); loop++){
					if(a & POW[loop]){

						tmp_state += POW[V[loop]];
					}
				}

				dp[i+1][state+tmp_state] = min(dp[i+1][state+tmp_state],max(dp[i][state],dp[1][tmp_state]));
			}
		}
	}

	double ans = BIG_NUM;
	for(int i = 1; i <= M; i++){

		ans = min(ans,dp[i][POW[N]-1]);
	}

	printf("%.10lf\n",ans);

	return 0;
}
accuracy: 0.03636363636363636
time_ms: 360
memory_kb: 3784
final_rank: 20

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

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

/* 幾何ライブラリ */
using DD = double;
const DD INF = 1LL<<60;      // to be set appropriately
const DD EPS = 1e-10;        // to be set appropriately
const DD PI = acosl(-1.0);
DD torad(int deg) {return (DD)(deg) * PI / 180;}
DD todeg(DD ang) {return ang * 180 / PI;}

/* Point */
struct Point {
    DD x, y;
    Point(DD x = 0.0, DD y = 0.0) : x(x), y(y) {}
    friend ostream& operator << (ostream &s, const Point &p) {return s << '(' << p.x << ", " << p.y << ')';}
};
inline Point operator + (const Point &p, const Point &q) {return Point(p.x + q.x, p.y + q.y);}
inline Point operator - (const Point &p, const Point &q) {return Point(p.x - q.x, p.y - q.y);}
inline Point operator * (const Point &p, DD a) {return Point(p.x * a, p.y * a);}
inline Point operator * (DD a, const Point &p) {return Point(a * p.x, a * p.y);}
inline Point operator * (const Point &p, const Point &q) {return Point(p.x * q.x - p.y * q.y, p.x * q.y + p.y * q.x);}
inline Point operator / (const Point &p, DD a) {return Point(p.x / a, p.y / a);}
inline Point conj(const Point &p) {return Point(p.x, -p.y);}
inline Point rot(const Point &p, DD ang) {return Point(cos(ang) * p.x - sin(ang) * p.y, sin(ang) * p.x + cos(ang) * p.y);}
inline Point rot90(const Point &p) {return Point(-p.y, p.x);}
inline DD cross(const Point &p, const Point &q) {return p.x * q.y - p.y * q.x;}
inline DD dot(const Point &p, const Point &q) {return p.x * q.x + p.y * q.y;}
inline DD norm(const Point &p) {return dot(p, p);}
inline DD abs(const Point &p) {return sqrt(dot(p, p));}
inline DD amp(const Point &p) {DD res = atan2(p.y, p.x); if (res < 0) res += PI*2; return res;}
inline bool eq(const Point &p, const Point &q) {return abs(p - q) < EPS;}
inline bool operator < (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x < q.x : p.y < q.y);}
inline bool operator > (const Point &p, const Point &q) {return (abs(p.x - q.x) > EPS ? p.x > q.x : p.y > q.y);}
inline Point operator / (const Point &p, const Point &q) {return p * conj(q) / norm(q);}

/* Line */
struct Line : vector<Point> {
    Line(Point a = Point(0.0, 0.0), Point b = Point(0.0, 0.0)) {
        this->push_back(a);
        this->push_back(b);
    }
    friend ostream& operator << (ostream &s, const Line &l) {return s << '{' << l[0] << ", " << l[1] << '}';}
};

// 1：a-bから見てcは左側(反時計回り)、-1：a-bから見てcは右側(時計回り)、0：一直線上
int simple_ccw(const Point &a, const Point &b, const Point &c) {
    if (cross(b-a, c-a) > EPS) return 1;
    if (cross(b-a, c-a) < -EPS) return -1;
    return 0;
}

// 円や直線の交点
vector<Point> crosspoint(const Line &l, const Line &m) {
    vector<Point> res;
    DD d = cross(m[1] - m[0], l[1] - l[0]);
    if (abs(d) < EPS) return vector<Point>();
    res.push_back(l[0] + (l[1] - l[0]) * cross(m[1] - m[0], m[1] - l[0]) / d);
    return res;
}

// 外心
Point gaisin(Point a, Point b, Point c) {
    Line ab((a+b)/2, (a+b)/2 + rot90(a-b));
    Line bc((b+c)/2, (b+c)/2 + rot90(b-c));
    return crosspoint(ab, bc)[0];
}

// 最小包含円
DD mic(const vector<Point> &v) {
    int N = (int)v.size();
    if (N <= 1) return 0;

    // 候補
    vector<Point> alt;
    for (int i = 0; i < N; ++i) {
        for (int j = i+1; j < N; ++j) {
            alt.push_back( (v[i] + v[j]) / 2 );
            for (int k = j+1; k < N; ++k) {
                if (simple_ccw(v[i], v[j], v[k]) == 0) continue;
                auto r = gaisin(v[i], v[j], v[k]);
                alt.push_back(r);
            }
        }
    }

    // 調べる
    DD res = INF;
    for (auto r : alt) {
        DD tmp = 0;
        for (auto p : v) chmax(tmp, abs(p - r));
        chmin(res, tmp);
    }
    return res;
}


int main() {
    int N, M; cin >> N >> M;
    vector<Point> v(N);
    for (int i = 0; i < N; ++i) cin >> v[i].x >> v[i].y;

    // pre
    vector<DD> need(1<<N, 0);
    for (int bit = 0; bit < (1<<N); ++bit) {
        vector<Point> part;
        for (int i = 0; i < N; ++i) {
            if (bit & (1<<i)) part.push_back(v[i]);
        }
        need[bit] = mic(part);

        //cout << bit << ": " << need[bit] << endl;
    }
        
    // bitDP
    vector<vector<DD>> dp(M+1, vector<DD>(1<<N,INF));
    dp[0][0] = 0;
    for (int m = 0; m < M; ++m) {
        for (int bit = 0; bit < (1<<N); ++bit) {
            int rem = ((1<<N)-1) - bit;
            for (int bit2 = rem; ; bit2 = (bit2-1) & rem) {
                chmin(dp[m+1][bit|bit2], max(dp[m][bit], need[bit2]));
                if (!bit2) break;
            }
        }
    }
    
    cout << fixed << setprecision(10) << dp[M][(1<<N)-1] << endl;
}
accuracy: 1
time_ms: 210
memory_kb: 4968
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
struct Vector {
	double x, y;
	double length() const { return std::sqrt(x * x + y * y); }
	double dot(const Vector& that) const { return x * that.x + y * that.y; }
	double cross(const Vector& that) const { return x * that.y - y * that.x; }
	Vector rotate90() const { return Vector{ -y, x }; }
	Vector flip180() const { return Vector{ -x, -y }; }
};
Vector operator*(const Vector& vec, const double scala) { return Vector{ vec.x * scala, vec.y * scala }; }
Vector operator*(const double scala, const Vector& vec) { return Vector{ vec.x * scala, vec.y * scala }; }
struct Coordinate {
	double x, y;
	double distance_from(const Coordinate& that) const { return (*this - that).length(); }
	Coordinate mid_point(const Coordinate& that) const { return Coordinate{ (x + that.x) / 2, (y + that.y) / 2 }; }
	Vector operator-(const Coordinate& that) const { return Vector{ x - that.x, y - that.y }; }
};
Coordinate operator+(const Vector& vec, const Coordinate& coordinate) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
Coordinate operator+(const Coordinate& coordinate, const Vector& vec) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
constexpr double EPS = 0.000000001;
int remove_all(const std::vector<Coordinate>& bravers, int state, const double radius, const Coordinate center) {
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (bravers[i].distance_from(center) <= radius + EPS) {
			state ^= 1 << i;
		}
	}
	return state;
}
bool can_defeat(const std::vector<Coordinate>& bravers, const int state, const int rest, const double radius, std::vector<std::vector<int>> &memo) {
	if (state == 0) return true;
	if (rest == 0) return false;
	if (memo[rest][state] >= 0) return memo[rest][state] == 1;
	memo[rest][state] = 0;
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (can_defeat(bravers, remove_all(bravers, state, radius, bravers[i]), rest - 1, radius, memo)) {
			memo[rest][state] = 1;
			return true;
		}
		for (auto j = 0; j < i; ++j) if ((state & (1 << j)) != 0 && bravers[i].distance_from(bravers[j]) <= radius * 2 + EPS && EPS < bravers[i].distance_from(bravers[j])) {
			auto mid = bravers[i].mid_point(bravers[j]);
			auto vec = bravers[i] - bravers[j];
			auto catheti = vec.rotate90() * std::sqrt(radius * radius - vec.length() * vec.length() / 4) * (1 / vec.length());
			if (can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti), rest - 1, radius, memo) || can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti.flip180()), rest - 1, radius, memo)) {
				memo[rest][state] = 1;
				return true;
			}
		}
	}
	return false;
}
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<Coordinate> bravers(n); for (auto& braver : bravers) std::cin >> braver.x >> braver.y;
	std::vector<std::vector<int>> memo(m + 1, std::vector<int>(1 << n, -1));
	double min = 0.0;
	double max = 150000;
	while (min + 0.000001 < max) {
		auto mid = (min + max) / 2;
		for (auto& vec : memo) std::fill(vec.begin(), vec.end(), -1);
		if (can_defeat(bravers, (1 << n) - 1, m, mid, memo)) max = mid;
		else min = mid;
	}
	std::cout << std::setprecision(10) << std::fixed << max << '\n';
}
accuracy: 1
time_ms: 230
memory_kb: 3600
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
struct Vector {
	double x, y;
	double length() const { return std::sqrt(x * x + y * y); }
	double dot(const Vector& that) const { return x * that.x + y * that.y; }
	double cross(const Vector& that) const { return x * that.y - y * that.x; }
	Vector rotate90() const { return Vector{ -y, x }; }
	Vector flip180() const { return Vector{ -x, -y }; }
};
Vector operator*(const Vector& vec, const double scala) { return Vector{ vec.x * scala, vec.y * scala }; }
Vector operator*(const double scala, const Vector& vec) { return Vector{ vec.x * scala, vec.y * scala }; }
struct Coordinate {
	double x, y;
	double distance_from(const Coordinate& that) const { return (*this - that).length(); }
	Coordinate mid_point(const Coordinate& that) const { return Coordinate{ (x + that.x) / 2, (y + that.y) / 2 }; }
	Vector operator-(const Coordinate& that) const { return Vector{ x - that.x, y - that.y }; }
};
Coordinate operator+(const Vector& vec, const Coordinate& coordinate) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
Coordinate operator+(const Coordinate& coordinate, const Vector& vec) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
constexpr double EPS = 0.000000001;
int remove_all(const std::vector<Coordinate>& bravers, int state, const double radius, const Coordinate center) {
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (bravers[i].distance_from(center) <= radius + EPS) {
			state ^= 1 << i;
		}
	}
	return state;
}
bool can_defeat(const std::vector<Coordinate>& bravers, const int state, const int rest, const double radius, std::vector<std::vector<int>> &memo) {
	if (state == 0) return true;
	if (rest == 0) return false;
	if (memo[rest][state] >= 0) return memo[rest][state] == 1;
	memo[rest][state] = 0;
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (can_defeat(bravers, remove_all(bravers, state, radius, bravers[i]), rest - 1, radius, memo)) {
			memo[rest][state] = 1;
			return true;
		}
		for (auto j = 0; j < i; ++j) if ((state & (1 << j)) != 0 && bravers[i].distance_from(bravers[j]) <= radius * 2 + EPS && EPS < bravers[i].distance_from(bravers[j])) {
			auto mid = bravers[i].mid_point(bravers[j]);
			auto vec = bravers[i] - bravers[j];
			auto catheti = vec.rotate90() * std::sqrt(radius * radius - vec.length() * vec.length() / 4) * (1 / vec.length());
			if (can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti), rest - 1, radius, memo) || can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti.flip180()), rest - 1, radius, memo)) {
				memo[rest][state] = 1;
				return true;
			}
		}
	}
	return false;
}
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<Coordinate> bravers(n); for (auto& braver : bravers) std::cin >> braver.x >> braver.y;
	std::vector<std::vector<int>> memo(m + 1, std::vector<int>(1 << n, -1));
	double min = 0.0;
	double max = 15000;
	while (min + 0.000001 < max) {
		auto mid = (min + max) / 2;
		for (auto& vec : memo) std::fill(vec.begin(), vec.end(), -1);
		if (can_defeat(bravers, (1 << n) - 1, m, mid, memo)) max = mid;
		else min = mid;
	}
	std::cout << std::setprecision(10) << std::fixed << max << '\n';
}
accuracy: 0.07272727272727272
time_ms: 50
memory_kb: 3344
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
struct Vector {
	double x, y;
	double length() const { return std::sqrt(x * x + y * y); }
	double dot(const Vector& that) const { return x * that.x + y * that.y; }
	double cross(const Vector& that) const { return x * that.y - y * that.x; }
	Vector rotate90() const { return Vector{ -y, x }; }
	Vector flip180() const { return Vector{ -x, -y }; }
};
Vector operator*(const Vector& vec, const double scala) { return Vector{ vec.x * scala, vec.y * scala }; }
Vector operator*(const double scala, const Vector& vec) { return Vector{ vec.x * scala, vec.y * scala }; }
struct Coordinate {
	double x, y;
	double distance_from(const Coordinate& that) const { return (*this - that).length(); }
	Coordinate mid_point(const Coordinate& that) const { return Coordinate{ (x + that.x) / 2, (y + that.y) / 2 }; }
	Vector operator-(const Coordinate& that) const { return Vector{ x - that.x, y - that.y }; }
};
Coordinate operator+(const Vector& vec, const Coordinate& coordinate) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
Coordinate operator+(const Coordinate& coordinate, const Vector& vec) { return Coordinate{ vec.x + coordinate.x, vec.y + coordinate.y }; }
constexpr double EPS = 0.0000001;
int remove_all(const std::vector<Coordinate>& bravers, int state, const double radius, const Coordinate center) {
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (bravers[i].distance_from(center) <= radius + EPS) {
			state ^= 1 << i;
		}
	}
	return state;
}
bool can_defeat(const std::vector<Coordinate>& bravers, const int state, const int rest, const double radius, std::vector<std::vector<int>> &memo) {
	if (state == 0) return true;
	if (rest == 0) return false;
	if (memo[rest][state] >= 0) return memo[rest][state] == 1;
	memo[rest][state] = 0;
	for (auto i = 0; i < bravers.size(); ++i) if ((state & (1 << i)) != 0) {
		if (can_defeat(bravers, remove_all(bravers, state, radius, bravers[i]), rest - 1, radius, memo)) {
			memo[rest][state] = 1;
			return true;
		}
		for (auto j = 0; j < i; ++j) if ((state & (1 << j)) != 0 && bravers[i].distance_from(bravers[j]) <= radius * 2 + EPS && EPS < bravers[i].distance_from(bravers[j])) {
			auto mid = bravers[i].mid_point(bravers[j]);
			auto vec = bravers[i] - bravers[j];
			auto catheti = vec.rotate90() * std::sqrt(radius * radius - vec.length() * vec.length() / 4) * (1 / vec.length());
			if (can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti), rest - 1, radius, memo) || can_defeat(bravers, remove_all(bravers, state, radius, mid + catheti.flip180()), rest - 1, radius, memo)) {
				memo[rest][state] = 1;
				return true;
			}
		}
	}
	return false;
}
int main() {
	int n, m; std::cin >> n >> m;
	std::vector<Coordinate> bravers(n); for (auto& braver : bravers) std::cin >> braver.x >> braver.y;
	std::vector<std::vector<int>> memo(m + 1, std::vector<int>(1 << n, -1));
	double min = 0.0;
	double max = 15000;
	while (min + 0.0001 < max) {
		auto mid = (min + max) / 2;
		for (auto& vec : memo) std::fill(vec.begin(), vec.end(), -1);
		if (can_defeat(bravers, (1 << n) - 1, m, mid, memo)) max = mid;
		else min = mid;
	}
	std::cout << std::setprecision(10) << std::fixed << max << '\n';
}
accuracy: 0.07272727272727272
time_ms: 40
memory_kb: 3344
final_rank: 18

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef long double ld;
typedef complex<ld> Point;
const ld eps = 1e-6;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;
int n, m;
ld x[14], y[14];
ld d[14][14];
ld rd[1 << 14];
bool can(int s,ld r) {
	vector<int> v;
	rep(i, n) {
		if (s&(1 << i))v.push_back(i);
	}
	if (v.size() <= 1)return true;
	int len = v.size();
	rep(i, len) {
		Rep(j, i + 1, len) {
			int id = v[i], jd = v[j];
			if (2*r < d[id][jd])return false;
			ld X = (x[jd] - x[id]) / 2.0;
			ld Y = (y[jd] - y[id]) / 2.0;
			ld dist = sqrt(pow(r, 2) - pow(d[id][jd] / 2.0, 2));
			ld sr = d[id][jd] / 2.0;
			ld x3 = Y * dist / sr; ld y3 = -X * dist / sr;
			ld midx = (x[id] + x[jd]) / 2.0, midy = (y[id] + y[jd]) / 2.0;
			ld cx = x3 + midx, cy = y3 + midy;
			bool valid = true;
			rep(k, len) {
				int kd = v[k];
				ld dis = sqrt(pow(cx - x[kd], 2) + pow(cy - y[kd], 2));
				if (dis > r+eps) {
					valid = false; break;
				}
			}
			if (valid)return true;
			valid = true;
			cx = -x3 + midx, cy = -y3 + midy;
			rep(k, len) {
				int kd = v[k];
				ld dis = sqrt(pow(cx - x[kd], 2) + pow(cy - y[kd], 2));
				if (dis > r+eps) {
					valid = false; break;
				}
			}
			if (valid)return true;
		}
	}
	return false;
}
ld dp[1 << 14], cop[1 << 14];
int main() {
	cin >> n >> m;
	rep(i, n) {
		cin >> x[i] >> y[i];
	}
	rep(i, n) {
		rep(j, n) {
			d[i][j] = sqrt(pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2));
		}
	}
	rep(i, (1 << n)) {
		ld le = 0, ri = 200000;
		while (ri - le > eps) {
			ld r = (ri + le) / 2;
			if (can(i, r))ri = r;
			else le = r;
		}
		rd[i] = ri;
	}
	fill(dp, dp + (1 << n), mod);
	dp[0] = 0;
	rep(aa, m) {
		rep(j, (1 << n)) {
			cop[j] = dp[j];
		}
		rep(j, (1 << n)) {
			vector<int> v;
			rep(i, n) {
				if (j&(1 << i))continue;
				v.push_back(i);
			}
			int len = v.size();
			rep(i, (1 << len)) {
				int s = 0;
				rep(k, len) {
					if (i&(1 << k))s += (1 << v[k]);
				}
				cop[j + s] = min(cop[j + s], max(dp[j], rd[s]));
			}
		}
		rep(j, (1 << n)) {
			dp[j] = cop[j];
		}
	}
	cout << fixed << setprecision(5);
	cout << dp[(1 << n) - 1] << endl;
	//stop
	return 0;
}
accuracy: 1
time_ms: 2300
memory_kb: 4064
final_rank: 14

code_snippet: //典型的な前処理O(N * 2^N) + O(M * 3^N)のDPで、最小包含円を求めるのが本質。O(N^3)かけても間に合うのが
//優しいけど、ちょっとライブラリを探してきた。
#include <iostream>
#include <vector>
#include <complex>
#include <cassert>
#include <random>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define rep(i, n) for(i = 0; i < n; i++)
using namespace std;

void chmin(double &a, double b) { a = min(a, b); }

//BEGIN: https://tubo28.me/algorithm/minball/
using ld = double;
using P = complex<ld>;
double eps = 1e-12;
double cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }

template <class iter>
std::pair<P, ld> min_ball(iter left, iter right, int seed = 1333) {
    const int n = right - left;

    assert(n >= 1);
    if (n == 1) {
        return {*left, ld(0)};
    }

    std::mt19937 mt(seed);
    std::shuffle(left, right, mt);
    // std::random_shuffle(left, right); // simple but deprecated

    iter ps = left;
    using circle = std::pair<P, ld>;

    auto make_circle_3 = [](const P &a, const P &b, const P &c) -> circle {
        ld A = std::norm(b - c), B = std::norm(c - a), C = std::norm(a - b),
           S = cross(b - a, c - a);
        P p = (A * (B + C - A) * a + B * (C + A - B) * b + C * (A + B - C) * c) / (4 * S * S);
        ld r2 = std::norm(p - a);
        return {p, r2};
    };

    auto make_circle_2 = [](const P &a, const P &b) -> circle {
        P c = (a + b) / (ld)2;
        ld r2 = std::norm(a - c);
        return {c, r2};
    };

    auto in_circle = [](const P &a, const circle &c) -> bool {
        return std::norm(a - c.first) <= c.second + eps;
    };

    circle c = make_circle_2(ps[0], ps[1]);

    // MiniDisc
    for (int i = 2; i < n; ++i) {
        if (!in_circle(ps[i], c)) {
            // MiniDiscWithPoint
            c = make_circle_2(ps[0], ps[i]);
            for (int j = 1; j < i; ++j) {
                if (!in_circle(ps[j], c)) {
                    // MiniDiscWith2Points
                    c = make_circle_2(ps[i], ps[j]);
                    for (int k = 0; k < j; ++k) {
                        if (!in_circle(ps[k], c)) {
                            c = make_circle_3(ps[i], ps[j], ps[k]);
                        }
                    }
                }
            }
        }
    }
    return c;
}
//END

int n, m;
P p[14];
double radius[1 << 14];
double dp[15][1 << 14];

int main() {
	int i, j, k;
	
	cin >> n >> m;
	rep(i, n) {
		double x, y; cin >> x >> y;
		p[i] = P(x, y);
	}
	
	rep(i, (1 << n)) {
		if (i == 0) continue;
		vector<P> ps;
		rep(j, n) {
			if ((i >> j) % 2 == 1) {
				ps.push_back(p[j]);
			}
		}
		radius[i] = min_ball(ps.begin(), ps.end()).second;
		radius[i] = sqrt(radius[i]);
	}

	double INF = 1e+9;
	rep(i, n + 1) rep(j, (1 << n)) dp[i][j] = INF;
	
	dp[0][0] = 0;
	rep(i, m) {
		rep(j, (1 << n)) {
			//参考：https://kimiyuki.net/blog/2017/07/16/enumerate-sets-with-bit-manipulation/
			int z = (1 << n) - 1 - j;
			for (int y = 0; ; y = (y - z) & z) {
				chmin(dp[i + 1][j + y], max(dp[i][j], radius[y]));
				if (y == z) break;
			}
		}
	}
	
	double ans = INF;
	rep(i, m + 1) {
		chmin(ans, dp[i][(1 << n) - 1]);
	}
	printf("%.14f\n", ans);
	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5284
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double PI = acos(-1);
const double EPS = 1e-9; // 許容誤差^2
#define X real()
#define Y imag()
#define LE(n,m) ((n) - (m) < EPS)
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 点集合を含む最小の円の中心
Point minEnclosingCircle(const VP& ps) {
  Point c;
  double move = 0.5;
  rep(i,30) {  // 2^(-39-1) \approx 0.9e-12
    rep(t,30) {
      double max = 0;
      int k = 0;
      rep (j, ps.size()) if (max < norm(ps[j]-c)) {
        max = norm(ps[j]-c);
        k = j;
      }
      c += (ps[k]-c) * move;
    }
    move /= 2;
  }
  return c;
}

Point READ(){
    int x,y;
    cin >>x >>y;
    return Point(x,y);
}

const int N = 14;
const int INF = 19191919;
int dp[1<<N];

int main(){
    int n,m;
    cin >>n >>m;

    VP p(n);
    rep(i,n) p[i] = READ();

    vector<double> r(1<<n);
    for(int mask=1; mask<(1<<n); ++mask){
        VP pts;
        rep(i,n)if(mask>>i&1) pts.pb(p[i]);

        Point c = minEnclosingCircle(pts);
        for(Point pp:pts) r[mask] = max(r[mask], abs(pp-c));
    }

    auto check = [&](double lim){
        rep(i,1<<n) dp[i] = INF;
        dp[(1<<n)-1] = 0;

        for(int mask = (1<<n)-1; mask>0; --mask){
            int sub = mask;
            do{
                sub = sub-1;
                sub &= mask;
                int tgt = mask^sub;
                if(r[tgt] <= lim) dp[sub] = min(dp[sub], dp[mask]+1);
            }while(sub>0);
        }

        return dp[0]<=m;
    };

    double ng=0, ok = 500000;
    rep(loop,100){
        double mid = (ng+ok)/2;
        if(check(mid)) ok = mid;
        else ng = mid;
    }
    printf("%.10f\n", ok);
    return 0;
}
accuracy: 1
time_ms: 1800
memory_kb: 3468
final_rank: 12

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;


/* 幾何の基本 */

#include <complex>

typedef complex<ld> Point;


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

// 点の入力
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// 誤差つき等号判定
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// 内積
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// 外積
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// 直線の定義
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// 円の定義
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,cが反時計周りの順に並ぶ
//-1: a,b,cが時計周りの順に並ぶ
// 2: c,a,bの順に直線に並ぶ
//-2: a,b,cの順に直線に並ぶ
// 0: a,c,bの順に直線に並ぶ
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,cが反時計周りの順に並ぶ
	if (cross(nb, nc) < -eps) return -1; // a,b,cが時計周りの順に並ぶ
	if (dot(nb, nc) < 0) return 2;       // c,a,bの順に直線に並ぶ
	if (norm(nb) < norm(nc)) return -2;  // a,b,cの順に直線に並ぶ
	return 0;                          // a,c,bの順に直線に並ぶ
}


/* 交差判定 */

// 直線と直線の交差判定
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// 直線と線分の交差判定
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// 線分と線分の交差判定
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// 点の直線上判定
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// 点の線分上判定
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// 垂線の足
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//線対象の位置にある点
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// 直線と直線の交点
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// 直線と直線の交点
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// 線分と線分の交点
//　重なってる部分あるとassert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//先にisis_ssしてね
		assert(false);
		return Point(0, 0);
	}
}
// 線分と線分の交点
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// 直線と点の距離
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//直線と直線の距離
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// 直線と線分の距離
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// 線分と点の距離
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// 線分と線分の距離
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//直線と直線の二等分線のベクトル
Line line_bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}
//点と点の垂直二等分線　aを左に見ながら
Line point_bisection(const Point&a, const Point&b) {
	const Point cen((a + b) / 2.l);
	const Point vec = (b - a)*Point(0, 1);
	return Line(cen, cen + vec);
}

//三つの点からなる外心
Point outer_center(const vector<Point>&ps) {
	assert(ps.size() == 3);
	Line l1 = point_bisection(ps[0], ps[1]);
	Line l2 = point_bisection(ps[1], ps[2]);

	return is_ll(l1, l2);
}


//三つの直線からなる内心
//三つの直線が並行でないことは確かめといてね
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(line_bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(line_bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//三つの直線からなる傍心
//三つの直線が並行でないことは確かめといてね
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(line_bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(line_bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:並行
//c:並行でない
//三つの直線から同距離の位置を求める。
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(line_bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(line_bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(line_bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* 円 */

// 円と円の交点
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

/*
点が円の中にいるか
0 => out
1 => on
2 => in*/
int is_in_Circle(const  Point& p, const Circle &cir) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
/*
円lcが円rcの中にいるか
0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// 円と直線の交点
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// 円と線分の距離
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// 円と点の接線
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// 円と円の接線
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), nret.begin(), nret.end());
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//二つの円の重なり面積
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* 多角形 */

typedef vector<Point> Polygon;



//多角形(複数の点)の最小包含円をO(N=頂点数)で求めるアルゴリズム
//同一直線上に三つの点がないこと
#include<random>
Circle welzl(vector<Point>ps) {
	struct solver {
		Circle solve(vector<Point>&ps, vector<Point>&rs) {
			if (ps.empty() || rs.size() == 3) {
				if (rs.size() == 1) {
					return Circle(Point(rs[0]), 0);
				}
				else if (rs.size() == 2) {
					return Circle((rs[0] + rs[1]) / 2.0l, abs(rs[1] - rs[0]) / 2);
				}
				else if (rs.size() == 3) {
					vector<Line> ls(3);
					for (int i = 0; i < 3; ++i) {
						ls[i] = Line(rs[i], rs[(i + 1) % 3]);
					}
					Point center = outer_center(rs);
					return Circle(center, abs(center - rs[0]));
				}
				else {
					return Circle(Point(), 0);
				}
			}
			else {

				Point p_ba = ps.back();
				ps.pop_back();
				Circle d = solve(ps, rs);
				ps.push_back(p_ba);
				if (is_in_Circle(d, p_ba)) {
					return d;
				}
				else {
					rs.push_back(p_ba);
					ps.pop_back();
					auto ans = solve(ps, rs);
					ps.push_back(p_ba);
					rs.pop_back();
					return ans;
				}
			}
		}
	}so;
	std::random_device rd;
	std::mt19937 mt(rd());
	shuffle(ps.begin(), ps.end(), mt);
	vector<Point>rs;
	Circle ans = so.solve(ps, rs);
	return ans;
}
// 面積
ld get_area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	for (int j = 0; j<n; ++j) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//多角形の回転方向
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	for(int i=0;i<n;++i) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// 円の内外判定
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	for(int i=0;i<n;++i) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//円の内外判定2　高速
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// 凸包
//点や線を返すことも有り得るので注意
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//凸カット
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	for(int i=0;i<n;++i) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


/* アレンジメント */
void add_Point(vector<Point> &ps, const Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}

bool solve(vector<pair<ld, vector<int>>>bombs, int N, int M, ld len) {
	{
		auto n_bombs(bombs);
		n_bombs.clear();
		for (int i = 0; i < bombs.size(); ++i) {
			ld r=bombs[i].first;
			if(r<len)n_bombs.emplace_back(bombs[i]);
		}
		bombs=n_bombs;
	}

	vector<vector<int>>memo(M+1,vector<int>(1<<N));
	memo[0][0]=true;
	for (int b_use = 0; b_use < M; ++b_use) {
		for (int i = 0; i < (1 << N); ++i) {
			if(!memo[b_use][i])continue;

			for (auto&& now_b : bombs) {

				bitset<14>bs(i);
				for (int j = 0; j < N; ++j) {
					if(now_b.second[j])bs[j]=true;
				}
				memo[b_use+1][bs.to_ulong()]=true;
			}
		}
	}
	return memo[M][(1<<N)-1];
}



int main() {
	int N,M;cin>>N>>M;
	vector<Point>pos;
	for (int i = 0; i < N; ++i) {
		int x,y;cin>>x>>y;
		pos.push_back(Point(x,y));
	}

	vector<pair<ld,vector<int>>>bombs;
	{
		vector<int>v(3);
		for (v[0] = 0; v[0] < N; ++v[0]) {
			{
				ld r=1e-8;
				Circle c(pos[v[0]], r);

				vector<int>oks(N);
				for (int i = 0; i < N; ++i) {
					if (is_in_Circle(c, pos[i])) {
						oks[i] = true;
					}
				}
				bombs.push_back(make_pair(r, oks));
			}
			for ( v[1] = v[0] + 1; v[1] < N; ++v[1]) {
				{
					Point p((pos[v[0]]+pos[v[1]])/2.0l);
					const ld r = abs(p - pos[v[0]]);
					Circle c(p, r);

					vector<int>oks(N);
					for (int i = 0; i < N; ++i) {
						if (is_in_Circle(c, pos[i])) {
							oks[i] = true;
						}
					}
					bombs.push_back(make_pair(r, oks));
				}
				
				for (v[2] = v[1] + 1; v[2] < N; ++v[2]) {
					vector<Point>ci_pos(3);
					for (int i = 0; i < 3; ++i) {
						ci_pos[i]=pos[v[i]];
					}
					Line l1 = point_bisection(ci_pos[0], ci_pos[1]);
					Line l2 = point_bisection(ci_pos[1], ci_pos[2]);
					Point sv = l1.b - l1.a, tv = l2.b - l2.a;
					if (abs(cross(sv, tv)) < eps) {
						continue;
					}

					Point p(outer_center(ci_pos));
					const ld r=abs(p-ci_pos[0]);
					Circle c(p,r);

					vector<int>oks(N);
					for (int i = 0; i < N; ++i) {
						if (is_in_Circle(c, pos[i])) {
							oks[i]=true;
						}
					}
					bombs.push_back(make_pair(r,oks));
				}
			}
		}
	}
	{
		map<int, ld>mp;
		for (auto&& bomb : bombs) {
			bitset<14>bs;
			for (int i = 0; i < bomb.second.size(); ++i) {
				if(bomb.second[i])bs[i]=true;
			}
			if (mp.find(bs.to_ulong()) == mp.end()) {
				mp[bs.to_ulong()]=bomb.first;
			}
			else {
				mp[bs.to_ulong()]=min(bomb.first,mp[bs.to_ulong()]);
			}
		}
		auto n_bombs(bombs);
		n_bombs.clear();
		for (auto m : mp) {
			bitset<14>bs(m.first);
			vector<int>v(N);
			for (int i = 0; i < N; ++i) {
				if(bs[i])v[i]=true;
			}
			n_bombs.emplace_back(m.second,v);
		}
		bombs=n_bombs;
	}

	ld l=0,r=1e5;
	int time=30;
	while (time--) {
		ld m=(l+r)/2;
		if (solve(bombs, N, M, m)) {
			r=m;
		}
		else {
			l=m;
		}
	}
	cout<<setprecision(10)<<fixed;
	cout<<l<<endl;
	return 0;
}
accuracy: 1
time_ms: 970
memory_kb: 4004
final_rank: 11

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

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)
#define ALL(x) x.begin(),x.end()
#define EPS (1e-8)
#define equals(a,b) (fabs((a)-(b))<EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

typedef long long ll;
typedef pair<int,int> ii;

inline bool LT(double a,double b) { return !equals(a,b) && a < b; }
inline bool LTE(double a,double b) { return equals(a,b) || a < b; }


const int MAX_V = 2000; /////////////////////////////////////////////////////////////

struct Edge{ int to,cap,rev; };

vector<Edge> G[MAX_V];
bool used[MAX_V];

void add_edge(int from,int to,int cap){
  G[from].push_back((Edge){to,cap,(int)G[to].size()});
  G[to].push_back((Edge){from,0,(int)G[from].size()-1});
}

int dfs(int v,int t,int f){
  if( v == t ) return f;
  used[v] = true;
  for(int i=0;i<(int)G[v].size();i++){
    Edge &e = G[v][i];
    if( !used[e.to] && e.cap > 0 ){
      int d = dfs(e.to,t,min(f,e.cap));
      if( d > 0 ){
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

int max_flow(int s,int t){
  int flow = 0;
  for(;;){
    memset(used,0,sizeof(used));
    int f = dfs(s,t,INT_MAX);
    if( f == 0 ) return flow;
    flow += f;
  }
}

void init(int _size=MAX_V){ rep(i,_size) G[i].clear(); }



class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  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);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

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

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

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ return os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ return os << "( " << a.p1 << " , " << a.p2 << " )"; }

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

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

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

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

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev から cur へ行って next へ行く際の角度を求める
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}






int N,M;
Point ps[111];

int dp[20*20*20][1<<14];
int calc(int n,double r) {
  vector<int> vec;

  rep(i,n) {
    int bits = 0;
    rep(j,n) {
      if( LTE(abs(ps[i]-ps[j]),r) ) {
	bits |= (1<<j);
      }
    }
    vec.push_back(bits);
  }
  
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      if(i == j)continue;
      Point Rr = ps[i]-ps[j];
      if(abs(Rr) <= r*2+EPS || 1){
	Point UKPC,U,P1,P2;
	UKPC = (ps[i]+ps[j])*0.5;
	double l = abs(ps[i]-ps[j]) * 0.5;
	if( LTE(r * r - l * l,0)  ) continue;
	double T = sqrt(r*r-l*l);
	
	UKPC = (ps[i]+ps[j])*0.5;
	//P1 = UKPC + (ps[i]-point[j])/abs(point[i]-point[j])*polar(T,PI/2.0);
	Point uni = (ps[i] - ps[j]) / abs(ps[i]-ps[j]);
	//cout << "uni = " << uni <<endl;
	//P1 = UKPC + (T*((ps[i]-ps[j])/abs(ps[i]-ps[j])))*
	P1 = UKPC + rotate(uni,M_PI/2.0) * T;
	//P2 = UKPC + (ps[i]-point[j])/abs(point[i]-point[j])*polar(T,-PI/2.0);
	//P2 = UKPC + (ps[i]-ps[j])/abs(ps[i]-ps[j])*rotate(T,-M_PI/2.0);
	P2 = UKPC + rotate(uni,-M_PI/2.0) * T;
	/*
	puts("");
	cout << ps[i] << " and " << ps[j] << endl;
	cout << "UKPC = " << UKPC << endl;
	cout << "T = " << T << endl;
	cout << "P1 = " << P1 << ", P2 = " << P2 << endl;
	*/
	//cout << ps[i] << " and " << ps[j] <<endl;;
	double Calc;
	int bits = 0;
	for(int k=0;k<n;k++){
	  Calc = abs(P1-ps[k]);
	  if(fabs(Calc) < r+EPS){
	    bits |= (1<<k);
	  }
	}
	//bitset<5> BIT(bits);
	//cout << BIT << endl;
	vec.push_back(bits);
	bits = 0;
	for(int k=0;k<n;k++){
	  Calc = abs(P2-ps[k]);
	  if(fabs(Calc) < r+EPS){
	    bits |= (1<<k);
	  }
	}
	//BIT = bits;
	//cout << BIT << endl;
	vec.push_back(bits);
 
      }
 
    }
  }
  assert(vec.size()<20*20*20);
  int len = vec.size();
  rep(i,len+1) rep(j,(1<<n)) {
    dp[i][j] = INT_MAX;
  }
  dp[0][0] = 0;

  rep(i,len) {
    rep(j,(1<<n)) {
      int bits = vec[i];
      dp[i+1][j] = min(dp[i+1][j|bits],dp[i][j]);
      if( dp[i][j] == INT_MAX ) continue;
      dp[i+1][j|bits] = min(dp[i+1][j|bits],dp[i][j]+1);

    }
  }
  int resp = dp[len][(1<<n)-1];
  return resp;
}

bool check(double r) {
  return calc(N,r) <= M;
}

void compute() {
  double L=0,R=100000000;//fewopajfeaw
  rep(_,100) {//feoajfewao
    double _M = ( L + R ) * 0.5;
    if( check(_M) ) {
       R = _M;
    } else {
      L = _M;
    }
  }
  printf("%.10f\n",L);
}

int main() {
  cin >> N >> M;
  rep(i,N) cin >> ps[i].x >> ps[i].y;
  compute();
  return 0;
}
accuracy: 1
time_ms: 1270
memory_kb: 27928
final_rank: 15

code_snippet: // 基本テンプレート
 
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
using namespace std;
 
#define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++)
#define repq(i,a,n) for(int (i)=(a); (i)<=(n); (i)++)
#define repr(i,a,n) for(int (i)=(a); (i)>=(n); (i)--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
typedef pair<int, int> pii;
typedef long long ll;
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

using ld = double;
using P = complex<ld>;
using G = vector<P>;
const ld pi = acos(-1);
const ld eps = 1e-10;
const ld inf = 1e12;
 
ld cross(const P& a, const P& b) { return a.real()*b.imag() - a.imag()*b.real(); }
ld dot(const P& a, const P& b) { return a.real()*b.real() + a.imag()*b.imag(); }

using C = pair<ld, P>;
#define rad first
#define pnt second
 
C smallest_enclosing_disc(vector<P> ps){
    auto c3 = [](const P &a, const P &b, const P &c){
        ld A = norm(b - c);
        ld B = norm(c - a);
        ld C = norm(a - b);
        ld S = abs(cross(b - a, c - a));
        P p = (A*(B+C-A)*a + B*(C+A-B)*b + C*(A+B-C)*c) / (4*S*S);
        ld r = abs(p - a);
        return make_pair(r, p);
    };
 
    auto c2 = [](const P &a, const P &b){
        P c = (a + b) / (ld)2;
        ld r = abs(a - c);
        return make_pair(r, c);
    };
 
    auto in_circle = [](const P &a, const C &c){
        return norm(a - c.pnt) <= c.rad*c.rad + eps;
    };
 
    int n = ps.size();
    if(n == 1) return make_pair(0, ps[0]);
    random_shuffle(ps.begin(), ps.end());
    C c = c2(ps[0], ps[1]);
    for(int i = 2; i < n; ++i){
        if(!in_circle(ps[i], c)){
            c = c2(ps[0], ps[i]);
            for(int j = 1; j < i; ++j){
                if(!in_circle(ps[j], c)){
                    c = c2(ps[j], ps[i]);
                    for(int k = 0; k < j; ++k){
                        if(!in_circle(ps[k], c)){
                            c = c3(ps[i], ps[j], ps[k]);
                        }
                    }
                }
            }
        }
    }
    return c;
}

double circle_r[1 << 14];
double dp[1 << 14][20];
double solve(int bit, int k) {
    if(dp[bit][k] >= 0) return dp[bit][k];
    if(k == 1) return dp[bit][k] = circle_r[bit];
    
    dp[bit][k] = inf;
    for(int part=bit; part>0; part=(part-1)&bit) {
        int nbit = bit ^ part;
        chmin(dp[bit][k], max(solve(nbit, k-1), circle_r[part]));
        // printf("lhs(%lld, %lld) = %.12f, rhs(%lld) = %.12f\n", nbit, k-1, dp[nbit][k-1], part, circle_r[part]);
    }
    // printf("dp[%lld][%lld] = %.12f\n", bit, k, dp[bit][k]);
    return dp[bit][k];
}
 
signed main() {
    int N, M; cin >> N >> M;
    vector<P> ps;
    for(int i=0; i<N; i++) {
        double x, y; cin >> x >> y;
        ps.push_back(P(x, y));
    }

    for(int bit=1; bit<(1<<N); bit++) {
        vector<P> tmp;
        for(int i=0; i<N; i++) {
            if(bit >> i & 1) tmp.push_back(ps[i]);
        }
        circle_r[bit] = smallest_enclosing_disc(tmp).first;
        // printf("circle_r[%lld] = %.12f\n", bit, circle_r[bit]);
    }

    for(int i=0; i<(1 << N); i++) {
        fill(dp[i], dp[i] + 20, -1);
    }
    printf("%.12f\n", solve((1 << N) - 1, M));
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 5956
final_rank: 4

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

using namespace std;

using Real = double;
using Point = complex< Real >;
const Real EPS = 1e-8, PI = acos(-1);

inline bool eq(Real a, Real b) { return fabs(b - a) < EPS; }

Point operator*(const Point &p, const Real &d) {
  return Point(real(p) * d, imag(p) * d);
}

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

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

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

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

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

Real get_angle(const Point &a, const Point &b, const Point &c) {
  const Point v(b - a), w(c - b);
  Real alpha = atan2(v.imag(), v.real()), beta = atan2(w.imag(), w.real());
  if(alpha > beta) swap(alpha, beta);
  Real theta = (beta - alpha);
  return min(theta, 2 * acos(-1) - theta);
}

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


struct Line {
  Point a, b;

  Line() = default;

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

  Line(Real A, Real B, Real C) // Ax + By = C
  {
    if(eq(A, 0)) a = Point(0, C / B), b = Point(1, C / B);
    else if(eq(B, 0)) b = Point(C / A, 0), b = Point(C / A, 1);
    else a = Point(0, C / B), b = Point(C / A, 0);
  }

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

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

struct Segment : Line {
  Segment() = default;

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

struct Circle {
  Point p;
  Real r;

  Circle() = default;

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

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

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

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

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

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool parallel(const Line &a, const Line &b) {
  return eq(cross(a.b - a.a, b.b - b.a), 0.0);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_A
bool orthogonal(const Line &a, const Line &b) {
  return eq(dot(a.a - a.b, b.a - b.b), 0.0);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_A
Point projection(const Line &l, const Point &p) {
  double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
  return l.a + (l.a - l.b) * t;
}

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

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_B
Point reflection(const Line &l, const Point &p) {
  return p + (projection(l, p) - p) * 2.0;
}

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

bool intersect(const Line &l, const Line &m) {
  return abs(cross(l.b - l.a, m.b - m.a)) > EPS || abs(cross(l.b - l.a, m.b - l.a)) < EPS;
}

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

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

Real distance(const Line &l, const Point &p);

bool intersect(const Circle &c, const Line &l) {
  return distance(l, c.p) <= c.r + EPS;
}

bool intersect(const Circle &c, const Point &p) {
  return abs(abs(p - c.p) - c.r) < EPS;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_B
bool intersect(const Segment &s, const Segment &t) {
  return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

int intersect(const Circle &c, const Segment &l) {
  if(norm(projection(l, c.p) - c.p) - c.r * c.r > EPS) return 0;
  auto d1 = abs(c.p - l.a), d2 = abs(c.p - l.b);
  if(d1 < c.r + EPS && d2 < c.r + EPS) return 0;
  if(d1 < c.r - EPS && d2 > c.r + EPS || d1 > c.r + EPS && d2 < c.r - EPS) return 1;
  const Point h = projection(l, c.p);
  if(dot(l.a - h, l.b - h) < 0) return 2;
  return 0;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_A&lang=jp
int intersect(Circle c1, Circle c2) {
  if(c1.r < c2.r) swap(c1, c2);
  Real d = abs(c1.p - c2.p);
  if(c1.r + c2.r < d) return 4;
  if(eq(c1.r + c2.r, d)) return 3;
  if(c1.r - c2.r < d) return 2;
  if(eq(c1.r - c2.r, d)) return 1;
  return 0;
}

Real distance(const Point &a, const Point &b) {
  return abs(a - b);
}

Real distance(const Line &l, const Point &p) {
  return abs(p - projection(l, p));
}

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

Real distance(const Segment &s, const Point &p) {
  Point r = projection(s, p);
  if(intersect(s, r)) return abs(r - p);
  return min(abs(s.a - p), abs(s.b - p));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_D
Real distance(const Segment &a, const Segment &b) {
  if(intersect(a, b)) return 0;
  return min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)});
}

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

Point crosspoint(const Line &l, const Line &m) {
  Real A = cross(l.b - l.a, m.b - m.a);
  Real B = cross(l.b - l.a, l.b - m.a);
  if(eq(abs(A), 0.0) && eq(abs(B), 0.0)) return m.a;
  return m.a + (m.b - m.a) * B / A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_2_C
Point crosspoint(const Segment &l, const Segment &m) {
  return crosspoint(Line(l), Line(m));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_D
pair< Point, Point > crosspoint(const Circle &c, const Line l) {
  Point pr = projection(l, c.p);
  Point e = (l.b - l.a) / abs(l.b - l.a);
  if(eq(distance(l, c.p), c.r)) return {pr, pr};
  double base = sqrt(c.r * c.r - norm(pr - c.p));
  return {pr - e * base, pr + e * base};
}

pair< Point, Point > crosspoint(const Circle &c, const Segment &l) {
  Line aa = Line(l.a, l.b);
  if(intersect(c, l) == 2) return crosspoint(c, aa);
  auto ret = crosspoint(c, aa);
  if(dot(l.a - ret.first, l.b - ret.first) < 0) ret.second = ret.first;
  else ret.first = ret.second;
  return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_E
pair< Point, Point > crosspoint(const Circle &c1, const Circle &c2) {
  Real d = abs(c1.p - c2.p);
  Real a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
  Real t = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
  Point p1 = c1.p + Point(cos(t + a) * c1.r, sin(t + a) * c1.r);
  Point p2 = c1.p + Point(cos(t - a) * c1.r, sin(t - a) * c1.r);
  return {p1, p2};
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_F
pair< Point, Point > tangent(const Circle &c1, const Point &p2) {
  return crosspoint(c1, Circle(p2, sqrt(norm(c1.p - p2) - c1.r * c1.r)));
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
Lines tangent(Circle c1, Circle c2) {
  Lines ret;
  if(c1.r < c2.r) swap(c1, c2);
  Real g = norm(c1.p - c2.p);
  if(eq(g, 0)) return ret;
  Point u = (c2.p - c1.p) / sqrt(g);
  Point v = rotate(PI * 0.5, u);
  for(int s : {-1, 1}) {
    Real h = (c1.r + s * c2.r) / sqrt(g);
    if(eq(1 - h * h, 0)) {
      ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
    } else if(1 - h * h > 0) {
      Point uu = u * h, vv = v * sqrt(1 - h * h);
      ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
      ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
    }
  }
  return ret;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_B
bool is_convex(const Polygon &p) {
  int n = (int) p.size();
  for(int i = 0; i < n; i++) {
    if(ccw(p[(i + n - 1) % n], p[i], p[(i + 1) % n]) == -1) return false;
  }
  return true;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_A
Polygon convex_hull(Polygon &p) {
  int n = (int) p.size(), k = 0;
  if(n <= 2) return p;
  sort(p.begin(), p.end());
  vector< Point > ch(2 * n);
  for(int i = 0; i < n; ch[k++] = p[i++]) {
    while(k >= 2 && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
  }
  for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
    while(k >= t && cross(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
  }
  ch.resize(k - 1);
  return ch;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C
enum {
  OUT, ON, IN
};

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


// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
void merge_segments(vector< Segment > &segs) {

  auto merge_if_able = [](Segment &s1, const Segment &s2) {
    if(abs(cross(s1.b - s1.a, s2.b - s2.a)) > EPS) return false;
    if(ccw(s1.a, s2.a, s1.b) == 1 || ccw(s1.a, s2.a, s1.b) == -1) return false;
    if(ccw(s1.a, s1.b, s2.a) == -2 || ccw(s2.a, s2.b, s1.a) == -2) return false;
    s1 = Segment(min(s1.a, s2.a), max(s1.b, s2.b));
    return true;
  };

  for(int i = 0; i < segs.size(); i++) {
    if(segs[i].b < segs[i].a) swap(segs[i].a, segs[i].b);
  }
  for(int i = 0; i < segs.size(); i++) {
    for(int j = i + 1; j < segs.size(); j++) {
      if(merge_if_able(segs[i], segs[j])) {
        segs[j--] = segs.back(), segs.pop_back();
      }
    }
  }
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1033
vector< vector< int > > segment_arrangement(vector< Segment > &segs, vector< Point > &ps) {
  vector< vector< int > > g;
  int N = (int) segs.size();
  for(int i = 0; i < N; i++) {
    ps.emplace_back(segs[i].a);
    ps.emplace_back(segs[i].b);
    for(int j = i + 1; j < N; j++) {
      const Point p1 = segs[i].b - segs[i].a;
      const Point p2 = segs[j].b - segs[j].a;
      if(cross(p1, p2) == 0) continue;
      if(intersect(segs[i], segs[j])) {
        ps.emplace_back(crosspoint(segs[i], segs[j]));
      }
    }
  }
  sort(begin(ps), end(ps));
  ps.erase(unique(begin(ps), end(ps)), end(ps));

  int M = (int) ps.size();
  g.resize(M);
  for(int i = 0; i < N; i++) {
    vector< int > vec;
    for(int j = 0; j < M; j++) {
      if(intersect(segs[i], ps[j])) {
        vec.emplace_back(j);
      }
    }
    for(int j = 1; j < vec.size(); j++) {
      g[vec[j - 1]].push_back(vec[j]);
      g[vec[j]].push_back(vec[j - 1]);
    }
  }
  return (g);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_C
Polygon convex_cut(const Polygon &U, Line l) {
  Polygon ret;
  for(int i = 0; i < U.size(); i++) {
    Point now = U[i], nxt = U[(i + 1) % U.size()];
    if(ccw(l.a, l.b, now) != -1) ret.push_back(now);
    if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) < 0) {
      ret.push_back(crosspoint(Line(now, nxt), l));
    }
  }
  return (ret);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_A
Real area2(const Polygon &p) {
  Real A = 0;
  for(int i = 0; i < p.size(); ++i) {
    A += cross(p[i], p[(i + 1) % p.size()]);
  }
  return A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_H
Real area2(const Polygon &p, const Circle &c) {
  if(p.size() < 3) return 0.0;
  function< Real(Circle, Point, Point) > cross_area = [&](const Circle &c, const Point &a, const Point &b) {
    Point va = c.p - a, vb = c.p - b;
    Real f = cross(va, vb), ret = 0.0;
    if(eq(f, 0.0)) return ret;
    if(max(abs(va), abs(vb)) < c.r + EPS) return f;
    if(distance(Segment(a, b), c.p) > c.r - EPS) return c.r * c.r * arg(vb * conj(va));
    auto u = crosspoint(c, Segment(a, b));
    vector< Point > tot{a, u.first, u.second, b};
    for(int i = 0; i + 1 < tot.size(); i++) {
      ret += cross_area(c, tot[i], tot[i + 1]);
    }
    return ret;
  };
  Real A = 0;
  for(int i = 0; i < p.size(); i++) {
    A += cross_area(c, p[i], p[(i + 1) % p.size()]);
  }
  return A;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_4_B
Real convex_diameter(const Polygon &p) {
  int N = (int) p.size();
  int is = 0, js = 0;
  for(int i = 1; i < N; i++) {
    if(p[i].imag() > p[is].imag()) is = i;
    if(p[i].imag() < p[js].imag()) js = i;
  }
  Real maxdis = norm(p[is] - p[js]);

  int maxi, maxj, i, j;
  i = maxi = is;
  j = maxj = js;
  do {
    if(cross(p[(i + 1) % N] - p[i], p[(j + 1) % N] - p[j]) >= 0) {
      j = (j + 1) % N;
    } else {
      i = (i + 1) % N;
    }
    if(norm(p[i] - p[j]) > maxdis) {
      maxdis = norm(p[i] - p[j]);
      maxi = i;
      maxj = j;
    }
  } while(i != is || j != js);
  return sqrt(maxdis);
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_5_A
Real closest_pair(Points ps) {
  if(ps.size() <= 1) throw (0);
  sort(begin(ps), end(ps));

  auto compare_y = [&](const Point &a, const Point &b) {
    return imag(a) < imag(b);
  };
  vector< Point > beet(ps.size());
  const Real INF = 1e18;

  function< Real(int, int) > rec = [&](int left, int right) {
    if(right - left <= 1) return INF;
    int mid = (left + right) >> 1;
    auto x = real(ps[mid]);
    auto ret = min(rec(left, mid), rec(mid, right));
    inplace_merge(begin(ps) + left, begin(ps) + mid, begin(ps) + right, compare_y);
    int ptr = 0;
    for(int i = left; i < right; i++) {
      if(abs(real(ps[i]) - x) >= ret) continue;
      for(int j = 0; j < ptr; j++) {
        auto luz = ps[i] - beet[ptr - j - 1];
        if(imag(luz) >= ret) break;
        ret = min(ret, abs(luz));
      }
      beet[ptr++] = ps[i];
    }
    return ret;
  };
  return rec(0, (int) ps.size());
}

Real smallest_enclosing_circle(Points &ps) {
  if(ps.size() == 1) return 0;

  mt19937 mt;
  mt.seed(random_device()());
  shuffle(begin(ps), end(ps), mt);

  auto make_circle3 = [](const Point &a, const Point &b, const Point &c) {
    auto A = norm(b - c), B = norm(c - a), C = norm(a - b);
    auto S = abs(cross(b - a, c - a));
    auto p = (A * (B + C - A) * a + B * (C + A - B) * b + C * (A + B - C) * c) * 0.25 / S / S;
    return Circle(p, abs(p - a));
  };

  auto make_circle2 = [](const Point &a, const Point &b) {
    Point c = (a + b) * 0.5;
    return Circle(c, abs(a - c));
  };

  auto in_circle = [](const Point &a, const Circle &c) {
    return norm(a - c.p) < c.r * c.r + EPS;
  };

  Circle c = make_circle2(ps[0], ps[1]);
  for(int i = 2; i < ps.size(); ++i) {
    if(!in_circle(ps[i], c)) {
      c = make_circle2(ps[0], ps[i]);
      for(int j = 1; j < i; ++j) {
        if(!in_circle(ps[j], c)) {
          c = make_circle2(ps[j], ps[i]);
          for(int k = 0; k < j; ++k) {
            if(!in_circle(ps[k], c)) {
              c = make_circle3(ps[i], ps[j], ps[k]);
            }
          }
        }
      }
    }
  }
  return c.r;
}

double cover[1 << 14];
double dp[1 << 14][15];
bool memo[1 << 14][15];

double rec(int bit, int sum) {
  if(sum == 1) return cover[bit];
  if(memo[bit][sum]) return dp[bit][sum];
  double ret = 1e9;
  for(int i = bit & (bit - 1); i > 0; i = (i - 1) & bit) {
    int other = i ^bit;
    ret = min(ret, max(rec(other, sum - 1), cover[i]));
  }
  memo[bit][sum] = true;
  return dp[bit][sum] = ret;
}

int main() {
  int N, M;
  Point p[14];

  cin >> N >> M;
  for(int i = 0; i < N; i++) {
    cin >> p[i];
  }
  for(int i = 1; i < (1 << N); i++) {
    Points ps;
    for(int j = 0; j < N; j++) {
      if((i >> j) & 1) ps.emplace_back(p[j]);
    }
    cover[i] = smallest_enclosing_circle(ps);
  }
  cout << fixed << setprecision(10) << rec((1 << N) - 1, M) << endl;
}
accuracy: 1
time_ms: 140
memory_kb: 5668
final_rank: 5

code_snippet: #include<bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define D long double
using namespace std;
//typedef long double D;
typedef complex<long double> P;
typedef vector<P> VP;
typedef pair<P, P> L;  // Line
typedef vector<P> VP;
const D EPS = 1e-9;    // 許容誤差。問題によって変える
#define X real()
#define Y imag()
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)
D dot(P a, P b) {return (conj(a)*b).X; }
D 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;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
bool isecSP(P a1, P a2, P b) {
  return !ccw(a1, a2, b);
}
P crosspointLL(P a1, P a2, P b1, P b2) {
  long double d1 = cross(b2-b1, b1-a1);
  long double d2 = cross(b2-b1, a2-a1);
  if (EQ(d1, 0) && EQ(d2, 0)) return a1;  // same line
  if (EQ(d2, 0)) throw "kouten ga nai";   // 交点がない
  return a1 + d1/d2 * (a2-a1);
}
P circumcenter(P a, P b, P c) {
  a = (a-c)*(long double)0.5;
  b = (b-c)*(long double)0.5;
  return c + crosspointLL(a, a*P(1,1), b, b*P(1,1));
}
int dp[1<<14],n,m;
D min_s[1<<14];
VP v;
void Mae_syori(){
  r(i,(1<<n))min_s[i]=1e15;
  for(int i=0;i<n;i++){
    for(int j=i+1;j<n;j++){
      for(int k=j+1;k<n;k++){
        if(isecSP(v[i],v[j],v[k]))continue;
        if(isecSP(v[i],v[k],v[j]))continue;
        if(isecSP(v[k],v[j],v[i]))continue;
        P c=circumcenter(v[i],v[j],v[k]);
        D ans=0;
        ans=max(ans,abs(v[i]-c));
        ans=max(ans,abs(v[j]-c));
        ans=max(ans,abs(v[k]-c));
        int mask=0;
        for(int l=0;l<n;l++){
          if(abs(v[l]-c)<=ans)mask|=(1<<l);
        }
        min_s[mask]=min(ans,min_s[mask]);
      }
      D ans=abs(v[i]-v[j])/2;
      P c=(v[i]+v[j]);c/=2;
      int mask=0;
      for(int l=0;l<n;l++){
        if(abs(v[l]-c)<=ans)mask|=(1<<l);
      }
      min_s[mask]=min(ans,min_s[mask]);
    }
  }
  r(i,n)min_s[(1<<i)]=0;
  for(int i=(1<<n)-1;i>=0;i--){
    for(int j=(i-1)&i;j>0;j=(j-1)&i){
      min_s[j]=min(min_s[j],min_s[i]);
    }
  }
  for(int i=0;i<(1<<n);i++) min_s[i]+=0.0000000001;
}
D dfs(int S){
  if(dp[S])return dp[S];
  D res=1e8;
  for(int i=(S-1)&S;i>0;i=(i-1)&S){
    res=min(res,dfs(i)+dfs(i^S));
  }
  return dp[S]=res;
}
bool check(D mid){
  memset(dp,0,sizeof(dp));
  for(int i=1;i<(1<<n);i++){
    if(min_s[i]<=mid)dp[i]=1;
  }
  return dfs((1<<n)-1)<=m;
}
D nibutan(){
  D l=0,r=100000;
  r(i,77){
    D mid=(l+r)/2;//cout<<mid<<endl;
    if(check(mid))r=mid;
    else l=mid;
  }
  return l;
}
int main(){
  cin>>n>>m;
  r(i,n){
    int x,y;
    cin>>x>>y;
    v.push_back(P(x,y));
  }
  Mae_syori();
  printf("%.12Lf\n",nibutan());
}
accuracy: 1
time_ms: 2020
memory_kb: 3616
final_rank: 13