import java.util.*;

public class Euler300 {
    static class ContactKey {
        long lo, hi;

        ContactKey(long lo, long hi) {
            this.lo = lo;
            this.hi = hi;
        }

        @Override
        public boolean equals(Object o) {
            ContactKey that = (ContactKey) o;
            return this.lo == that.lo && this.hi == that.hi;
        }

        @Override
        public int hashCode() {
            long x = lo * -7046045454385353131L; // 11400714819323198485ull
            long y = hi * -4417276706812531889L; // 14029467366897019727ull
            return (int) (x ^ (y >>> 1));
        }
    }

    static class FoldingSolver {
        int n;
        int gridSide;
        int offset;

        int[] px, py;
        byte[] occupied;

        int[] dx = { 1, -1, 0, 0 };
        int[] dy = { 0, 0, 1, -1 };

        List<int[]> pairList = new ArrayList<>();
        Set<ContactKey> contactMaps = new HashSet<>();

        FoldingSolver(int n) {
            this.n = n;
            gridSide = 2 * n + 1;
            offset = n;

            px = new int[n];
            py = new int[n];
            occupied = new byte[gridSide * gridSide];

            for (int i = 0; i < n; ++i) {
                for (int j = i + 2; j < n; ++j) {
                    pairList.add(new int[] { i, j });
                }
            }
        }

        int cellId(int x, int y) {
            return y * gridSide + x;
        }

        void addCurrentContactMap() {
            long lo = 0, hi = 0;
            for (int p = 0; p < pairList.size(); ++p) {
                int[] pair = pairList.get(p);
                int i = pair[0], j = pair[1];
                int manhattan = Math.abs(px[i] - px[j]) + Math.abs(py[i] - py[j]);
                if (manhattan == 1) {
                    if (p < 64)
                        lo |= (1L << p);
                    else
                        hi |= (1L << (p - 64));
                }
            }
            contactMaps.add(new ContactKey(lo, hi));
        }

        void dfs(int idx) {
            if (idx == n - 1) {
                addCurrentContactMap();
                return;
            }

            int cx = px[idx];
            int cy = py[idx];

            for (int dir = 0; dir < 4; ++dir) {
                int nx = cx + dx[dir];
                int ny = cy + dy[dir];
                int cid = cellId(nx, ny);
                if (occupied[cid] != 0)
                    continue;

                occupied[cid] = 1;
                px[idx + 1] = nx;
                py[idx + 1] = ny;
                dfs(idx + 1);
                occupied[cid] = 0;
            }
        }

        List<ContactKey> enumerateMaps() {
            int x0 = offset, y0 = offset;
            int x1 = offset + 1, y1 = offset;

            occupied[cellId(x0, y0)] = 1;
            occupied[cellId(x1, y1)] = 1;
            px[0] = x0;
            py[0] = y0;
            px[1] = x1;
            py[1] = y1;

            dfs(1);
            return new ArrayList<>(contactMaps);
        }

        long solveNumerator() {
            List<ContactKey> maps = enumerateMaps();
            List<int[]> adjMasks = new ArrayList<>(maps.size());

            for (ContactKey key : maps) {
                int[] adj = new int[n];
                for (int p = 0; p < pairList.size(); ++p) {
                    boolean on = false;
                    if (p < 64)
                        on = ((key.lo >>> p) & 1L) != 0;
                    else
                        on = ((key.hi >>> (p - 64)) & 1L) != 0;
                    if (on) {
                        int[] pair = pairList.get(p);
                        int i = pair[0], j = pair[1];
                        adj[i] |= (1 << j);
                        adj[j] |= (1 << i);
                    }
                }
                adjMasks.add(adj);
            }

            int maskCount = 1 << n;
            byte[] best = new byte[maskCount];
            byte[] score = new byte[maskCount];

            for (int[] adj : adjMasks) {
                score[0] = 0;
                for (int mask = 1; mask < maskCount; ++mask) {
                    int lb = mask & -mask;
                    int i = Integer.numberOfTrailingZeros(lb);
                    int prev = mask ^ lb;
                    int m = adj[i];
                    int add = Integer.bitCount(prev & m);
                    score[mask] = (byte) (score[prev] + add);
                    if (score[mask] > best[mask]) {
                        best[mask] = score[mask];
                    }
                }
            }

            long numerator = 0;
            for (int mask = 0; mask < maskCount; ++mask) {
                int consecutiveHh = Integer.bitCount(mask & (mask >>> 1));
                numerator += best[mask] + consecutiveHh;
            }
            return numerator;
        }
    }

    static String exactAverageDecimal(long numerator, int n) {
        long denominator = 1L << n;
        long integerPart = numerator / denominator;
        long rem = numerator % denominator;

        StringBuilder out = new StringBuilder();
        out.append(integerPart);
        if (rem == 0)
            return out.toString();

        out.append('.');
        while (rem != 0) {
            rem *= 10;
            long digit = rem / denominator;
            out.append(digit);
            rem %= denominator;
        }
        return out.toString();
    }

    public static String solve() {
        int n = 15;
        FoldingSolver solver = new FoldingSolver(n);
        long numerator = solver.solveNumerator();
        return exactAverageDecimal(numerator, n);
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
