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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < b ? (a = b, 1) : 0)
#define chmin(a, b) (a > b ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
const int INF = 1 << 29;
typedef long long ll;
typedef pair<int, int> pii;

char ba[50][50];

struct P {
  int y, x;
  int d;
  int dist;
  P(int y, int x, int d, int dist) : y(y), x(x), d(d), dist(dist) {}
  bool operator<(const P &p) const { return dist > p.dist; }
};

int dist[50][50][4];

int &get(const P &p) { return dist[p.y][p.x][p.d]; }

const int dy[4] = {0, 1, 0, -1};
const int dx[4] = {1, 0, -1, 0};

const int kdy[4] = {0, 0, 1, 1};
const int kdx[4] = {0, 1, 0, 1};

const int pdy[4][2] = {0, 1, 2, 2, 0, 1, -1, -1};
const int pdx[4][2] = {2, 2, 0, 1, -1, -1, 0, 1};

int h, w;

bool ok(int y, int x) { return valid(y, x, h, w) && ba[y][x] != '*'; }

bool isKing(int i, int j, int y, int x) {
  REP(k, 4) {
    int yy = y + kdy[k];
    int xx = x + kdx[k];
    if (yy == i & xx == j)
      return 1;
  }
  return 0;
}

int dist2[2][50][50];

void calcPawnDist(int id, int i, int j, int ky, int kx) {
  queue<pii> Q;
  Q.push(pii(i, j));
  dist2[id][i][j] = 0;
  while (!Q.empty()) {
    pii p = Q.front();
    Q.pop();
    REP(k, 4) {
      int y = p.first + dy[k];
      int x = p.second + dx[k];
      if (!ok(y, x) || isKing(y, x, ky, kx) || dist2[id][y][x] != -1)
        continue;
      Q.push(pii(y, x));
      dist2[id][y][x] = dist2[id][p.first][p.second] + 1;
    }
  }
}

