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

#include <bits/stdc++.h>
using namespace std;
using Int = signed;

Int s[20][20], idx[20][20], cnt, pru;
Int u[40][4];
Int num[40], ok[40];
vector<vector<vector<Int>>> G;

unordered_map<int, int> dp;
Int dfs(Int z, Int b) {
  if (b == 0)
    dp.clear();
  int hs = (b << 5) | z;
  if ((z & 3) == 0)
    if (dp.count(hs))
      return dp[hs];

  Int res = 0;

  for (Int k = 0; k < 4; k++) {
    for (auto w : G[z][k]) {
      if ((b >> w) & 1)
        break;
      Int nb = b ^ (1 << w), flg = 1;
      for (Int i = 0; i < 4; i++) {
        if (u[w][i] >= cnt)
          continue;
        num[u[w][i]]--;
        if ((~nb >> u[w][i]) & 1)
          flg &= num[u[w][i]] >= 1;
      }
      if (flg) {
        if (nb + 1 == (1 << cnt))
          res += ok[w];
        else if ((nb & pru) != pru)
          res += dfs(w, nb);
      }
      for (Int i = 0; i < 4; i++)
        num[u[w][i]]++;
    }
  }

  if ((z & 3) == 0)
    dp[hs] = res;
  return res;
};

// INSERT ABOVE HERE
signed main() {
  Int w, h;
  while (cin >> w >> h, w + h) {
    for (Int i = 0; i < h; i++)
      for (Int j = 0; j < w; j++)
        cin >> s[i][j];

    cnt = 0;
    for (Int i = 0; i < h; i++) {
      for (Int j = 0; j < w; j++) {
        idx[i][j] = cnt;
        cnt += s[i][j] == 1;
      }
    }

    for (Int i = 0; i < h; i++)
      for (Int j = 0; j < w; j++)
        if (s[i][j] == 2)
          idx[i][j] = cnt;

    Int dy[] = {0, 0, 1, -1};
    Int dx[] = {1, -1, 0, 0};
    auto in = [&](Int y, Int x) { return 0 <= y && y < h && 0 <= x && x < w; };

    G.clear();
    G.resize(cnt + 1);

    memset(num, 0, sizeof(num));
    memset(ok, 0, sizeof(ok));

    for (Int y = 0; y < h; y++) {
      for (Int x = 0; x < w; x++) {
        if (s[y][x] == 0)
          continue;
        Int z = idx[y][x];
        G[z].resize(4);
        for (Int k = 0; k < 4; k++) {
          Int ny = y, nx = x;
          while (1) {
            ny += dy[k], nx += dx[k];
            while (in(ny, nx) && s[ny][nx] == 0)
              ny += dy[k], nx += dx[k];
            if (!in(ny, nx))
              break;
            if (s[ny][nx] == 2)
              ok[z] = 1;
            else
              G[z][k].emplace_back(idx[ny][nx]);
          }
        }

        for (Int k = 0; k < 4; k++) {
          u[z][k] = cnt + 1;
          for (auto w : G[z][k]) {
            u[z][k] = w;
            num[w]++;
            break;
          }
        }

        if (z == cnt) {
          pru = 0;
          for (Int k = 0; k < 4; k++) {
            for (auto w : G[z][k]) {
              pru |= (1 << w);
              break;
            }
          }
        }
      }
    }

    cout << dfs(cnt, 0) << endl;
  }
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using Int = signed;

Int s[20][20], idx[20][20], cnt, pru;
Int u[40][4];
Int num[40], ok[40];
vector<vector<vector<Int>>> G;

unordered_map<int, int> dp;
Int dfs(Int z, Int b) {
  if (b == 0)
    dp.clear();
  int hs = (b << 5) | z;
  if ((z & 4) == 0)
    if (dp.count(hs))
      return dp[hs];

  Int res = 0;

  for (Int k = 0; k < 4; k++) {
    for (auto w : G[z][k]) {
      if ((b >> w) & 1)
        break;
      Int nb = b ^ (1 << w), flg = 1;
      for (Int i = 0; i < 4; i++) {
        if (u[w][i] >= cnt)
          continue;
        num[u[w][i]]--;
        if ((~nb >> u[w][i]) & 1)
          flg &= num[u[w][i]] >= 1;
      }
      if (flg) {
        if (nb + 1 == (1 << cnt))
          res += ok[w];
        else if ((nb & pru) != pru)
          res += dfs(w, nb);
      }
      for (Int i = 0; i < 4; i++)
        num[u[w][i]]++;
    }
  }

  if ((z & 4) == 0)
    dp[hs] = res;
  return res;
};

// INSERT ABOVE HERE
signed main() {
  Int w, h;
  while (cin >> w >> h, w + h) {
    for (Int i = 0; i < h; i++)
      for (Int j = 0; j < w; j++)
        cin >> s[i][j];

    cnt = 0;
    for (Int i = 0; i < h; i++) {
      for (Int j = 0; j < w; j++) {
        idx[i][j] = cnt;
        cnt += s[i][j] == 1;
      }
    }

    for (Int i = 0; i < h; i++)
      for (Int j = 0; j < w; j++)
        if (s[i][j] == 2)
          idx[i][j] = cnt;

    Int dy[] = {0, 0, 1, -1};
    Int dx[] = {1, -1, 0, 0};
    auto in = [&](Int y, Int x) { return 0 <= y && y < h && 0 <= x && x < w; };

    G.clear();
    G.resize(cnt + 1);

    memset(num, 0, sizeof(num));
    memset(ok, 0, sizeof(ok));

    for (Int y = 0; y < h; y++) {
      for (Int x = 0; x < w; x++) {
        if (s[y][x] == 0)
          continue;
        Int z = idx[y][x];
        G[z].resize(4);
        for (Int k = 0; k < 4; k++) {
          Int ny = y, nx = x;
          while (1) {
            ny += dy[k], nx += dx[k];
            while (in(ny, nx) && s[ny][nx] == 0)
              ny += dy[k], nx += dx[k];
            if (!in(ny, nx))
              break;
            if (s[ny][nx] == 2)
              ok[z] = 1;
            else
              G[z][k].emplace_back(idx[ny][nx]);
          }
        }

        for (Int k = 0; k < 4; k++) {
          u[z][k] = cnt + 1;
          for (auto w : G[z][k]) {
            u[z][k] = w;
            num[w]++;
            break;
          }
        }

        if (z == cnt) {
          pru = 0;
          for (Int k = 0; k < 4; k++) {
            for (auto w : G[z][k]) {
              pru |= (1 << w);
              break;
            }
          }
        }
      }
    }

    cout << dfs(cnt, 0) << endl;
  }
  return 0;
}