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

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Point {
  int x, y;
  Point(int x, int y) : x(x), y(y) { ; }
};

vector<Point> points[10];
inline int dist(int x1, int y1, int x2, int y2) {
  return abs(x1 - x2) + abs(y1 - y2);
}

int gx, gy;
int memo[1010][1010][5];
int calc(int used, int prev, int x, int y) {
  if (used == 31) {
    return dist(x, y, gx, gy);
  }
  if (memo[x][y][prev] != -1) {
    return memo[x][y][prev];
  }
  int ret = 1 << 25;
  int next = (prev + 1) % 5;
  FORIT(it, points[next]) {
    ret = min(ret, calc(used | (1 << next), next, it->x, it->y) +
                       dist(it->x, it->y, x, y));
  }
  return memo[x][y][prev] = ret;
}

int h, w;
char field[1010][1010];
int main() {
  while (scanf("%d %d", &w, &h), w | h) {
    REP(i, 10) { points[i].clear(); }
    int sx, sy;
    REP(y, h) {
      scanf("%s", field[y]);
      REP(x, w) {
        if (field[y][x] == 'S') {
          sx = x;
          sy = y;
        } else if (field[y][x] == 'G') {
          gx = x;
          gy = y;
        } else if (isdigit(field[y][x])) {
          points[field[y][x] - '1'].push_back(Point(x, y));
        }
      }
    }
    int ans = 1 << 20;
    int type = -1;
    REP(i, 5) {
      memset(memo, -1, sizeof(int) * 5 * 1010 * w);
      int lans = calc(1 << i, i, sx, sy);
      if (lans < ans) {
        ans = lans;
        type = i + 1;
      }
    }
    if (type == -1) {
      puts("NA");
    } else {
      printf("%d %d\\n", type, ans);
    }
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Point {
  int x, y, type;
  Point(int x, int y, int type) : x(x), y(y), type(type) { ; }
};

vector<Point> points[10];
inline int dist(int x1, int y1, int x2, int y2) {
  return abs(x1 - x2) + abs(y1 - y2);
}

int gx, gy;
int memo[5][1010][1010];
int calc(int used, int prev, int x, int y) {
  if (used == 31) {
    return dist(x, y, gx, gy);
  }
  if (memo[prev][x][y] != -1) {
    return memo[prev][x][y];
  }
  int ret = 1 << 25;
  int next = (prev + 1) % 5;
  FORIT(it, points[next]) {
    ret = min(ret, calc(used | (1 << next), next, it->x, it->y) +
                       dist(it->x, it->y, x, y));
  }
  return memo[prev][x][y] = ret;
}

int h, w;
char field[1010][1010];
int main() {
  while (scanf("%d %d", &w, &h), w | h) {
    REP(i, 10) { points[i].clear(); }
    int sx, sy;
    REP(y, h) {
      scanf("%s", field[y]);
      REP(x, w) {
        if (field[y][x] == 'S') {
          sx = x;
          sy = y;
        } else if (field[y][x] == 'G') {
          gx = x;
          gy = y;
        } else if (isdigit(field[y][x])) {
          points[field[y][x] - '1'].push_back(Point(x, y, field[y][x] - 1));
        }
      }
    }
    int ans = 1 << 20;
    int type = -1;
    REP(i, 5) {
      MEMSET(memo, -1);
      int lans = calc(1 << i, i, sx, sy);
      if (lans < ans) {
        ans = lans;
        type = i + 1;
      }
    }
    if (type == -1) {
      puts("NA");
    } else {
      printf("%d %d\\n", type, ans);
    }
  }
}