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

#include <bits/stdc++.h>

using namespace std;

namespace {

typedef double real;
typedef long long ll;

template <class T> ostream &operator<<(ostream &os, const vector<T> &vs) {
  if (vs.empty())
    return os << "[]";
  os << "[" << vs[0];
  for (int i = 1; i < vs.size(); i++)
    os << " " << vs[i];
  return os << "]";
}
template <class T> istream &operator>>(istream &is, vector<T> &vs) {
  for (auto it = vs.begin(); it != vs.end(); it++)
    is >> *it;
  return is;
}

const int INF = INT_MAX / 4;

const int MAX_H = 50;
const int MAX_W = 50;

int H, W;
vector<string> F;
bool input() {
  cin >> H >> W;
  if (H == 0 && W == 0)
    return false;
  F.clear();
  F.resize(H);
  cin >> F;
  return true;
}

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

int G[MAX_H][MAX_W][MAX_H][MAX_W];
bool R[MAX_H][MAX_W][MAX_H][MAX_W];

void dfs(int sy, int sx, int y, int x) {
  R[sy][sx][y][x] = true;
  for (int i = 0; i < 2; i++) {
    int ny = y + dy[i];
    int nx = x + dx[i];
    if (ny < 0 || ny >= H)
      continue;
    if (nx < 0 || nx >= W)
      continue;
    if (F[ny][nx] == '#')
      continue;
    if (R[sy][sx][ny][nx])
      continue;
    dfs(sy, sx, ny, nx);
  }
}

int f(int sy, int sx, int ty, int tx) {
  if (sy < 0 || sy >= H || sx < 0 || sx >= W)
    return -INF;
  if (ty < 0 || ty >= H || tx < 0 || tx >= W)
    return -INF;
  if (not R[sy][sx][ty][tx])
    return -INF;
  int &cache = G[sy][sx][ty][tx];
  if (cache >= 0)
    return cache;

  if (abs(sy - ty) + abs(sx - tx) == 1)
    return islower(F[sy][sx]) && toupper(F[sy][sx]) == F[ty][tx];

  int r = 0;
  r = max(r, f(sy, sx + 1, ty, tx));
  r = max(r, f(sy + 1, sx, ty, tx));

  if (not islower(F[sy][sx])) {
    return cache = r;
  }

  for (int y = sy; y <= ty; y++) {
    for (int x = sx; x <= tx; x++) {
      if (y == ty && x == tx)
        continue;
      r = max(r,
              f(sy, sx, y, x) + max(f(y + 1, x, ty, tx), f(y, x + 1, ty, tx)));
    }
  }

  int d = toupper(F[sy][sx]) == F[ty][tx];
  r = max(r, f(sy + 1, sx, ty - 1, tx) + d);
  r = max(r, f(sy + 1, sx, ty, tx - 1) + d);
  r = max(r, f(sy, sx + 1, ty - 1, tx) + d);
  r = max(r, f(sy, sx + 1, ty, tx - 1) + d);
  return cache = r;
}

void solve() {
  memset(G, -1, sizeof(G));
  memset(R, false, sizeof(R));

  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (F[i][j] != '#')
        dfs(i, j, i, j);

  if (not R[0][0][H - 1][W - 1]) {
    cout << -1 << endl;
    return;
  }

  cout << f(0, 0, H - 1, W - 1) << endl;
}
} // namespace

int main() {
  while (input())
    solve();
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

namespace {

typedef double real;
typedef long long ll;

template <class T> ostream &operator<<(ostream &os, const vector<T> &vs) {
  if (vs.empty())
    return os << "[]";
  os << "[" << vs[0];
  for (int i = 1; i < vs.size(); i++)
    os << " " << vs[i];
  return os << "]";
}
template <class T> istream &operator>>(istream &is, vector<T> &vs) {
  for (auto it = vs.begin(); it != vs.end(); it++)
    is >> *it;
  return is;
}

const int INF = INT_MAX / 4;

const int MAX_H = 50;
const int MAX_W = 50;

int H, W;
vector<string> F;
bool input() {
  cin >> H >> W;
  if (H == 0 && W == 0)
    return false;
  F.clear();
  F.resize(H);
  cin >> F;
  return true;
}

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

int G[MAX_H][MAX_W][MAX_H][MAX_W];
bool R[MAX_H][MAX_W][MAX_H][MAX_W];

void dfs(int sy, int sx, int y, int x) {
  R[sy][sx][y][x] = true;
  for (int i = 0; i < 2; i++) {
    int ny = y + dy[i];
    int nx = x + dx[i];
    if (ny < 0 || ny >= H)
      continue;
    if (nx < 0 || nx >= W)
      continue;
    if (F[ny][nx] == '#')
      continue;
    dfs(sy, sx, ny, nx);
  }
}

int f(int sy, int sx, int ty, int tx) {
  if (sy < 0 || sy >= H || sx < 0 || sx >= W)
    return 0;
  if (ty < 0 || ty >= H || tx < 0 || tx >= W)
    return 0;
  if (not R[sy][sx][ty][tx])
    return 0;
  int &cache = G[sy][sx][ty][tx];
  if (cache >= 0)
    return cache;

  if (not islower(F[sy][sx])) {
    return cache = max(f(sy + 1, sx, ty, tx), f(sy, sx + 1, ty, tx));
  }

  int r = 0;
  for (int y = sy; y <= ty; y++) {
    for (int x = sx; x <= tx; x++) {
      if (y == ty && x == tx)
        continue;
      r = max(r,
              f(sy, sx, y, x) + max(f(y + 1, x, ty, tx), f(y, x + 1, ty, tx)));
    }
  }

  int d = toupper(F[sy][sx]) == F[ty][tx];
  r = max(r, f(sy + 1, sx, ty - 1, tx) + d);
  r = max(r, f(sy + 1, sx, ty, tx - 1) + d);
  r = max(r, f(sy, sx + 1, ty - 1, tx) + d);
  r = max(r, f(sy, sx + 1, ty, tx - 1) + d);
  return cache = r;
}

void solve() {
  memset(G, -1, sizeof(G));
  memset(R, false, sizeof(R));

  for (int i = 0; i < H; i++)
    for (int j = 0; j < W; j++)
      if (F[i][j] != '#')
        dfs(i, j, i, j);

  if (not R[0][0][H - 1][W - 1]) {
    cout << -1 << endl;
    return;
  }

  cout << f(0, 0, H - 1, W - 1) << endl;
}
} // namespace

int main() {
  while (input())
    solve();
  return 0;
}