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

#include <bits/stdc++.h>
#define MAX 51
#define inf 1 << 29
#define inf2 1 << 15
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0 + sqrt(5.0)) / 2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(), (a).end()
#define pd(a) printf("%.10f\\n", (double)(a))
#define pld(a) printf("%.10Lf\\n", (ld)(a))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, a, b) for (int i = (a)-1; (b) <= i; i--)
#define Unique(v) v.erase(unique(all(v)), v.end())
#define equals(a, b) (fabs((a) - (b)) < eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, int> pdi;
typedef pair<double, double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;

int h, w;
string grid[MAX];
int mem[MAX][MAX][MAX][MAX];
vector<pii> alph;

bool in(int y, int x) {
  if (x < 0 || y < 0 || w <= x || h <= y)
    return false;
  return true;
}

int rec(int a, int b, int c, int d) {
  if (!in(a, b))
    return -inf2;
  if (!in(c, d))
    return -inf2;
  if (c < a || d < b)
    return -inf2;
  if (mem[a][b][c][d] != -inf)
    return mem[a][b][c][d];
  if (grid[a][b] == '#')
    return mem[a][b][c][d] = -inf2;
  if (grid[c][d] == '#')
    return mem[a][b][c][d] = -inf2;
  if (a == c && b == d && grid[a][b] != '#')
    return mem[a][b][c][d] = 0;
  int res = -inf2;

  if (grid[a][b] == grid[c][d] + 32 && grid[a][b] != '.' && grid[c][d] != '.') {
    if ((a == c && b == d - 1) || (a == c - 1 && b == d))
      res = 1;
    else {
      res = max(res, rec(a + 1, b, c - 1, d) + 1);
      res = max(res, rec(a, b + 1, c, d - 1) + 1);
      res = max(res, rec(a + 1, b, c, d - 1) + 1);
      res = max(res, rec(a, b + 1, c - 1, d) + 1);
    }
  }
  res = max(res, rec(a + 1, b, c, d));
  res = max(res, rec(a, b + 1, c, d));
  res = max(res, rec(a, b, c - 1, d));
  res = max(res, rec(a, b, c, d - 1));

  FOR(i, 0, alph.size()) {
    int my = alph[i].f, mx = alph[i].s;
    if (my == a && mx == b)
      continue;
    if (my == c && mx == d)
      continue;
    if (my < a || c < my || mx < b || d < mx)
      continue;
    res = max(res, rec(a, b, my, mx) + rec(my, mx, c, d));
  }
  mem[a][b][c][d] = res;
  return res;
}

int solve() {
  FOR(a, 0, h) FOR(b, 0, w) FOR(c, 0, h) FOR(d, 0, w) mem[a][b][c][d] = -inf;
  alph.clear();
  FOR(i, 0, h)
  FOR(j, 0, w)
  if (grid[i][j] != '.' && grid[i][j] != '#')
    alph.pb(mp(i, j));
  int res = rec(0, 0, h - 1, w - 1);
  if (res < 0)
    return -1;
  return res;
}

int main() {
  while (cin >> h >> w && h) {
    FOR(i, 0, h) cin >> grid[i];
    cout << solve() << endl;
  }
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
#define MAX 51
#define inf 1 << 29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-15)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0 + sqrt(5.0)) / 2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(), (a).end()
#define pd(a) printf("%.10f\\n", (double)(a))
#define pld(a) printf("%.10Lf\\n", (ld)(a))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define RFOR(i, a, b) for (int i = (a)-1; (b) <= i; i--)
#define Unique(v) v.erase(unique(all(v)), v.end())
#define equals(a, b) (fabs((a) - (b)) < eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, int> pdi;
typedef pair<double, double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[2] = {1, 0};
const int dy[2] = {0, 1};

int h, w;
string grid[MAX];
int mem[MAX][MAX][MAX][MAX];
bool used[MAX][MAX];

int rec(int a, int b, int c, int d) {
  if (mem[a][b][c][d] != -1)
    return mem[a][b][c][d];
  int res = 0;
  if (grid[a][b] == '#')
    return -1;
  FOR(i, a, c) {
    FOR(j, b, d) {
      if (islower(grid[i][j])) {
        queue<pii> q;
        q.push(mp(i, j));
        while (q.size()) {
          pii u = q.front();
          used[u.f][u.s] = true;
          q.pop();
          if (grid[i][j] == grid[u.f][u.s] + 32) {
            int tmp = rec(u.f, u.s, c, d) + 1;
            res = max(res, rec(i + 1, j, u.f + 1, u.s) + tmp);
            res = max(res, rec(i + 1, j, u.f, u.s + 1) + tmp);
            res = max(res, rec(i, j + 1, u.f + 1, u.s) + tmp);
            res = max(res, rec(i, j + 1, u.f, u.s + 1) + tmp);
          }
          FOR(k, 0, 2) {
            int ny = u.f + dy[k];
            int nx = u.s + dx[k];
            if (c == ny || d == nx)
              continue;
            if (grid[ny][nx] == '#')
              continue;
            q.push(mp(ny, nx));
          }
        }
      }
    }
  }
  if (!used[c - 1][d - 1])
    res = -1;
  mem[a][b][c][d] = res;
  return res;
}

int main() {
  while (cin >> h >> w && h) {
    FOR(i, 0, h) cin >> grid[i];
    memset(mem, -1, sizeof(mem));
    memset(used, false, sizeof(used));
    cout << rec(0, 0, h, w) << endl;
  }
  return 0;
}