Problem p01650 (C++)

Buggy submission (status: Runtime Error):
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &o) {
  out << "(" << o.first << "," << o.second << ")";
  return out;
}
template <class T> ostream &operator<<(ostream &out, const vector<T> V) {
  for (int i = 0; i < V.size(); i++) {
    out << V[i];
    if (i != V.size() - 1)
      out << " ";
  }
  return out;
}
template <class T>
ostream &operator<<(ostream &out, const vector<vector<T>> Mat) {
  for (int i = 0; i < Mat.size(); i++) {
    if (i != 0)
      out << endl;
    out << Mat[i];
  }
  return out;
}
template <class S, class T>
ostream &operator<<(ostream &out, const map<S, T> mp) {
  out << "{ ";
  for (auto it = mp.begin(); it != mp.end(); it++) {
    out << it->first << ":" << it->second;
    if (mp.size() - 1 != distance(mp.begin(), it))
      out << ", ";
  }
  out << " }";
  return out;
}

/*
 <url:>
 問題文============================================================
 =================================================================
 解説=============================================================
 ================================================================
 */

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

#define MAX_WH 55
vector<pii> alpha[30];
int dp[MAX_WH][MAX_WH][MAX_WH][MAX_WH];
bool can[MAX_WH][MAX_WH][MAX_WH][MAX_WH];
ll H, W;

int dfs(ll y1, ll x1, ll y2, ll x2, vector<vector<char>> &maze) {
  int &ret = dp[y1][x1][y2][x2];
  if (ret != -1)
    return ret;
  if (y1 == y2 && x1 == x2)
    return ret = 0;
  if (maze[y1][x1] == '#')
    return ret;
  if (y1 + 1 <= y2 && maze[y1 + 1][x1] != '#') {
    ret = max(ret, dfs(y1 + 1, x1, y2, x2, maze));
  }
  if (x1 + 1 <= x2 && maze[y1][x1 + 1] != '#') {
    ret = max(ret, dfs(y1, x1 + 1, y2, x2, maze));
  }
  char c = maze[y1][x1];
  if (c >= 'a' && c <= 'z') {
    int idx = c - 'a';
    for (auto p : alpha[idx]) {
      ll ny = p.first, nx = p.second;
      if (ny > y2 || nx > x2)
        continue;
      if (abs(ny - y1) + abs(nx - x1) == 1)
        ret = max(ret, dfs(ny, nx, y2, x2, maze) + 1);
      else {
        for (int i = 0; i < 2; i++)
          for (int j = 0; j < 2; j++) {
            int ny1 = y1 + dy[i], nx1 = x1 + dx[i];
            if (ny1 > y2 || nx1 > x2)
              continue;
            int bny = ny - dy[j], bnx = nx - dx[j];
            if (bny < y1 || bnx < x1)
              continue;
            if (!can[ny1][nx1][bny][bnx])
              continue;
            ret = max(ret, 1 + dfs(ny1, nx1, bny, bnx, maze) +
                               dfs(ny, nx, y2, x2, maze));
          }
      }
    }
  }
  return ret;
}

int solve() {
  int res = -1;
  vector<vector<char>> maze(H + 2, vector<char>(W + 2, '#'));
  for (int i = 0; i < 30; i++)
    alpha[i].clear();
  for (int i = 1; i <= H; i++) {
    for (int j = 1; j <= W; j++) {
      char c;
      cin >> c;
      maze[i][j] = c;
      if (c >= 'A' && c <= 'Z')
        alpha[c - 'A'].push_back({i, j});
    }
  }
  memset(can, false, sizeof(can));
  //    fill(***can,***can+MAX_WH*MAX_WH*MAX_WH*MAX_WH,false);

  for (ll i = H; i >= 1; i--) {
    for (ll j = W; j >= 1; j--) {
      if (maze[i][j] == '#')
        continue;
      can[i][j][i][j] = 1;
      if (maze[i + 1][j] != '#') {
        for (ll ii = i + 1; ii <= H; ii++) {
          for (ll jj = j; jj <= W; jj++) {
            can[i][j][ii][jj] |= can[i + 1][j][ii][jj];
          }
        }
      }
      if (maze[i][j + 1] != '#') {
        for (ll ii = i; ii <= H; ii++) {
          for (ll jj = j + 1; jj <= W; jj++) {
            can[i][j][ii][jj] |= can[i][j + 1][ii][jj];
          }
        }
      }
    }
  }
  // cout << maze << endl;
  // fill(***dp,***dp+MAX_WH*MAX_WH*MAX_WH*MAX_WH,-1);
  memset(dp, -1, sizeof(dp));
  res = max(res, dfs(1, 1, H, W, maze));
  return res;
}
int main(void) {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  while (cin >> H >> W, H | W) {
    cout << solve() << endl;
  }
  return 0;
}


