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

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

typedef vector<char> Array;
typedef vector<Array> Matrix;

struct Water {
  char x;
  char y;
  char dir;
  Water() { ; }
  Water(int x, int y, int dir) : x(x), y(y), dir(dir) { ; }
};

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

int maxDepth;
int calc(int depth, const Matrix &field);
int NextState(int depth, Matrix field, int sx, int sy) {
  if (field[sy][sx] != 4) {
    field[sy][sx]++;
  } else {
    field[sy][sx] = 0;
    vector<Water> waters;
    REP(dir, 4) { waters.push_back(Water(sx, sy, dir)); }
    while (!waters.empty()) {
      vector<Water> nwaters;
      vector<char> end;
      FORIT(it, waters) {
        int nx = it->x + dx[(int)it->dir];
        int ny = it->y + dy[(int)it->dir];
        if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4) {
          continue;
        }
        if (field[ny][nx] != 0) {
          field[ny][nx]++;
          if (field[ny][nx] == 5) {
            end.push_back((ny << 4) + nx);
          }
        } else {
          nwaters.push_back(Water(nx, ny, it->dir));
        }
      }
      FORIT(it, end) {
        int x = *it & 3;
        int y = *it >> 4;
        field[y][x] = 0;
        REP(dir, 4) { nwaters.push_back(Water(x, y, dir)); }
      }
      waters = nwaters;
    }
  }
  return calc(depth + 1, field);
}

int calc(int depth, const Matrix &field) {
  {
    int sum = 0;
    REP(y, 4) REP(x, 4) { sum += field[y][x]; }
    if (sum == 0) {
      return depth;
    }
  }
  if (depth == maxDepth) {
    return 1 << 30;
  }
  int ret = 1 << 30;
  REP(y, 4) {
    REP(x, 4) {
      if (field[y][x] != 0) {
        ret = min(ret, NextState(depth, field, x, y));
        if (ret == maxDepth) {
          return ret;
        }
      }
    }
  }
  return ret;
}

int main() {
  while (true) {
    Matrix field(4, Array(4, 0));
    REP(y, 4) {
      REP(x, 4) {
        int v;
        if (scanf("%d", &v) <= 0) {
          return 0;
        }
        field[y][x] = v;
      }
    }
    int ans = -1;
    REP(iter, 6) {
      maxDepth = iter;
      if (calc(0, field) == maxDepth) {
        ans = maxDepth;
        break;
      }
    }
    printf("%d\\n", ans);
  }
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c)                                                           \\
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

typedef vector<char> Array;
typedef vector<Array> Matrix;

struct Water {
  char x;
  char y;
  char dir;
  Water() { ; }
  Water(int x, int y, int dir) : x(x), y(y), dir(dir) { ; }
};

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

Matrix NextState(Matrix field, int sx, int sy) {
  if (field[sy][sx] != 4) {
    field[sy][sx]++;
  } else {
    field[sy][sx] = 0;
    vector<Water> waters;
    REP(dir, 4) { waters.push_back(Water(sx, sy, dir)); }
    while (!waters.empty()) {
      vector<Water> nwaters;
      vector<char> end;
      FORIT(it, waters) {
        int nx = it->x + dx[(int)it->dir];
        int ny = it->y + dy[(int)it->dir];
        if (nx < 0 || nx >= 4 || ny < 0 || ny >= 4) {
          continue;
        }
        if (field[ny][nx] != 0) {
          field[ny][nx]++;
          if (field[ny][nx] == 5) {
            end.push_back((ny << 4) + nx);
          }
        } else {
          nwaters.push_back(Water(nx, ny, it->dir));
        }
      }
      FORIT(it, end) {
        int x = *it & 3;
        int y = *it >> 4;
        field[y][x] = 0;
        REP(dir, 4) { nwaters.push_back(Water(x, y, dir)); }
      }
      waters = nwaters;
    }
  }
  return field;
}

bool OK(const Matrix &field) {
  int sum = 0;
  REP(y, 4) REP(x, 4) { sum += field[y][x]; }
  return sum == 0;
}

int main() {
  while (true) {
    Matrix field(4, Array(4, 0));
    REP(y, 4) {
      REP(x, 4) {
        int v;
        if (scanf("%d", &v) <= 0) {
          return 0;
        }
        field[y][x] = v;
      }
    }
    int ans = 1 << 30;
    set<Matrix> visit;
    queue<Matrix> que[2];
    que[0].push(field);
    REP(iter, 100) {
      int prev = iter & 1;
      int next = prev ^ 1;
      while (!que[prev].empty()) {
        Matrix matrix = que[prev].front();
        que[prev].pop();
        REP(y, 4) {
          REP(x, 4) {
            if (field[y][x] != 0) {
              Matrix nmatrix = NextState(matrix, x, y);
              if (visit.count(nmatrix)) {
                continue;
              }
              visit.insert(nmatrix);
              if (OK(nmatrix)) {
                ans = iter + 1;
                goto end;
              } else {
                que[next].push(nmatrix);
              }
            }
          }
        }
      }
    }
  end:;
    printf("%d\\n", ans);
  }
}