Problem p04009 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

int H, W, sx, sy;
string S[100];
int dp[100][101][100][101];
int sum[102][102];

int rect(int a, int b, int c, int d, int e, int f, int g, int h) {
  a = max(a, e);
  b = min(b, f);
  c = max(c, g);
  d = min(d, h);
  return sum[b][d] - sum[b][c] - sum[a][d] + sum[a][c];
}

int rec(int top, int bottom, int left, int right) {
  if (top >= bottom || left >= right)
    return 0;
  if (~dp[top][bottom][left][right])
    return dp[top][bottom][left][right];
  int ret = 0;
  int b2 = H - (sy - top), t2 = bottom - sy - 1;
  int r2 = W - (sx - left), l2 = right - sx - 1;
  if (top > 0) {
    int add = rect(top - 1, top, left, right, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top - 1, bottom, left, right) + add);
  }
  if (left > 0) {
    int add = rect(top, bottom, left - 1, left, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom, left - 1, right) + add);
  }
  if (bottom < H) {
    int add = rect(bottom, bottom + 1, left, right, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom + 1, left, right) + add);
  }
  if (right < W) {
    int add = rect(top, bottom, right, right + 1, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom, left, right + 1) + add);
  }
  return dp[top][bottom][left][right] = ret;
}

int main() {
  cin >> H >> W;
  for (int i = 0; i < H; i++) {
    cin >> S[i];
    for (int j = 0; j < W; j++) {
      if (S[i][j] == 'E')
        sy = i, sx = j;
    }
  }
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++)
      sum[i + 1][j + 1] = S[i][j] == 'o';
  }
  for (int i = 0; i <= H; i++) {
    for (int j = 1; j <= W; j++)
      sum[i][j] += sum[i][j - 1];
  }
  for (int i = 1; i <= H; i++) {
    for (int j = 0; j <= W; j++)
      sum[i][j] += sum[i - 1][j];
  }
  memset(dp, -1, sizeof(dp));
  cout << rec(sy, sy + 1, sx, sx + 1) << endl;
}

Fixed submission:
#include <bits/stdc++.h>

using namespace std;

int H, W, sx, sy;
string S[100];
short dp[100][101][100][101];
int sum[102][102];

int rect(int a, int b, int c, int d, int e, int f, int g, int h) {
  a = max(a, e);
  b = min(b, f);
  c = max(c, g);
  d = min(d, h);
  return sum[b][d] - sum[b][c] - sum[a][d] + sum[a][c];
}

int rec(int top, int bottom, int left, int right) {
  if (top >= bottom || left >= right)
    return 0;
  if (~dp[top][bottom][left][right])
    return dp[top][bottom][left][right];
  int ret = 0;
  int b2 = H - (sy - top), t2 = bottom - sy - 1;
  int r2 = W - (sx - left), l2 = right - sx - 1;
  if (top > 0) {
    int add = rect(top - 1, top, left, right, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top - 1, bottom, left, right) + add);
  }
  if (left > 0) {
    int add = rect(top, bottom, left - 1, left, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom, left - 1, right) + add);
  }
  if (bottom < H) {
    int add = rect(bottom, bottom + 1, left, right, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom + 1, left, right) + add);
  }
  if (right < W) {
    int add = rect(top, bottom, right, right + 1, t2, b2, l2, r2);
    if (add >= 0)
      ret = max(ret, rec(top, bottom, left, right + 1) + add);
  }
  return dp[top][bottom][left][right] = ret;
}

int main() {
  cin >> H >> W;
  for (int i = 0; i < H; i++) {
    cin >> S[i];
    for (int j = 0; j < W; j++) {
      if (S[i][j] == 'E')
        sy = i, sx = j;
    }
  }
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++)
      sum[i + 1][j + 1] = S[i][j] == 'o';
  }
  for (int i = 0; i <= H; i++) {
    for (int j = 1; j <= W; j++)
      sum[i][j] += sum[i][j - 1];
  }
  for (int i = 1; i <= H; i++) {
    for (int j = 0; j <= W; j++)
      sum[i][j] += sum[i - 1][j];
  }
  memset(dp, -1, sizeof(dp));
  cout << rec(sy, sy + 1, sx, sx + 1) << endl;
}