using System;
using System.Text;
using System.Collections.Generic;
class Solve{
    public Solve(){}
    StringBuilder sb;
    public static int Main(){
        new Solve().Run();
        return 0;
    }
    void Run(){
        sb = new StringBuilder();
        Calc();
        Console.Write(sb.ToString());
    }
    void Calc(){
        int N = int.Parse(Console.ReadLine());
        double[] data = new double[1 << N];
        {   
            long[] X = new long[N];
            long[] Y = new long[N];
            long[] A = new long[N];
            for(int i=0;i<N;i++){
                string[] str = Console.ReadLine().Split(' ');
                X[i] = int.Parse(str[0]);
                Y[i] = int.Parse(str[1]);
                A[i] = int.Parse(str[2]);
            }
            data[0] = 1000000000000000000;
            for(int i=1;i<1 << N;i++){
                List<int> choose = new List<int>();
                double sum = 0;
                for(int j=0;j<N;j++){
                    if((i & (1 << j)) != 0){
                        choose.Add(j);
                        sum += A[j];
                    }
                }
                List<int> p1 = new List<int>();
                List<int> p2 = new List<int>();
                List<double> d = new List<double>();
                for(int j=0;j<choose.Count;j++){
                    for(int k=j+1;k<choose.Count;k++){
                        p1.Add(j);
                        p2.Add(k);
                        d.Add(Math.Sqrt((X[choose[j]]-X[choose[k]])*(X[choose[j]]-X[choose[k]])+(Y[choose[j]]-Y[choose[k]])*(Y[choose[j]]-Y[choose[k]])));
                    }
                }
                Kruskal K = new Kruskal(choose.Count,p1.ToArray(),p2.ToArray(),d.ToArray());
                data[i] = (sum - K.cost)/choose.Count;
            }
        }
        double[] dp = new double[1 << N];
        dp[0] = 1000000000000000000;
        for(int i=1;i< 1 << N;i++){
            double max = 0;
            for(int j = i;j != 0;j = (i & (j-1))){
                max = Math.Max(max,Math.Min(dp[i-j],data[j]));
            }
            dp[i] = max;
        }
        sb.Append(dp[(1 << N) - 1]+"\n");
    }
}
class UnionFind{
    int[] par;
    public UnionFind(int n){
        par = new int[n];
        for(int i=0;i<n;i++){
            par[i] = i;
        }
    }
    public void Union(int x,int y){
        par[Get(x)] = Get(y); 
    }
    public bool Same(int x,int y){
        return Get(x) == Get(y);
    }
    int Get(int x){
        if(x != par[x]){
            par[x] = Get(par[x]);
        }
        return par[x];
    }
}
class Edge{
    public int a;
    public int b;
    public double cost;
    public Edge(int a0,int b0,double c){
        a = a0;
        b = b0;
        cost = c;
    }
}
class Kruskal{
    int N,M;
    public Edge[] edges;
    public double cost;
    public Kruskal(int n,Edge[] e){
        N = n;
        edges = e;
        M = e.Length;
        Act();
    }
    public Kruskal(int n,int[] a,int[] b,double[] c){
        N = n;
        M = a.Length;
        edges = new Edge[M];
        for(int i=0;i<M;i++){
            edges[i] = new Edge(a[i],b[i],c[i]);
        }
        Act();
    }
    void Act(){
        UnionFind U = new UnionFind(N);
        cost = 0;
        Array.Sort(edges,(a,b) => a.cost > b.cost ? 1 : (a.cost == b.cost ? 0 : -1));
        for(int i=0;i<M;i++){
            if(!U.Same(edges[i].a,edges[i].b)){
                U.Union(edges[i].a,edges[i].b);
                cost += edges[i].cost;
            }
        }
    } 
}

Measured memory_bytes: 7552