Problem p00635 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

int n;
int g[10][10];
int dist[10] = {};
int maxHate[10] = {};
int minHate[10] = {};
int ord[10];
int maxRest[10][1 << 10];

int solve() {
  if (n == 1)
    return 0;
  ord[1] = 0;
  int minD = 1 << 30;
  int sumMinHate = 0;
  for (int i = 0; i < n; ++i)
    sumMinHate += minHate[i];
  do {
    int pOne = -1;
    int used = (1 << ord[0]);
    int rest = sumMinHate - minHate[ord[0]];
    bool one = ord[0] == 0;
    for (int i = 1; i < n; ++i) {
      int p = ord[i];
      if (ord[i] == 0) {
        if (one) {
          pOne = i;
          p = ord[i] = 1;
        }
        one = !one;
      }
      rest -= minHate[p];
      dist[i] = dist[i - 1];
      for (int j = i - 1; j >= 0; --j) {
        if (dist[i] - dist[j] >= maxRest[p][used])
          break;
        dist[i] = max(dist[i], dist[j] + g[p][ord[j]]);
      }
      if (dist[i] + rest >= minD) {
        dist[n - 1] = 1 << 30;
        break;
      }
      used += 1 << p;
    }
    minD = min(minD, dist[n - 1]);
    if (pOne != -1)
      ord[pOne] = 0;
  } while (next_permutation(ord, ord + n));
  return minD;
}

int main() {
  int trailZero[1024] = {};
  for (int i = 0; i < 10; ++i) {
    trailZero[(1 << (i + 1)) - 1] = i;
  }
  while (true) {
    cin >> n;
    if (n == 0 || cin.eof())
      break;
    for (int i = 0; i < n; ++i) {
      ord[i] = i;
      minHate[i] = 1 << 30;
      maxHate[i] = 0;
      for (int j = 0; j < n; ++j) {
        scanf("%d", g[i] + j);
      }
    }
    memset(maxRest, 0, sizeof(maxRest));
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        g[i][j] = g[j][i] = max(g[i][j], g[j][i]);
        maxHate[i] = max(maxHate[i], g[i][j]);
        maxHate[j] = max(maxHate[j], g[i][j]);
        minHate[i] = min(minHate[i], g[i][j]);
        minHate[j] = min(minHate[j], g[i][j]);
      }
    }
    for (int j = 1; j < (1 << n); ++j) {
      for (int k = 0; k < n; ++k) {
        if ((j & (1 << k)) == 0 || j == (1 << k))
          continue;
        int st = j - (1 << k);
        int prev = st & (st - 1);
        int pos = trailZero[st ^ (st - 1)];
        maxRest[k][st] = max(maxRest[k][prev], g[k][pos]);
      }
    }
    printf("%d\\n", solve());
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

int n;
int g[10][10];
int dist[10] = {};
int maxHate[10] = {};
int minHate[10] = {};
int ord[10];
int maxRest[10][1 << 10];

int solve() {
  if (n == 1)
    return 0;
  ord[1] = 0;
  int minD = 1 << 30;
  int sumMinHate = 0;
  for (int i = 0; i < n; ++i)
    sumMinHate += minHate[i];
  do {
    int p1 = 0;
    for (int i = n - 1;; --i) {
      if (ord[i] == 0) {
        p1 = i;
        ord[p1] = 1;
        break;
      }
    }
    int used = (1 << ord[0]);
    int rest = sumMinHate - minHate[ord[0]];
    for (int i = 1; i < n; ++i) {
      rest -= minHate[ord[i]];
      dist[i] = dist[i - 1] + minHate[ord[i]];
      for (int j = i - 1; j >= 0; --j) {
        if (dist[i] - dist[j] >= maxRest[ord[i]][used])
          break;
        dist[i] = max(dist[i], dist[j] + g[ord[i]][ord[j]]);
      }
      if (dist[i] + rest >= minD) {
        dist[n - 1] = 1 << 30;
        goto next;
      }
      used += 1 << ord[i];
    }
    minD = min(minD, dist[n - 1]);
  next:
    ord[p1] = 0;
  } while (next_permutation(ord, ord + n));
  return minD;
}

int main() {
  int trailZero[1024] = {};
  for (int i = 0; i < 10; ++i) {
    trailZero[(1 << i) - 1] = i - 1;
  }
  while (true) {
    cin >> n;
    if (n == 0 || cin.eof())
      break;
    for (int i = 0; i < n; ++i) {
      ord[i] = i;
      minHate[i] = 1 << 30;
      for (int j = 0; j < n; ++j) {
        scanf("%d", g[i] + j);
      }
    }
    for (int i = 0; i < n; ++i) {
      for (int j = i + 1; j < n; ++j) {
        g[i][j] = g[j][i] = max(g[i][j], g[j][i]);
        maxHate[i] = max(maxHate[i], g[i][j]);
        maxHate[j] = max(maxHate[j], g[i][j]);
        minHate[i] = min(minHate[i], g[i][j]);
        minHate[j] = min(minHate[j], g[i][j]);
      }
    }
    memset(maxRest, sizeof(maxRest), 0);
    for (int j = 1; j < (1 << n); ++j) {
      for (int k = 0; k < n; ++k) {
        if ((j & (1 << k)) == 0 || j == (1 << k))
          continue;
        int st = j - (1 << k);
        int prev = st & (st - 1);
        int pos = trailZero[st ^ (st - 1)];
        // while((st & (1 << pos)) == 0) ++pos;
        maxRest[k][st] = max(maxRest[k][prev], g[k][pos]);
      }
    }
    printf("%d\\n", solve());
  }
}