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

#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>

using namespace std;
typedef pair<short, short> pii;

short dp[2001][2001];
pii to[2001][2001];

string s;
string s2;
int n;

// sツづ2ツづ可づつつ「ツづ、ツ催妥・ツ閉板閉ェツ暗ェツ致ツ閉カツ篠堋療アツ陳キツづーツ仰づ淞づゥ
// ツつスツつセツつオツ、s_posツづ2_posツづーcrossツつウツつケツづづ債つ「ツつッツづ按つ「
int dfs(int a, int b) {
  int b_rev = n - 1 - b;
  if (b_rev < a) {
    to[a][b].first = -1;
    return 0;
  } else if (b_rev == a) {
    to[a][b].first = -2;
    return 1;
  }
  if (dp[a][b] != -1)
    return dp[a][b];
  int res = 0;
  if (s[a] == s2[b]) {
    int tmp = res;
    res = max(res, dfs(a + 1, b + 1) + 2);
    if (tmp != res) {
      to[a][b] = pii(a + 1, b + 1);
    }
  }
  int tmp = res;
  res = max(res, dfs(a + 1, b));
  if (tmp != res) {
    to[a][b] = pii(a + 1, b);
  }
  tmp = res;
  res = max(res, dfs(a, b + 1));
  if (tmp != res) {
    to[a][b] = pii(a, b + 1);
  }
  return dp[a][b] = res;
}

int main() {

  while (cin >> s) {
    n = s.size();
    memset(dp, -1, sizeof(dp));
    s2 = s;
    reverse(s2.begin(), s2.end());
    int res = dfs(0, 0);
    pii cur = pii(0, 0);
    string ret;
    while (1) {
      pii nxt = to[cur.first][cur.second];
      if (nxt.first == -1) {
        string tmp = ret;
        reverse(tmp.begin(), tmp.end());
        ret = ret + tmp;
        break;
      }
      if (nxt.first == -2) {
        string tmp = ret;
        reverse(tmp.begin(), tmp.end());
        ret = ret + s[cur.first] + tmp;
        break;
      }
      // diffツつェ1
      if (nxt.first - cur.first == 1 && nxt.second - cur.second == 1)
        ret += s[cur.first];
      cur = nxt;
    }
    cout << ret << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>

using namespace std;
typedef pair<int, int> pii;

int dp[2001][2001];
pii to[2001][2001];

string s;
string s2;
int n;

// sツづ2ツづ可づつつ「ツづ、ツ催妥・ツ閉板閉ェツ暗ェツ致ツ閉カツ篠堋療アツ陳キツづーツ仰づ淞づゥ
// ツつスツつセツつオツ、s_posツづ2_posツづーcrossツつウツつケツづづ債つ「ツつッツづ按つ「
int dfs(int a, int b) {
  int b_rev = n - 1 - b;
  if (b_rev < a) {
    to[a][b].first = -1;
    to[a][b].second = -1;
    return 0;
  } else if (b_rev == a) {
    if (s[a] == s2[b]) {
      to[a][b].first = -2;
      return 1;
    } else {
      to[a][b].first = -1;
      return 0;
    }
  }
  if (dp[a][b] != -1)
    return dp[a][b];
  int res = 0;
  if (s[a] == s2[b]) {
    int tmp = res;
    res = max(res, dfs(a + 1, b + 1) + 1);
    if (tmp != res) {
      to[a][b] = pii(a + 1, b + 1);
    }
  }
  int tmp = res;
  res = max(res, dfs(a + 1, b));
  if (tmp != res) {
    to[a][b] = pii(a + 1, b);
  }
  tmp = res;
  res = max(res, dfs(a, b + 1));
  if (tmp != res) {
    to[a][b] = pii(a, b + 1);
  }
  return dp[a][b] = res;
}

int main() {

  while (cin >> s) {
    n = s.size();
    memset(dp, -1, sizeof(dp));
    s2 = s;
    reverse(s2.begin(), s2.end());
    int res = dfs(0, 0);
    // cout<<res<<endl;
    pii cur;
    string ret;
    while (1) {
      if (cur.first == -1)
        break;
      pii nxt = to[cur.first][cur.second];
      if (nxt.first == -2) {
        string tmp = ret;
        reverse(tmp.begin(), tmp.end());
        ret = ret + s[cur.first] + tmp;
        break;
      }
      // diffツつェ1
      if (nxt.first - cur.first == 1 && nxt.second - cur.second == 1)
        ret += s[cur.first];
      cur = nxt;
    }
    cout << ret << endl;
  }

  return 0;
}