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

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;

int main(void) {
  const ll H = 19, W = 15;
  char S[H][W];
  REP(i, 0, H) REP(j, 0, W) cin >> S[i][j];

  pll white;
  vector<pll> black, cand;
  REP(i, 0, H) REP(j, 0, W) {
    if (S[i][j] == 'O') {
      white = pll(i, j);
      cand.push_back(pll(i, j));
    }
    if (S[i][j] == 'X') {
      black.push_back(pll(i, j));
      REP(di, -1, 2) REP(dj, -1, 2) if (di != 0 || dj != 0) {
        ll ni = i + di, nj = j + dj;
        if (!(0 <= ni && ni < H && 0 <= nj && nj < W))
          break;
        cand.push_back(pll(i + di, j + dj));
      }
    }
  }
  sort(black.begin(), black.end());
  sort(cand.begin(), cand.end());
  cand.erase(unique(cand.begin(), cand.end()), cand.end());

  ll N = black.size(), M = cand.size();
  map<pll, bool> visited;

  struct state {
    ll s, v, d;
  };
  queue<state> q;
  q.push((state){(1LL << N) - 1,
                 lower_bound(cand.begin(), cand.end(), white) - cand.begin(),
                 0});

  while (!q.empty()) {
    ll s = q.front().s, v = q.front().v, d = q.front().d;
    ll y = cand[v].first, x = cand[v].second;
    q.pop();

    visited[pll(s, v)] = true;

    REP(i, -1, 2) REP(j, -1, 2) if (i != 0 || j != 0) {
      ll ns = s, ny = y + i, nx = x + j, nd = d + 1;
      ll cnt = 0;

      while (1) {
        if (!(0 <= ny && ny < H && 0 <= nx && nx < W))
          break;
        if (S[ny][nx] != 'X')
          break;

        ll b = lower_bound(black.begin(), black.end(), pll(ny, nx)) -
               black.begin();
        if (b == N)
          break;
        if (!(ns & (1LL << b)))
          break;

        ns = ns - (1LL << b);
        ny += i;
        nx += j;
        cnt++;
      }

      if (cnt > 0 && ((ny == H - 1 && 0 <= nx && nx < W) || ny >= H)) {
        cout << nd << endl;
        return 0;
      } else if (cnt > 0 && 0 <= ny && ny < H && 0 <= nx && nx < W) {
        ll nv =
            lower_bound(cand.begin(), cand.end(), pll(ny, nx)) - cand.begin();
        if (!visited[pll(ns, nv)])
          q.push((state){ns, nv, nd});
      }
    }
  }
  cout << -1 << endl;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
#define REP(i, a, n) for (ll i = ((ll)a); i < ((ll)n); i++)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;

bool visited[1LL << 20][200];

int main(void) {
  const ll H = 19, W = 15;
  char S[H][W];
  REP(i, 0, H) REP(j, 0, W) cin >> S[i][j];

  pll white;
  vector<pll> black, cand;
  REP(i, 0, H) REP(j, 0, W) {
    if (S[i][j] == 'O') {
      white = pll(i, j);
      cand.push_back(pll(i, j));
    }
    if (S[i][j] == 'X') {
      black.push_back(pll(i, j));
      REP(di, -1, 2) REP(dj, -1, 2) if (di != 0 || dj != 0) {
        ll ni = i + di, nj = j + dj;
        if (!(0 <= ni && ni < H && 0 <= nj && nj < W))
          break;
        cand.push_back(pll(i + di, j + dj));
      }
    }
  }
  sort(black.begin(), black.end());
  sort(cand.begin(), cand.end());
  cand.erase(unique(cand.begin(), cand.end()), cand.end());

  ll N = black.size(), M = cand.size();
  REP(i, 0, 1LL << N) REP(j, 0, M) visited[i][j] = false;

  struct state {
    ll s, v, d;
  };
  queue<state> q;
  q.push((state){(1LL << N) - 1,
                 lower_bound(cand.begin(), cand.end(), white) - cand.begin(),
                 0});

  while (!q.empty()) {
    ll s = q.front().s, v = q.front().v, d = q.front().d;
    ll y = cand[v].first, x = cand[v].second;
    q.pop();

    visited[s][v] = true;

    REP(i, -1, 2) REP(j, -1, 2) if (i != 0 || j != 0) {
      ll ns = s, ny = y + i, nx = x + j, nd = d + 1;
      ll cnt = 0;

      while (1) {
        if (!(0 <= ny && ny < H && 0 <= nx && nx < W))
          break;
        if (S[ny][nx] != 'X')
          break;

        ll b = lower_bound(black.begin(), black.end(), pll(ny, nx)) -
               black.begin();
        if (b == N)
          break;
        if (!(ns & (1LL << b)))
          break;

        ns = ns & (~(1LL << b));
        ny += i;
        nx += j;
        cnt++;
      }

      if (cnt > 0 && ny >= H - 1) {
        cout << nd << endl;
        return 0;
      } else if (cnt > 0) {
        ll nv =
            lower_bound(cand.begin(), cand.end(), pll(ny, nx)) - cand.begin();
        if (!visited[ns][nv])
          q.push((state){ns, nv, nd});
      }
    }
  }
  cout << -1 << endl;
}