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

#include <algorithm>
#include <bitset>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <vector>

using namespace std;

typedef long long ll;

const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const int MAX = 21;
int W, H, fld[10][10];
int P, sx, sy;
map<pair<pair<int, int>, int>, int> memo;

inline int CountBit(int s) {
  int res = 0;
  for (int i = 0; i < P; i++)
    res += (s >> i) & 1;
  return res;
}

inline bool IsInside(int x, int y) {
  return 0 <= x && x < W && 0 <= y && y < H;
}

inline bool CanDown(int x, int y, int s, int noBits) {
  if (x == sx && y == sy && noBits == P)
    return true;
  if (fld[y][x] == -1)
    return false;
  return ((s >> fld[y][x]) & 1) == 0;
}

int DFS(int x, int y, int s) {
  int cnt = CountBit(s);
  if (x == sx && y == sy && cnt == P)
    return 1;
  pair<pair<int, int>, int> state = make_pair(make_pair(x, y), s);
  if (cnt < MAX) {
    map<pair<pair<int, int>, int>, int>::iterator itr = memo.find(state);
    if (itr != memo.end())
      return itr->second;
  }
  int sum = 0;
  for (int i = 0; i < 4; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    while (IsInside(nx, ny) && !CanDown(nx, ny, s, cnt))
      nx += dx[i], ny += dy[i];
    if (!IsInside(nx, ny))
      continue;
    sum += DFS(nx, ny, s | (1 << fld[ny][nx]));
  }
  if (cnt < MAX && !(cnt >= 18 && sum == 0))
    memo[state] = sum;
  return sum;
}

signed main() {
  while (cin >> W >> H, W || H) {
    memo.clear();
    P = 0;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        cin >> fld[i][j];
        if (fld[i][j] == 0)
          fld[i][j] = -1;
        else if (fld[i][j] == 1)
          fld[i][j] = P++;
        else
          sx = j, sy = i, fld[i][j] = -1;
      }
    }
    printf("%d\\n", DFS(sx, sy, 0));
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <vector>

using namespace std;

typedef long long ll;

const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const int MAX = 1 << 15;
int W, H, fld[10][10];
int P, sx, sy;
int memo[MAX][10][10];

inline int CountBit(int s) {
  int res = 0;
  for (int i = 0; i < P; i++)
    res += (s >> i) & 1;
  return res;
}

inline bool IsInside(int x, int y) {
  return 0 <= x && x < W && 0 <= y && y < H;
}

inline bool CanDown(int x, int y, int s, int noBits) {
  if (x == sx && y == sy && noBits == P)
    return true;
  if (fld[y][x] == -1)
    return false;
  return ((s >> fld[y][x]) & 1) == 0;
}

int DFS(int x, int y, int s) {
  int cnt = CountBit(s);
  if (x == sx && y == sy && cnt == P)
    return 1;
  pair<pair<int, int>, int> state = make_pair(make_pair(x, y), s);
  if (s < MAX) {
    if (memo[s][x][y] != -1)
      return memo[s][x][y];
  }
  int sum = 0;
  for (int i = 0; i < 4; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    while (IsInside(nx, ny) && !CanDown(nx, ny, s, cnt))
      nx += dx[i], ny += dy[i];
    if (!IsInside(nx, ny))
      continue;
    sum += DFS(nx, ny, s | (1 << fld[ny][nx]));
  }
  if (s < MAX)
    memo[s][x][y] = sum;
  return sum;
}

signed main() {
  while (cin >> W >> H, W || H) {
    P = 0;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        cin >> fld[i][j];
        if (fld[i][j] == 0)
          fld[i][j] = -1;
        else if (fld[i][j] == 1)
          fld[i][j] = P++;
        else
          sx = j, sy = i, fld[i][j] = -1;
      }
    }
    fill_n((int *)memo, min(1 << P, MAX) * 10 * 10, -1);
    printf("%d\\n", DFS(sx, sy, 0));
  }
  return 0;
}