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

#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 100;
const int MAX_MONEY = 500 * MAX_N;
int n;
int p[MAX_N];
pair<char, int> memo[MAX_N][MAX_MONEY];

inline void Change(pair<char, int> &a, pair<char, int> &b) {
  if ((a.first < b.first) || (a.first == b.first && a.second > b.second))
    a = b;
}

pair<char, int> Solve(int idx, int money) {
  if (idx == n)
    return pair<char, int>(0, 0);

  auto &opt = memo[idx][money];
  if (opt.second != -1)
    return opt;

  // idx?????????????????§????????????
  opt = Solve(idx + 1, money);

  // idx?????????????????§??????
  if (0 < (p[idx] % 1000) && (p[idx] % 1000) <= 500) {
    // 1000????????§?????????
    int res = 1000 - (p[idx] % 1000) - 500 + money;
    auto tmp = Solve(idx + 1, res);
    tmp.first += 1;
    tmp.second += p[idx];
    Change(opt, tmp);
  } else if (p[idx] % 1000 == 0) {
    if (500 <= money) {
      int res = money - 500;
      auto tmp = Solve(idx + 1, res);
      tmp.first += 1;
      tmp.second += p[idx];
      Change(opt, tmp);
    }
  } else if (500 <= money + 1000 - (p[idx] % 1000)) {
    // 1000????????¨?°????money??§?????????
    int res = money + 1000 - (p[idx] % 1000) - 500;
    auto tmp = Solve(idx + 1, res);
    tmp.first += 1;
    tmp.second += p[idx];
    Change(opt, tmp);
  } else {
    // 1000??????????????§?????????
    int res = 1000 - (p[idx] % 1000) + money;
    auto tmp = Solve(idx + 1, res);
    tmp.second += p[idx];
    Change(opt, tmp);
  }

  return opt;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  while (cin >> n, n) {
    for (int i = 0; i < n; ++i)
      cin >> p[i];

    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n * 500; ++j)
        memo[i][j] = pair<char, int>(0, -1);

    auto res = Solve(0, 0);
    cout << (int)res.first << ' ' << res.second << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

const int MAX_MONEY = 500;
int n;
vector<int> p;
// int big = 0;
vector<vector<pair<char, int>>> memo;

inline void Change(pair<char, int> &a, pair<char, int> &b) {
  if ((a.first < b.first) || (a.first == b.first && a.second > b.second))
    a = b;
}

pair<char, int> Solve(int idx, int money) {
  // if (big < money) {
  //     big = money;
  //     cout << "money = " << big << endl;
  // }
  if (idx == n)
    return pair<char, int>(0, 0);

  auto &opt = memo[idx][money];
  if (opt.second != -1)
    return opt;

  // idx?????????????????§????????????
  opt = Solve(idx + 1, money);

  // idx?????????????????§??????
  if (0 < (p[idx] % 1000) && (p[idx] % 1000) <= 500) {
    // 1000????????§?????????
    int res = 1000 - (p[idx] % 1000) - 500 + money;
    auto tmp = Solve(idx + 1, res);
    tmp.first += 1;
    tmp.second += p[idx];
    Change(opt, tmp);
  } else if (p[idx] % 1000 == 0) {
    if (500 <= money) {
      int res = money - 500;
      auto tmp = Solve(idx + 1, res);
      tmp.first += 1;
      tmp.second += p[idx];
      Change(opt, tmp);
    }
  } else if (500 <= money + 1000 - (p[idx] % 1000)) {
    // 1000????????¨?°????money??§?????????
    int res = money + 1000 - (p[idx] % 1000) - 500;
    auto tmp = Solve(idx + 1, res);
    tmp.first += 1;
    tmp.second += p[idx];
    Change(opt, tmp);
  } else {
    // 1000??????????????§?????????
    int res = 1000 - (p[idx] % 1000) + money;
    auto tmp = Solve(idx + 1, res);
    tmp.second += p[idx];
    Change(opt, tmp);
  }

  return opt;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  while (cin >> n, n) {
    p.resize(n);
    for (int i = 0; i < n; ++i)
      cin >> p[i];

    memo.clear();
    memo.resize(n, vector<pair<char, int>>(5000 * n, pair<char, int>(0, -1)));

    auto res = Solve(0, 0);
    cout << (int)res.first << ' ' << res.second << endl;
  }

  return 0;
}