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

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

struct P {
  int x, y;
};

std::vector<P> creature[7]; // 0は始点, 6は終点となっている
const int INF = 1 << 24;
// dp[ゲットしたパチモンの匹数][さっきつかまえた種族][さっきつかまえたパチモンの番号]:
// 最小手数
int dp[5][5][1000];

int rec(int i, int t, int n) {
  if (dp[i][t][n] >= 0) {
    return dp[i][t][n];
  }

  if (i == 4) {
    int x_diff = abs(creature[6][0].x - creature[t][n].x),
        y_diff = abs(creature[6][0].y - creature[t][n].y);
    return x_diff + y_diff;
  }

  // t+1へ行こう
  int res = INF, prev_res;
  for (int v = 0; v < creature[t + 1].size(); v++) {
    int x_diff = abs(creature[t + 1][v].x - creature[t][n].x),
        y_diff = abs(creature[t + 1][v].y - creature[t][n].y);
    res = std::min(res, rec(i + 1, t + 1, v) + x_diff + y_diff);
  }

  return dp[i][t][n] = res;
}

int main() {
  int w, h;
  while (std::cin >> w >> h, w) {
    for (int i = 0; i < 7; i++)
      creature[i].clear();

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        char c;
        std::cin >> c;
        if (c == 'S') {
          creature[0].push_back({j, i});
        } else if (c == 'G') {
          creature[6].push_back({j, i});
        } else if ('1' <= c && c <= '5') {
          creature[c - '0'].push_back({j, i});
        }
      }
    }

    int res = INF, type;
    for (int i = 1; i <= 5; i++) {
      for (int S = 0; S < 5; S++) {
        for (int t = 0; t < 5; t++) {
          for (int n = 0; n < 1000; n++) {
            dp[S][t][n] = -1;
          }
        }
      }

      std::rotate(creature + 1, creature + 2, creature + 6);

      if (rec(0, 0, 0) < res) {
        res = rec(0, 0, 0);
        type = i;
      }
    }

    if (res == INF) {
      std::cout << "NA" << std::endl;
    } else {
      std::cout << type << " " << res << std::endl;
    }
  }
}

Error: TLE

Fixed submission:

#include <iostream>
#include <vector>

struct P {
  int x, y;
};

std::vector<P> creature[7]; // 0は始点, 6は終点となっている
const int INF = 1 << 24;
// dp[ゲットしたパチモンの種族の集合][さっきつかまえた種族][さっきつかまえたパチモンの番号]:
// 最小手数
int dp[1 << 6][6][1000];

int abs(int i) { return (i > 0) ? i : -i; }

int rec(int S, int t, int n) {
  if (dp[S][t][n] >= 0) {
    return dp[S][t][n];
  }

  if (S == (1 << 6) - 1) {
    int x_diff = abs(creature[6][0].x - creature[t][n].x),
        y_diff = abs(creature[6][0].y - creature[t][n].y);
    return x_diff + y_diff;
  }

  int min_res = INF;
  for (int u = 0; u < 6; u++) {
    if (!(S >> u & 1)) {
      for (int v = 0; v < creature[u].size(); v++) {
        int x_diff = abs(creature[t][n].x - creature[u][v].x),
            y_diff = abs(creature[t][n].y - creature[u][v].y),
            res = rec(S | (1 << u), u, v) + x_diff + y_diff;
        if (res < min_res) {
          min_res = res;
        }
      }
    }
  }

  return dp[S][t][n] = min_res;
}

int main() {
  int w, h;
  while (std::cin >> w >> h, w) {
    for (int i = 0; i < 7; i++)
      creature[i].clear();

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        char c;
        std::cin >> c;
        if (c == 'S') {
          creature[0].push_back({i, j});
        } else if (c == 'G') {
          creature[6].push_back({i, j});
        } else if ('1' <= c && c <= '5') {
          creature[c - '0'].push_back({i, j});
        }
      }
    }

    int res = INF, type;

    for (int i = 1; i <= 5; i++) {
      for (int S = 0; S < (1 << 6); S++) {
        for (int t = 0; t < 6; t++) {
          for (int n = 0; n < 1000; n++) {
            dp[S][t][n] = -1;
          }
        }
      }

      if (rec(1 << i, 0, 0) < res) {
        res = rec(1 << i, 0, 0);
        type = i;
      }
    }

    if (res == INF) {
      std::cout << "NA" << std::endl;
    } else {
      std::cout << type << " " << res << std::endl;
    }
  }
}