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

#include <bits/stdc++.h>
#define int short

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = (int)(a)-1; i >= (int)(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))

// #define DEBUG

#ifdef DEBUG
#define dump(...) fprintf(stderr, __VA_ARGS__)
#else
#define dump(...)
#endif

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using namespace std;
using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;

const double EPS = 1e-10;
const double PI = acos(-1.0);
const int inf = 1 << 10;
const ll mod = 1000000007LL;
const int dx[] = {1, 0, -1, 0, 0};
const int dy[] = {0, 1, 0, -1, 0};

ll extgcd(ll a, ll b, ll &x, ll &y) {
  x = 1, y = 0;
  ll g = a;
  if (b != 0)
    g = extgcd(b, a % b, y, x), y -= a / b * x;
  return g;
}
ll ADD(const ll &a, const ll &b, const ll &mod) { return (a + b) % mod; }
ll SUB(const ll &a, const ll &b, const ll &mod) { return (a - b + mod) % mod; }
ll MUL(const ll &a, const ll &b, const ll &mod) { return (1LL * a * b) % mod; }
ll DIV(const ll &a, const ll &b, const ll &mod) {
  ll x, y;
  extgcd(b, mod, x, y);
  return MUL(a, (x + mod) % mod, mod);
}

random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dice(1, 6);
uniform_real_distribution<double> score(0.0, 10.0);

const int N = 16, M = 150;
int w, h, n;
vector<string> field;
short memo[M][M][M];
int p2i[N][N];
int i2x[M], i2y[M];

using State = tuple<int, int, int>;
using Elem = tuple<int, State>;

inline bool check(State pre, State cur) {
  int pp[3], cp[3];
  tie(pp[0], pp[1], pp[2]) = pre;
  tie(cp[0], cp[1], cp[2]) = cur;

  // exchange
  rep(i, 3) {
    int j = (i + 1) % 3;
    if (i >= n or j >= n)
      continue;

    if (pp[i] == cp[j] and pp[j] == cp[i]) {
      return false;
    }
  }

  // overlap
  rep(i, 3) {
    int j = (i + 1) % 3;
    if (i >= n or j >= n)
      continue;

    if (cp[i] == cp[j]) {
      return false;
    }
  }

  return true;
}

