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

#include <cstdio>
#include <map>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
struct P {
  int x, y;
  P() {}
  P(int X, int Y) : x(X), y(Y) {}
};

map<int, int> dp[24];
int adj[24][4][23], deg[24][4], house_num;

int dfs(int id, int picked) {
  if (dp[id].find(picked) != dp[id].end())
    return dp[id][picked];

  if (picked == (1 << (house_num + 1)) - 1) {
    rep(k, 4) rep(a, deg[id][k]) if (adj[id][k][a] == house_num) return 1;
    return 0;
  }

  int ans = 0;
  rep(k, 4) rep(a, deg[id][k]) {
    int next_id = adj[id][k][a];
    if ((picked & (1 << next_id)) == 0) {
      ans += dfs(next_id, picked | (1 << next_id));
      break;
    }
  }

  if (dp[id].size() < 10000)
    dp[id][picked] = ans;
  return ans;
}

int main() {
  for (int n, m; scanf("%d%d", &n, &m), n;) {
    int field[10][10], charch_x, charch_y, f[10][10];
    house_num = 0;
    rep(i, m) rep(j, n) {
      scanf("%d", field[i] + j);
      if (field[i][j] == 1)
        f[i][j] = house_num++;
      if (field[i][j] == 2)
        charch_x = j, charch_y = i;
    }
    f[charch_y][charch_x] = house_num;

    rep(i, m) rep(j, n) if (field[i][j] != 0) {
      int id = f[i][j];
      dp[id].clear();
      rep(k, 4) {
        deg[id][k] = 0;
        int x = j + dx[k], y = i + dy[k];
        while (0 <= y && y < m && 0 <= x && x < n) {
          if (field[y][x] != 0)
            adj[id][k][deg[id][k]++] = f[y][x];
          x += dx[k], y += dy[k];
        }
      }
    }

    printf("%d\\n", dfs(house_num, 1 << house_num));
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cstdio>
#include <map>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
struct P {
  int x, y;
  P() {}
  P(int X, int Y) : x(X), y(Y) {}
};

map<int, int> dp[24];
int adj[24][4][23], deg[24][4], house_num;

int dfs(int id, int picked) {
  if (dp[id].find(picked) != dp[id].end())
    return dp[id][picked];

  if (picked == (1 << (house_num + 1)) - 1) {
    rep(k, 4) rep(a, deg[id][k]) if (adj[id][k][a] == house_num) return 1;
    return 0;
  }

  int ans = 0;
  rep(k, 4) rep(a, deg[id][k]) {
    int next_id = adj[id][k][a];
    if ((picked & (1 << next_id)) == 0) {
      ans += dfs(next_id, picked | (1 << next_id));
      break;
    }
  }

  if (dp[id].size() < 1000)
    dp[id][picked] = ans;
  return ans;
}

int main() {
  for (int n, m; scanf("%d%d", &n, &m), n;) {
    int field[10][10], charch_x, charch_y, f[10][10];
    house_num = 0;
    rep(i, m) rep(j, n) {
      scanf("%d", field[i] + j);
      if (field[i][j] == 1)
        f[i][j] = house_num++;
      if (field[i][j] == 2)
        charch_x = j, charch_y = i;
    }
    f[charch_y][charch_x] = house_num;

    rep(i, m) rep(j, n) if (field[i][j] != 0) {
      int id = f[i][j];
      dp[id].clear();
      rep(k, 4) {
        deg[id][k] = 0;
        int x = j + dx[k], y = i + dy[k];
        while (0 <= y && y < m && 0 <= x && x < n) {
          if (field[y][x] != 0)
            adj[id][k][deg[id][k]++] = f[y][x];
          x += dx[k], y += dy[k];
        }
      }
    }

    printf("%d\\n", dfs(house_num, 1 << house_num));
  }

  return 0;
}