// Adapted from Readiz/h-contest-lesson at 2011c00330b5.
// Local C++17 runner: 1 <= N <= 100, coordinates in [0, 999].
#include <iostream>
#include <cstdlib>
static int coordinates[100][2];
int get_dist(int a, int b) {
    return std::abs(coordinates[a][0] - coordinates[b][0])
         + std::abs(coordinates[a][1] - coordinates[b][1]);
}
int get_path_dist(const int order[], int size) {
    int cost = 0;
    for (int i = 1; i < size; ++i) cost += get_dist(order[i-1], order[i]);
    return cost;
}
extern int get_dist(int a, int b);
extern int get_path_dist(const int order[], int size);

static void reverse_range(int order[], int left, int right) {
    while (left < right) {
        int temp = order[left];
        order[left] = order[right];
        order[right] = temp;
        ++left;
        --right;
    }
}

void build_initial_path(int n, const int points[][2], int order[]) {
    int used[100];
    (void)points;

    for (int i = 0; i < n; ++i) {
        used[i] = 0;
    }

    order[0] = 0;
    used[0] = 1;

    for (int pos = 1; pos < n; ++pos) {
        int current = order[pos - 1];
        int best = -1;
        int best_dist = 0;

        for (int cand = 0; cand < n; ++cand) {
            if (used[cand]) continue;

            int dist = get_dist(current, cand);
            if (best == -1 || dist < best_dist) {
                best = cand;
                best_dist = dist;
            }
        }

        order[pos] = best;
        used[best] = 1;
    }

    for (int pass = 0; pass < 80; ++pass) {
        int improved = 0;

        for (int left = 1; left < n - 1; ++left) {
            for (int right = left + 1; right < n; ++right) {
                int a = order[left - 1];
                int b = order[left];
                int c = order[right];
                int before = get_dist(a, b);
                int after = get_dist(a, c);

                if (right + 1 < n) {
                    int d = order[right + 1];
                    before += get_dist(c, d);
                    after += get_dist(b, d);
                }

                if (after < before) {
                    reverse_range(order, left, right);
                    improved = 1;
                }
            }
        }

        if (!improved) break;
    }
}
namespace hc {
static_assert(sizeof(unsigned) == 4, "32-bit unsigned required");
struct Random {
    unsigned state;
    void reset(unsigned seed) { state = seed; }
    unsigned next() {
        state = state * 1664525u + 1013904223u;
        return state;
    }
    unsigned below(unsigned bound) { // 전제: bound > 0
        const unsigned threshold = (0u - bound) % bound;
        unsigned value;
        do { value = next(); } while (value < threshold);
        return value % bound;
    }
    void shuffle(int a[], int n) { // [0, n), n >= 0
        for (int i = n - 1; i > 0; --i) {
            int j = (int)below((unsigned)i + 1u);
            int temp = a[i]; a[i] = a[j]; a[j] = temp;
        }
    }
};
}
namespace ordering_sa {
struct Stats {
    int bestCost;
    int currentCost;
    int accepted;
    int acceptedWorse;
};

// x >= 0. No math header: reduce x, evaluate a short series, then square.
double expNegative(double x) {
    if (x >= 32.0) return 0.0;
    int halves = 0;
    while (x > 0.5) { x *= 0.5; ++halves; }
    double sum = 1.0, term = 1.0;
    for (int k = 1; k <= 12; ++k) {
        term *= -x / k;
        sum += term;
    }
    for (int k = 0; k < halves; ++k) sum *= sum;
    return sum;
}

int delta(int n, const int order[], int left, int right) {
    int a = order[left - 1], b = order[left], c = order[right];
    int change = get_dist(a, c) - get_dist(a, b);
    if (right + 1 < n) {
        int d = order[right + 1];
        change += get_dist(b, d) - get_dist(c, d);
    }
    return change;
}

Stats improve(int n, int order[], int attempts, unsigned seed,
              double startTemperature, double endTemperature) {
    int current[100];
    for (int i = 0; i < n; ++i) current[i] = order[i];
    int initialCost = get_path_dist(order, n);
    Stats stats = {initialCost, initialCost, 0, 0};
    if (n <= 2 || attempts == 0) return stats;

    hc::Random rng;
    rng.reset(seed);
    for (int step = 0; step < attempts; ++step) {
        int left = 1 + (int)rng.below((unsigned)(n - 1));
        int right = 1 + (int)rng.below((unsigned)(n - 2));
        if (right >= left) ++right;
        if (left > right) { int temp = left; left = right; right = temp; }

        double progress = attempts == 1 ? 0.0 : (double)step / (attempts - 1);
        double temperature = startTemperature
                           + (endTemperature - startTemperature) * progress;
        int change = delta(n, current, left, right);
        // Consume one draw on every proposal, including improvements.
        double u = (rng.next() >> 8) / 16777216.0;
        bool accept = change <= 0;
        if (!accept && temperature > 0.0) {
            accept = u < expNegative(change / temperature);
        }
        if (!accept) continue;

        reverse_range(current, left, right);
        stats.currentCost += change;
        ++stats.accepted;
        if (change > 0) ++stats.acceptedWorse;
        if (stats.currentCost < stats.bestCost) {
            stats.bestCost = stats.currentCost;
            for (int i = 0; i < n; ++i) order[i] = current[i];
        }
    }
    return stats;
}
}
void build_path(int n, const int points[][2], int order[]) {
    build_initial_path(n, points, order);
    ordering_sa::improve(n, order, 30000, 20260922u, 128.0, 1.0);
}

int main() {
    int n;
    if (!(std::cin >> n) || n < 1 || n > 100) return 1;
    for (int i = 0; i < n; ++i) {
        if (!(std::cin >> coordinates[i][0] >> coordinates[i][1])) return 1;
        for (int v : coordinates[i]) if (v < 0 || v > 999) return 1;
    }
    int order[100];
    build_path(n, coordinates, order);
    std::cout << get_path_dist(order, n) << '\n';
    for (int i = 0; i < n; ++i) std::cout << (i ? " " : "") << order[i];
    std::cout << '\n';
}
