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

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>
#include <utility>
using namespace std;
typedef pair<int, int> pii;
inline void chmax(int &a, const int &b) { a = max(a, b); }
inline void chmin(int &a, const int &b) { a = min(a, b); }
const int INF = 1 << 28;
string s;
int N;
pii dp[210][210], INIT;

pii solve(int l, int r) {
  pii &res = dp[l][r];
  if (dp[l][r] != INIT)
    return res;
  // 数字
  if (r - l == 1) {
    int val = s[l] - '0';
    return res = make_pair(val, val);
  }
  // 括弧をとっぱらって再帰的に
  // このとき、括弧含め幅が 3 以下 (つまり実質 2 以下) だと
  // 数式になりえないので飛ばす
  if (s[l] == '(' && r - l > 3) {
    pii tmp = solve(l + 1, r);
    res.first = max(res.first, tmp.first);
    res.second = min(res.second, tmp.second);
  }
  if (s[r - 1] == ')' && r - l > 3) {
    pii tmp = solve(l, r - 1);
    res.first = max(res.first, tmp.first);
    res.second = min(res.second, tmp.second);
  }
  for (int k = l; k < r; k++) {
    if (s[k] != '+' && s[k] != '-')
      continue;
    pii v1 = solve(l, k), v2 = solve(k + 1, r);
    if (s[k] == '+') {
      res.first = max(res.first, v1.first + v2.first);
      res.second = min(res.second, v1.second + v2.second);
    } else {
      res.first = max(res.first, v1.first - v2.second);
      res.second = min(res.second, v1.second - v2.first);
    }
  }
  return res;
}

int main() {
  cin >> s;
  N = s.length();
  INIT = make_pair(-INF, INF);
  for (int i = 0; i < N; i++) {
    fill(dp[i], dp[i] + N + 1, INIT);
  }

  cout << solve(0, N).first << endl;
  /*
  for(int i=0; i<N; i++) {
      for(int j=i+1; j<=N; j++) {
          if(dp_max[i][j] == -INF) continue;
          printf("%s\\n", s.c_str());
          for(int k=0; k<N; k++) {
              if(i <= k && k < j) printf("=");
              else printf(" ");
          }
          printf(" -> %d\\n", dp_max[i][j]);
      }
  }
  */
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>
#include <utility>
using namespace std;
typedef pair<int, int> pii;
void chmax(int &a, const int &b) { a = max(a, b); }
void chmin(int &a, const int &b) { a = min(a, b); }
const int INF = 1 << 28;
string s;
int N;
pii dp[210][210], INIT;

pii solve(int l, int r) {
  if (dp[l][r] != INIT)
    return dp[l][r];
  // 数字
  if (r - l == 1 && isdigit(s[l])) {
    int val = s[l] - '0';
    return dp[l][r] = make_pair(val, val);
  }
  // 括弧をとっぱらって再帰的に
  // このとき、括弧含め幅が 3 以下 (つまり実質 2 以下) だと
  // 数式になりえないので飛ばす
  if (s[l] == '(' && r - l > 3) {
    pii res = solve(l + 1, r);
    chmax(dp[l][r].first, res.first);
    chmin(dp[l][r].second, res.second);
  } else if (s[r - 1] == ')' && r - l > 3) {
    pii res = solve(l, r - 1);
    chmax(dp[l][r].first, res.first);
    chmin(dp[l][r].second, res.second);
  } else {
    for (int k = l; k < r; k++) {
      if (s[k] != '+' && s[k] != '-')
        continue;
      pii v1 = solve(l, k), v2 = solve(k + 1, r);
      if (v1 == INIT || v2 == INIT)
        continue;
      if (s[k] == '+') {
        chmax(dp[l][r].first, v1.first + v2.first);
        chmin(dp[l][r].second, v1.second + v2.second);
      } else {
        chmax(dp[l][r].first, v1.first - v2.second);
        chmin(dp[l][r].second, v1.second - v2.first);
      }
    }
  }
  return dp[l][r];
}

int main() {
  cin >> s;
  N = s.length();
  INIT = make_pair(-INF, INF);
  for (int i = 0; i < N; i++) {
    fill(dp[i], dp[i] + N + 1, INIT);
  }

  cout << solve(0, N).first << endl;
  /*
  for(int i=0; i<N; i++) {
      for(int j=i+1; j<=N; j++) {
          if(dp_max[i][j] == -INF) continue;
          printf("%s\\n", s.c_str());
          for(int k=0; k<N; k++) {
              if(i <= k && k < j) printf("=");
              else printf(" ");
          }
          printf(" -> %d\\n", dp_max[i][j]);
      }
  }
  */
  return 0;
}