signed main(void) {
  for (; cin >> w >> h >> n, w;) {
    field = vector<string>(h);
    cin.ignore();
    for (auto &e : field)
      getline(cin, e);

    i2x[0] = 0, i2y[0] = 0;
    {
      int cnt = 1;
      rep(y, h) {
        rep(x, w) {
          if (field[y][x] != '#') {
            p2i[y][x] = cnt;
            i2x[cnt] = x;
            i2y[cnt] = y;
            cnt++;
          } else
            p2i[y][x] = -1;
        }
      }
    }
    p2i[0][0] = 0;

    State s = State(0, 0, 0), z = State(0, 0, 0);
    rep(y, h) {
      rep(x, w) {
        int as, bs, cs, az, bz, cz;
        tie(as, bs, cs) = s;
        tie(az, bz, cz) = z;

        switch (field[y][x]) {
        case 'a': {
          as = p2i[y][x];
          break;
        }
        case 'b': {
          bs = p2i[y][x];
          break;
        }
        case 'c': {
          cs = p2i[y][x];
          break;
        }
        case 'A': {
          az = p2i[y][x];
          break;
        }
        case 'B': {
          bz = p2i[y][x];
          break;
        }
        case 'C': {
          cz = p2i[y][x];
          break;
        }
        }
        s = State(as, bs, cs);
        z = State(az, bz, cz);
      }
    }

    rep(i, M) rep(j, M) rep(k, M) memo[i][j][k] = inf;

    queue<Elem> q;
    q.push(Elem(0, s));

    while (q.size()) {
      short cost;
      State cur;
      tie(cost, cur) = q.front();
      q.pop();
      int ap, bp, cp;
      tie(ap, bp, cp) = cur;

      short &ret = memo[ap][bp][cp];
      if (ret != inf)
        continue;
      ret = cost;

      rep(i, 5) {
        int ax = i2x[ap] + dx[i], ay = i2y[ap] + dy[i];
        if (p2i[ay][ax] == -1)
          continue;

        rep(j, 5) {
          if (n <= 1 and j <= 3)
            continue;

          int bx = i2x[bp] + dx[j], by = i2y[bp] + dy[j];
          if (p2i[by][bx] == -1)
            continue;

          rep(k, 5) {
            if (n <= 2 and k <= 3)
              continue;

            int cx = i2x[cp] + dx[k], cy = i2y[cp] + dy[k];
            if (p2i[cy][cx] == -1)
              continue;

            State next = State(p2i[ay][ax], p2i[by][bx], p2i[cy][cx]);
            if (not check(cur, next))
              continue;
            q.push(Elem(cost + 1, next));
          }
        }
      }
    }

    int az, bz, cz;
    tie(az, bz, cz) = z;
    cout << memo[az][bz][cz] << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>

#define _overload(_1, _2, _3, name, ...) name
#define _rep(i, n) _range(i, 0, n)
#define _range(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep(...) _overload(__VA_ARGS__, _range, _rep, )(__VA_ARGS__)

#define _rrep(i, n) _rrange(i, n, 0)
#define _rrange(i, a, b) for (int i = (int)(a)-1; i >= (int)(b); --i)
#define rrep(...) _overload(__VA_ARGS__, _rrange, _rrep, )(__VA_ARGS__)

#define _all(arg) begin(arg), end(arg)
#define uniq(arg) sort(_all(arg)), (arg).erase(unique(_all(arg)), end(arg))
#define getidx(ary, key) lower_bound(_all(ary), key) - begin(ary)
#define clr(a, b) memset((a), (b), sizeof(a))
#define bit(n) (1LL << (n))

// #define DEBUG

#ifdef DEBUG
#define dump(...) fprintf(stderr, __VA_ARGS__)
#else
#define dump(...)
#endif

template <class T> bool chmax(T &a, const T &b) {
  return (a < b) ? (a = b, 1) : 0;
}
template <class T> bool chmin(T &a, const T &b) {
  return (b < a) ? (a = b, 1) : 0;
}

using namespace std;
using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;

const double EPS = 1e-10;
const double PI = acos(-1.0);
const int inf = 1 << 10;
const ll mod = 1000000007LL;
const int dx[] = {1, 0, -1, 0, 0};
const int dy[] = {0, 1, 0, -1, 0};

ll extgcd(ll a, ll b, ll &x, ll &y) {
  x = 1, y = 0;
  ll g = a;
  if (b != 0)
    g = extgcd(b, a % b, y, x), y -= a / b * x;
  return g;
}
ll ADD(const ll &a, const ll &b, const ll &mod) { return (a + b) % mod; }
ll SUB(const ll &a, const ll &b, const ll &mod) { return (a - b + mod) % mod; }
ll MUL(const ll &a, const ll &b, const ll &mod) { return (1LL * a * b) % mod; }
ll DIV(const ll &a, const ll &b, const ll &mod) {
  ll x, y;
  extgcd(b, mod, x, y);
  return MUL(a, (x + mod) % mod, mod);
}

random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dice(1, 6);
uniform_real_distribution<double> score(0.0, 10.0);

const int N = 16, M = 150;
int w, h, n;
vector<string> field;
short memo[M][M][M];
int p2i[N][N];
int i2x[M], i2y[M];

using State = tuple<int, int, int>;
using Elem = tuple<int, State>;

inline bool check(State pre, State cur) {
  int pp[3], cp[3];
  tie(pp[0], pp[1], pp[2]) = pre;
  tie(cp[0], cp[1], cp[2]) = cur;

  // exchange
  rep(i, 3) {
    int j = (i + 1) % 3;
    if (i >= n or j >= n)
      continue;

    if (pp[i] == cp[j] and pp[j] == cp[i]) {
      return false;
    }
  }

  // overlap
  rep(i, 3) {
    int j = (i + 1) % 3;
    if (i >= n or j >= n)
      continue;

    if (cp[i] == cp[j]) {
      return false;
    }
  }

  return true;
}

int main(void) {
  for (; cin >> w >> h >> n, w;) {
    field = vector<string>(h);
    cin.ignore();
    for (auto &e : field)
      getline(cin, e);

    i2x[0] = 0, i2y[0] = 0;
    {
      int cnt = 1;
      rep(y, h) {
        rep(x, w) {
          if (field[y][x] != '#') {
            p2i[y][x] = cnt;
            i2x[cnt] = x;
            i2y[cnt] = y;
            cnt++;
          } else
            p2i[y][x] = -1;
        }
      }
    }
    p2i[0][0] = 0;

    State s = State(0, 0, 0), z = State(0, 0, 0);
    rep(y, h) {
      rep(x, w) {
        int as, bs, cs, az, bz, cz;
        tie(as, bs, cs) = s;
        tie(az, bz, cz) = z;

        switch (field[y][x]) {
        case 'a': {
          as = p2i[y][x];
          break;
        }
        case 'b': {
          bs = p2i[y][x];
          break;
        }
        case 'c': {
          cs = p2i[y][x];
          break;
        }
        case 'A': {
          az = p2i[y][x];
          break;
        }
        case 'B': {
          bz = p2i[y][x];
          break;
        }
        case 'C': {
          cz = p2i[y][x];
          break;
        }
        }
        s = State(as, bs, cs);
        z = State(az, bz, cz);
      }
    }

    rep(i, M) rep(j, M) rep(k, M) memo[i][j][k] = inf;

    queue<Elem> q;
    q.push(Elem(0, s));

    while (q.size()) {
      short cost;
      State cur;
      tie(cost, cur) = q.front();
      q.pop();
      int ap, bp, cp;
      tie(ap, bp, cp) = cur;

      short &ret = memo[ap][bp][cp];
      if (ret != inf)
        continue;
      ret = cost;

      rep(i, 5) {
        int ax = i2x[ap] + dx[i], ay = i2y[ap] + dy[i];
        if (p2i[ay][ax] == -1)
          continue;

        rep(j, 5) {
          if (n <= 1 and j <= 3)
            continue;

          int bx = i2x[bp] + dx[j], by = i2y[bp] + dy[j];
          if (p2i[by][bx] == -1)
            continue;

          rep(k, 5) {
            if (n <= 2 and k <= 3)
              continue;

            int cx = i2x[cp] + dx[k], cy = i2y[cp] + dy[k];
            if (p2i[cy][cx] == -1)
              continue;

            State next = State(p2i[ay][ax], p2i[by][bx], p2i[cy][cx]);
            if (not check(cur, next))
              continue;
            q.push(Elem(cost + 1, next));
          }
        }
      }
    }

    int az, bz, cz;
    tie(az, bz, cz) = z;
    cout << memo[az][bz][cz] << endl;
  }

  return 0;
}