Fixed submission:
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int INF = 1e9;
const ll LINF = 1e18;
template <class S, class T>
ostream &operator<<(ostream &out, const pair<S, T> &o) {
  out << "(" << o.first << "," << o.second << ")";
  return out;
}
template <class T> ostream &operator<<(ostream &out, const vector<T> V) {
  for (int i = 0; i < V.size(); i++) {
    out << V[i];
    if (i != V.size() - 1)
      out << " ";
  }
  return out;
}
template <class T>
ostream &operator<<(ostream &out, const vector<vector<T>> Mat) {
  for (int i = 0; i < Mat.size(); i++) {
    if (i != 0)
      out << endl;
    out << Mat[i];
  }
  return out;
}
template <class S, class T>
ostream &operator<<(ostream &out, const map<S, T> mp) {
  out << "{ ";
  for (auto it = mp.begin(); it != mp.end(); it++) {
    out << it->first << ":" << it->second;
    if (mp.size() - 1 != distance(mp.begin(), it))
      out << ", ";
  }
  out << " }";
  return out;
}

/*
 <url:>
 問題文============================================================
 =================================================================
 解説=============================================================
 ================================================================
 */

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

#define MAX_WH 55
vector<pii> alpha[30];
int dp[MAX_WH][MAX_WH][MAX_WH][MAX_WH];
bool can[MAX_WH][MAX_WH][MAX_WH][MAX_WH];
ll H, W;

int dfs(ll y1, ll x1, ll y2, ll x2, vector<vector<char>> &maze) {
  int &ret = dp[y1][x1][y2][x2];
  if (ret != -1)
    return ret;
  if (y1 == y2 && x1 == x2)
    return ret = 0;
  ret = -INF;
  if (maze[y1][x1] == '#')
    return ret;
  if (y1 + 1 <= y2 && maze[y1 + 1][x1] != '#') {
    ret = max(ret, dfs(y1 + 1, x1, y2, x2, maze));
  }
  if (x1 + 1 <= x2 && maze[y1][x1 + 1] != '#') {
    ret = max(ret, dfs(y1, x1 + 1, y2, x2, maze));
  }
  char c = maze[y1][x1];
  if (c >= 'a' && c <= 'z') {
    int idx = c - 'a';
    for (auto p : alpha[idx]) {
      ll ny = p.first, nx = p.second;
      if (ny > y2 || nx > x2)
        continue;
      if (abs(ny - y1) + abs(nx - x1) == 1)
        ret = max(ret, dfs(ny, nx, y2, x2, maze) + 1);
      else {
        for (int i = 0; i < 2; i++)
          for (int j = 0; j < 2; j++) {
            int ny1 = y1 + dy[i], nx1 = x1 + dx[i];
            if (ny1 > y2 || nx1 > x2)
              continue;
            int bny = ny - dy[j], bnx = nx - dx[j];
            if (bny < y1 || bnx < x1)
              continue;
            if (!can[ny1][nx1][bny][bnx])
              continue;
            ret = max(ret, 1 + dfs(ny1, nx1, bny, bnx, maze) +
                               dfs(ny, nx, y2, x2, maze));
          }
      }
    }
  }
  return ret;
}

int solve() {
  int res = -1;
  vector<vector<char>> maze(H + 2, vector<char>(W + 2, '#'));
  for (int i = 0; i < 30; i++)
    alpha[i].clear();
  for (int i = 1; i <= H; i++) {
    for (int j = 1; j <= W; j++) {
      char c;
      cin >> c;
      maze[i][j] = c;
      if (c >= 'A' && c <= 'Z')
        alpha[c - 'A'].push_back({i, j});
    }
  }
  memset(can, false, sizeof(can));
  //    fill(***can,***can+MAX_WH*MAX_WH*MAX_WH*MAX_WH,false);

  for (ll i = H; i >= 1; i--) {
    for (ll j = W; j >= 1; j--) {
      if (maze[i][j] == '#')
        continue;
      can[i][j][i][j] = 1;
      if (maze[i + 1][j] != '#') {
        for (ll ii = i + 1; ii <= H; ii++) {
          for (ll jj = j; jj <= W; jj++) {
            can[i][j][ii][jj] |= can[i + 1][j][ii][jj];
          }
        }
      }
      if (maze[i][j + 1] != '#') {
        for (ll ii = i; ii <= H; ii++) {
          for (ll jj = j + 1; jj <= W; jj++) {
            can[i][j][ii][jj] |= can[i][j + 1][ii][jj];
          }
        }
      }
    }
  }
  // cout << maze << endl;
  // fill(***dp,***dp+MAX_WH*MAX_WH*MAX_WH*MAX_WH,-1);
  memset(dp, -1, sizeof(dp));
  res = max(res, dfs(1, 1, H, W, maze));
  return res;
}
int main(void) {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  while (cin >> H >> W, H | W) {
    cout << solve() << endl;
  }
  return 0;
}