int main() {
  while (cin >> h >> w, h || w) {
    REP(i, h) REP(j, w) cin >> ba[i][j];
    int ky = -1, kx;
    vector<pii> ps;
    REP(i, h) REP(j, w) {
      if (ky == -1 && ba[i][j] == 'X')
        ky = i, kx = j;
      if (ba[i][j] == '.')
        ps.push_back(pii(i, j));
    }
    assert(ps.size() == 2 && ky != -1);

    if (ky == 0 && kx == 0) {
      cout << 0 << endl;
      continue;
    }

    memset(dist2, -1, sizeof(dist2));
    REP(i, 2) {
      int y = ps[i].first;
      int x = ps[i].second;
      calcPawnDist(i, y, x, ky, kx);
    }

    memset(dist, 0x3f, sizeof(dist));
    priority_queue<P> PQ;

    REP(d, 4) {
      int cost[2][2];
      bool f = 1;
      REP(i, 2) {
        int y = ky + pdy[d][i];
        int x = kx + pdx[d][i];
        if (!ok(y, x)) {
          f = 0;
          break;
        }
        REP(j, 2) {
          cost[i][j] = dist2[j][y][x];
          if (cost[i][j] == -1)
            f = 0;
        }
      }
      if (f) {
        int dis = min(cost[0][0] + cost[1][1], cost[0][1] + cost[1][0]);
        dist[ky][kx][d] = dis;
        PQ.push(P(ky, kx, d, dis));
      }
    }

    int ans = -1;

    while (!PQ.empty()) {
      P p = PQ.top();
      PQ.pop();

      if (p.dist > get(p))
        continue;

      // cout << p.dist << endl;
      // char c[h][w];
      // REP(i,h)REP(j,w)c[i][j]=(ba[i][j]=='*'?'*':'o');
      // REP(k,4) {
      //   int y=p.y + kdy[k];
      //   int x=p.x + kdx[k];
      //   c[y][x]='X';
      // }
      // REP(i,2) c[p.y+pdy[p.d][i]][p.x+pdx[p.d][i]] = '.';
      // REP(i,h) { REP(j,w) cout << c[i][j]; cout << endl;}
      // cout << endl;

      if (p.y == 0 && p.x == 0) {
        ans = p.dist;
        break;
      }

      // pawn
      memset(dist2, -1, sizeof(dist2));
      REP(i, 2) {
        int y = p.y + pdy[p.d][i];
        int x = p.x + pdx[p.d][i];
        calcPawnDist(i, y, x, p.y, p.x);
      }

      REP(d, 4) {
        int cost[2][2];
        bool f = 1;
        REP(i, 2) {
          int ty = p.y + pdy[d][i];
          int tx = p.x + pdx[d][i];
          if (!ok(ty, tx)) {
            f = 0;
            break;
          }
          REP(j, 2) {
            cost[i][j] = dist2[j][ty][tx];
            if (cost[i][j] == -1)
              f = 0;
          }
        }
        if (f) {
          int dis = min(cost[0][0] + cost[1][1], cost[0][1] + cost[1][0]);
          P nxt(p.y, p.x, d, p.dist + dis);
          if (get(nxt) > p.dist + dis) {
            get(nxt) = p.dist + dis;
            PQ.push(nxt);
          }
        }
      }

      // king
      int y = p.y + dy[p.d];
      int x = p.x + dx[p.d];
      P nxt(y, x, (p.d + 2) % 4, p.dist + 1);
      if (get(nxt) > p.dist + 1) {
        get(nxt) = p.dist + 1;
        PQ.push(nxt);
      }
    }
    cout << ans << endl;
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < b ? (a = b, 1) : 0)
#define chmin(a, b) (a > b ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
const int INF = 1 << 29;
typedef long long ll;
typedef pair<int, int> pii;

char ba[50][50];

struct P2 {
  int y1, x1;
  int y2, x2;
  P2(int y1, int x1, int y2, int x2) : y1(y1), x1(x1), y2(y2), x2(x2) {}
};
int dist2[50][50][50][50];

struct P {
  int ky, kx;
  int py, px;
  int d;
  int dist;
  P(int ky, int kx, int py, int px, int d, int dist)
      : ky(ky), kx(kx), py(py), px(px), d(d), dist(dist) {}
  bool operator<(const P &p) const { return dist > p.dist; }
};
int dist[50][50][50][50][2];

int &get(const P2 &p) { return dist2[p.y1][p.x1][p.y2][p.x2]; }

int &get(const P &p) { return dist[p.ky][p.kx][p.py][p.px][p.d]; }

const int dy[4] = {0, 1, 0, -1};
const int dx[4] = {1, 0, -1, 0};

const int dy2[2][4] = {{0, 0, -1, -1}, {0, 0, 1, 1}};
const int dx2[2][4] = {{0, 1, 0, 1}, {-1, 0, -1, 0}};

const int kdy[4] = {0, 0, 1, 1};
const int kdx[4] = {0, 1, 0, 1};

const int dy3[4] = {0, 0, 0, 1};
const int dx3[4] = {0, 0, 1, 0};

int h, w;

bool collideKing(int y, int x, int d, int ky, int kx) {
  int y2 = y + dy[d];
  int x2 = x + dx[d];
  if (!valid(y, x, h, w) || !valid(y2, x2, h, w))
    return 1;
  if (ba[y][x] == '*' || ba[y2][x2] == '*')
    return 1;
  REP(i, 4) {
    int kyy = ky + kdy[i];
    int kxx = kx + kdx[i];
    if (y == kyy && x == kxx || y2 == kyy && x2 == kxx)
      return 1;
  }
  return 0;
}

bool okKing(int y, int x) {
  REP(i, 4) {
    int yy = y + kdy[i];
    int xx = x + kdx[i];
    if (!valid(yy, xx, h, w))
      return 0;
    if (ba[yy][xx] == '*')
      return 0;
  }
  return 1;
}

int countCollide(int y, int x, int d, int ky, int kx) {
  int y2 = y + dy[d];
  int x2 = x + dx[d];
  if (!valid(y, x, h, w) || !valid(y2, x2, h, w))
    return 0;
  int cnt = 0;
  REP(i, 4) {
    int kyy = ky + kdy[i];
    int kxx = kx + kdx[i];
    if (y == kyy && x == kxx || y2 == kyy && x2 == kxx)
      cnt++;
  }
  return cnt;
}

int main() {
  while (cin >> h >> w, h || w) {
    REP(i, h) REP(j, w) cin >> ba[i][j];
    int ky = -1, kx;
    vector<pii> ps;
    REP(i, h) REP(j, w) {
      if (ky == -1 && ba[i][j] == 'X') {
        ky = i, kx = j;
      }
      if (ba[i][j] == '.') {
        ps.push_back(pii(i, j));
      }
    }
    assert(ps.size() == 2 && ky != -1);

    if (ky == 0 && kx == 0) {
      cout << 0 << endl;
      continue;
    }

    memset(dist, 0x3f, sizeof(dist));
    priority_queue<P> PQ;

    queue<P2> Q;
    memset(dist2, -1, sizeof(dist2));
    P2 tmp(ps[0].first, ps[0].second, ps[1].first, ps[1].second);
    Q.push(tmp);
    get(tmp) = 0;

    while (!Q.empty()) {
      P2 p = Q.front();
      Q.pop();

      int cost = get(p);
      // cout << p.y1 << " " << p.x1 << " , " << p.y2 << " " << p.x2 << endl;
      if (abs(p.y1 - p.y2) + abs(p.x1 - p.x2) == 1) {
        int d = 0;
        if (p.x1 == p.x2)
          d = 1;
        P pq(ky, kx, min(p.y1, p.y2), min(p.x1, p.x2), d, cost);
        if (get(pq) > cost) {
          PQ.push(pq);
          get(pq) = cost;
        }
      }
      REP(i, 4) {
        int y = p.y1 + dy[i];
        int x = p.x1 + dx[i];
        if (!valid(y, x, h, w) || ba[y][x] == '*' || ba[y][x] == 'X')
          continue;
        P2 nxt(y, x, p.y2, p.x2);
        if (get(nxt) == -1) {
          get(nxt) = cost + 1;
          Q.push(nxt);
        }
      }
      REP(i, 4) {
        int y = p.y2 + dy[i];
        int x = p.x2 + dx[i];
        if (!valid(y, x, h, w) || ba[y][x] == '*' || ba[y][x] == 'X')
          continue;
        P2 nxt(p.y1, p.x1, y, x);
        if (get(nxt) == -1) {
          get(nxt) = cost + 1;
          Q.push(nxt);
        }
      }
    }

    int ans = -1;

    while (!PQ.empty()) {
      P p = PQ.top();
      PQ.pop();

      if (p.dist > get(p))
        continue;

      if (p.ky == 0 && p.kx == 0) {
        ans = p.dist;
        break;
      }

      // cout << p.ky << " " << p.kx << " " << p.py << " " << p.px << " " << p.d
      // << " " << p.dist << endl; pawn slide
      REP(i, 4) {
        int y = p.py + dy[i];
        int x = p.px + dx[i];
        if (!valid(y, x, h, w) || collideKing(y, x, p.d, p.ky, p.kx) ||
            ba[y][x] == '*')
          continue;
        P nxt(p.ky, p.kx, y, x, p.d, p.dist + 2);
        if (get(nxt) > p.dist + 2) {
          get(nxt) = p.dist + 2;
          PQ.push(nxt);
        }
      }
      // rotate
      REP(i, 4) {
        int y = p.py + dy2[p.d][i];
        int x = p.px + dx2[p.d][i];
        if (!valid(y, x, h, w) || collideKing(y, x, !p.d, p.ky, p.kx) ||
            ba[y][x] == '*')
          continue;
        P nxt(p.ky, p.kx, y, x, !p.d, p.dist + 2);
        if (get(nxt) > p.dist + 2) {
          get(nxt) = p.dist + 2;
          PQ.push(nxt);
        }
      }
      // king
      REP(i, 4) {
        int y = p.ky + dy[i];
        int x = p.kx + dx[i];
        if (countCollide(p.py, p.px, p.d, y, x) != 2)
          continue;
        P nxt(y, x, p.ky + dy3[i], p.kx + dx3[i], p.d, p.dist + 1);

        if (get(nxt) > p.dist + 1) {
          get(nxt) = p.dist + 1;
          PQ.push(nxt);
        }
      }
    }
    cout << ans << endl;
  }
}