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

#include <algorithm>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define srep(i, n, m) for (int i = (int)n; i <= (int)m; i++)
int n, m;
int dp[52][52][52][52];
bool ok[52][52][52][52];
int inf = 1000000;
vector<string> s;
int saiki(int a, int b, int c, int d) {
  if (a < 0 || a >= n || c < 0 || c >= n || b < 0 || b >= m || d < 0 || d >= m)
    return -inf;
  if (s[a][b] == '#' || s[c][d] == '#')
    return -inf;
  if (a == c && b == d)
    return 0;
  if (ok[a][b][c][d])
    return dp[a][b][c][d];
  ok[a][b][c][d] = 1;
  if (a > c || b > d) {
    return dp[a][b][c][d] = -inf;
  }
  if (s[a][b] >= 'a' && s[a][b] <= 'z' && s[c][d] == s[a][b] + ('A' - 'a')) {
    if (c == a + 1 && b == d)
      return dp[a][b][c][d] = 1;
    if (c == a && d == b + 1)
      return dp[a][b][c][d] = 1;
    int tmp = -inf;
    tmp = max(tmp, saiki(a + 1, b, c - 1, d) + 1);
    tmp = max(tmp, saiki(a + 1, b, c, d - 1) + 1);
    tmp = max(tmp, saiki(a, b + 1, c - 1, d) + 1);
    tmp = max(tmp, saiki(a, b + 1, c, d - 1) + 1);
    if (s[a][b] != '.' && s[c][d] != '.') {
      srep(i, a, c) {
        srep(j, b, d) {
          if (i == c && j == d)
            continue;
          tmp = max(tmp, saiki(a, b, i, j) + saiki(i + 1, j, c, d));
          tmp = max(tmp, saiki(a, b, i, j) + saiki(i, j + 1, c, d));
        }
      }
    }
    if (tmp < 0)
      tmp = -inf;
    return dp[a][b][c][d] = tmp;
  } else {
    if (c == a + 1 && b == d)
      return dp[a][b][c][d] = 0;
    if (c == a && d == b + 1)
      return dp[a][b][c][d] = 0;
    int tmp = -inf;
    tmp = max(tmp, saiki(a + 1, b, c, d));
    tmp = max(tmp, saiki(a, b, c - 1, d));
    tmp = max(tmp, saiki(a, b + 1, c, d));
    tmp = max(tmp, saiki(a, b, c, d - 1));
    if (s[a][b] != '.' && s[c][d] != '.') {
      srep(i, a, c) {
        srep(j, b, d) {
          if (i == c && j == d)
            continue;
          tmp = max(tmp, saiki(a, b, i, j) + saiki(i + 1, j, c, d));
          tmp = max(tmp, saiki(a, b, i, j) + saiki(i, j + 1, c, d));
        }
      }
    }
    if (tmp < 0)
      tmp = -inf;
    return dp[a][b][c][d] = tmp;
  }
}

int main() {
  while (cin >> n >> m && n != 0) {
    s.resize(n);
    rep(i, n) cin >> s[i];
    rep(i, 52) {
      rep(j, 52) {
        rep(k, 52) {
          rep(l, 52) {
            dp[i][j][k][l] = 0;
            ok[i][j][k][l] = 0;
          }
        }
      }
    }
    int ans = saiki(0, 0, n - 1, m - 1);
    if (ans < 0) {
      cout << -1 << endl;
    } else {
      cout << ans << endl;
    }
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)n; i++)
#define srep(i, n, m) for (int i = (int)n; i <= (int)m; i++)
int n, m;
int dp[52][52][52][52];
bool ok[52][52][52][52];
int inf = 1000000;
vector<string> s;
int saiki(int a, int b, int c, int d) {
  if (a < 0 || a >= n || c < 0 || c >= n || b < 0 || b >= m || d < 0 || d >= m)
    return -inf;
  if (s[a][b] == '#' || s[c][d] == '#')
    return -inf;
  if (a == c && b == d)
    return 0;
  if (ok[a][b][c][d])
    return dp[a][b][c][d];
  ok[a][b][c][d] = 1;
  if (a > c || b > d) {
    return dp[a][b][c][d] = -inf;
  }
  if (s[a][b] >= 'a' && s[a][b] <= 'z' && s[c][d] == s[a][b] + ('A' - 'a')) {
    if (c == a + 1 && b == d)
      return dp[a][b][c][d] = 1;
    if (c == a && d == b + 1)
      return dp[a][b][c][d] = 1;
    int tmp = -inf;
    tmp = max(tmp, saiki(a + 1, b, c - 1, d) + 1);
    tmp = max(tmp, saiki(a + 1, b, c, d - 1) + 1);
    tmp = max(tmp, saiki(a, b + 1, c - 1, d) + 1);
    tmp = max(tmp, saiki(a, b + 1, c, d - 1) + 1);
    srep(i, a, c) {
      srep(j, b, d) {
        if (i == c && j == d)
          continue;
        tmp = max(tmp, saiki(a, b, i, j) + saiki(i + 1, j, c, d));
        tmp = max(tmp, saiki(a, b, i, j) + saiki(i, j + 1, c, d));
      }
    }
    if (tmp < 0)
      tmp = -inf;
    return dp[a][b][c][d] = tmp;
  } else {
    if (c == a + 1 && b == d)
      return dp[a][b][c][d] = 0;
    if (c == a && d == b + 1)
      return dp[a][b][c][d] = 0;
    int tmp = -inf;
    tmp = max(tmp, saiki(a + 1, b, c, d));
    tmp = max(tmp, saiki(a, b, c - 1, d));
    tmp = max(tmp, saiki(a, b + 1, c, d));
    tmp = max(tmp, saiki(a, b, c, d - 1));
    srep(i, a, c) {
      srep(j, b, d) {
        if (i == c && j == d)
          continue;
        tmp = max(tmp, saiki(a, b, i, j) + saiki(i + 1, j, c, d));
        tmp = max(tmp, saiki(a, b, i, j) + saiki(i, j + 1, c, d));
      }
    }
    if (tmp < 0)
      tmp = -inf;
    return dp[a][b][c][d] = tmp;
  }
}

int main() {
  while (cin >> n >> m && n != 0) {
    s.resize(n);
    rep(i, n) cin >> s[i];
    rep(i, 52) {
      rep(j, 52) {
        rep(k, 52) {
          rep(l, 52) {
            dp[i][j][k][l] = 0;
            ok[i][j][k][l] = 0;
          }
        }
      }
    }
    int ans = saiki(0, 0, n - 1, m - 1);
    if (ans < 0) {
      cout << -1 << endl;
    } else {
      cout << ans << endl;
    }
  }
  return 0;
}