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

#include <algorithm>
#include <iostream>
#include <set>
#include <unordered_map>
#include <vector>

using namespace std;

typedef pair<int, int> P;

int HashH(int now, set<int> &vis) {
  int val = now;
  for (auto x : vis) {
    val += (1 << (x + 7));
  }
  return val;
}

int dfs(int now, set<int> &vis, unordered_map<int, int> &dp,
        vector<vector<vector<int>>> &e, int church, int cnt) {
  int hashval = HashH(now, vis);

  if (dp.count(hashval) != 0) {
    return dp[hashval];
  } else if (cnt == 0 && now == church) {
    return dp[hashval] = 1;
  }

  int dh[4] = {-1, 0, 1, 0};
  int dw[4] = {0, -1, 0, 1};

  int ret = 0;
  for (int d = 0; d < 4; ++d) {
    for (int i = 0; i < (int)e[d][now].size(); ++i) {
      if (vis.count(e[d][now][i]) == 0) {
        if (e[d][now][i] == church && cnt > 1)
          continue;
        vis.insert(e[d][now][i]);
        ret += dfs(e[d][now][i], vis, dp, e, church, cnt - 1);
        vis.erase(e[d][now][i]);
        break;
      }
    }
  }
  return dp[hashval] = ret;
}

void solve(int m, int n) {
  vector<vector<int>> mp(n);
  int cnt = 0;
  vector<P> hou;
  P ch;
  set<int> vis;

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      int temp;
      cin >> temp;
      if (temp == 1) {
        mp[i].push_back(cnt);
        hou.push_back(P(i, j));
        ++cnt;
      } else if (temp == 2) {
        ch = P(i, j);
        mp[i].push_back(-2);
      } else {
        mp[i].push_back(-1);
      }
    }
  }

  hou.push_back(ch);
  mp[ch.first][ch.second] = cnt;

  // edge
  vector<vector<vector<int>>> e(4);
  for (int i = 0; i < 4; ++i)
    e[i].resize(cnt + 1);

  for (int i = 0; i < (int)hou.size(); ++i) {
    P now = hou[i];
    int dh[4] = {-1, 0, 1, 0};
    int dw[4] = {0, -1, 0, 1};
    for (int d = 0; d < 4; ++d) {
      P nxt = now;
      while (true) {
        nxt.first += dh[d];
        nxt.second += dw[d];
        if (nxt.first < 0 || nxt.first >= n || nxt.second < 0 ||
            nxt.second >= m)
          break;
        if (mp[nxt.first][nxt.second] >= 0)
          e[d][i].push_back(mp[nxt.first][nxt.second]);
      }
    }
  }

  unordered_map<int, int> dp;
  int ans = dfs(cnt, vis, dp, e, cnt, cnt + 1);
  cout << ans << endl;
  return;
}

int main() {
  int m, n;
  while (true) {
    cin >> m >> n;
    if (m == 0 && n == 0)
      break;
    solve(m, n);
  }
  return 0;
}


Error: MLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <numeric>
#include <queue>
#include <vector>

using namespace std;

typedef pair<int, int> P;

struct QUE {
  P house;
  int count;
  vector<int> visit;
  QUE() {}
  QUE(P a, int b, vector<int> c) {
    this->house = a;
    this->count = b;
    this->visit = c;
  }
};

void solve(int m, int n) {
  vector<int> mp[n];
  P church;
  int cnt = 0;

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      int temp;
      cin >> temp;
      if (temp == 1) {
        ++cnt;
        mp[i].push_back(cnt);
      } else if (temp == 2) {
        church = P(i, j);
        mp[i].push_back(100);
      } else {
        mp[i].push_back(0);
      }
    }
  }

  int ans = 0;

  queue<QUE> q;
  vector<int> vis(cnt + 1, 0);
  q.push(QUE(church, 0, vis));
  while (!q.empty()) {
    QUE now = q.front();
    q.pop();

    int dh[4] = {-1, 0, 1, 0};
    int dw[4] = {0, 1, 0, -1};
    for (int i = 0; i < 4; ++i) {
      P h = now.house;
      while (true) {
        h.first += dh[i];
        h.second += dw[i];

        if (h.first < 0 || h.first >= n || h.second < 0 || h.second >= m)
          break;

        int v = mp[h.first][h.second];
        if (v != 0 && v != 100 && now.visit[v] == 0) {
          now.visit[v] = 1;
          q.push(QUE(h, now.count + 1, now.visit));
          now.visit[v] = 0;
          break;
        } else if (v == 100 && now.count == cnt) {
          ++ans;
          break;
        }
      }
    }
  }

  cout << ans << endl;

  return;
}

int main() {
  int m, n;
  while (true) {
    cin >> m >> n;
    if (n == 0 && m == 0)
      break;
    solve(m, n);
  }
  return 0;
}