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

#include <bits/stdc++.h>

using namespace std;

int N;
pair<int, int> A[5000];
long long dp1[5000][2505];
long long dp2[5000][2505];

long long prefix(int pos, int typeA) {
  if (pos == -1)
    return 0;
  long long &ret = dp1[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA + 1;
  int len = A[pos].first + A[pos].second;
  if (typeA > 0)
    ret = min(ret, 1LL * len * (typeA - 1) + A[pos].second +
                       prefix(pos - 1, typeA - 1));
  if (typeB > 0)
    ret = min(ret,
              1LL * len * (typeB - 1) + A[pos].first + prefix(pos - 1, typeA));
  return ret;
}

long long suffix1(int pos, int typeA) {
  if (pos == N) {
    if (typeA == (N - 1) / 2)
      return 0;
    return 0x3f3f3f3f3f3f3f3fLL;
  }
  if (typeA > (N - 1) / 2)
    return 0x3f3f3f3f3f3f3f3fLL;
  long long &ret = dp2[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA - 1;
  int len = A[pos].first + A[pos].second;
  ret =
      min(ret, 1LL * len * typeA + A[pos].second + suffix1(pos + 1, typeA + 1));
  ret = min(ret, 1LL * len * typeB + A[pos].first + suffix1(pos + 1, typeA));
  return ret;
}

long long suffix2(int pos, int typeA) {
  if (pos == N) {
    if (typeA == (N - 1) / 2 + 1)
      return 0;
    return 0x3f3f3f3f3f3f3f3fLL;
  }
  if (typeA > (N - 1) / 2 + 1)
    return 0x3f3f3f3f3f3f3f3fLL;
  long long &ret = dp2[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA - 1;
  int len = A[pos].first + A[pos].second;
  ret =
      min(ret, 1LL * len * typeA + A[pos].second + suffix2(pos + 1, typeA + 1));
  ret = min(ret, 1LL * len * typeB + A[pos].first + suffix2(pos + 1, typeA));
  return ret;
}

int main() {
  scanf("%d", &N);
  for (int i = 0; i < N; i++)
    scanf("%d%d", &A[i].first, &A[i].second);
  sort(A, A + N, [](const pair<int, int> &a, const pair<int, int> &b) {
    return a.first + a.second > b.first + b.second;
  });
  memset(dp1, -1, sizeof dp1);
  memset(dp2, -1, sizeof dp2);
  long long ans = 0x3f3f3f3f3f3f3f3fLL;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j <= min((N - 1) / 2, i); j++)
      ans = min(ans, 1LL * A[i].first * ((N - 1) / 2) +
                         1LL * A[i].second * (N - 1 - (N - 1) / 2) +
                         prefix(i - 1, j) + suffix1(i + 1, j));
  }
  memset(dp2, -1, sizeof dp2);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j <= min((N - 1) / 2 + 1, i); j++)
      ans = min(ans, 1LL * A[i].first * ((N - 1) / 2 + 1) +
                         1LL * A[i].second * (N - 1 - ((N - 1) / 2 + 1)) +
                         prefix(i - 1, j) + suffix2(i + 1, j));
  }
  printf("%lld\\n", ans);
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

int N;
pair<int, int> A[5000];
long long *dp1[5000];
long long dp2[5000][5001];

long long prefix(int pos, int typeA) {
  if (pos == -1)
    return 0;
  long long &ret = dp1[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA + 1;
  int len = A[pos].first + A[pos].second;
  if (typeA > 0)
    ret = min(ret, 1LL * len * (typeA - 1) + A[pos].second +
                       prefix(pos - 1, typeA - 1));
  if (typeB > 0)
    ret = min(ret,
              1LL * len * (typeB - 1) + A[pos].first + prefix(pos - 1, typeA));
  return ret;
}

long long suffix1(int pos, int typeA) {
  if (pos == N) {
    if (typeA == (N - 1) / 2)
      return 0;
    return 0x3f3f3f3f3f3f3f3fLL;
  }
  long long &ret = dp2[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA - 1;
  int len = A[pos].first + A[pos].second;
  ret =
      min(ret, 1LL * len * typeA + A[pos].second + suffix1(pos + 1, typeA + 1));
  ret = min(ret, 1LL * len * typeB + A[pos].first + suffix1(pos + 1, typeA));
  return ret;
}

long long suffix2(int pos, int typeA) {
  if (pos == N) {
    if (typeA == (N - 1) / 2 + 1)
      return 0;
    return 0x3f3f3f3f3f3f3f3fLL;
  }
  long long &ret = dp2[pos][typeA];
  if (ret != -1)
    return ret;
  ret = 0x3f3f3f3f3f3f3f3fLL;
  int typeB = pos - typeA - 1;
  int len = A[pos].first + A[pos].second;
  ret =
      min(ret, 1LL * len * typeA + A[pos].second + suffix2(pos + 1, typeA + 1));
  ret = min(ret, 1LL * len * typeB + A[pos].first + suffix2(pos + 1, typeA));
  return ret;
}

int main() {
  scanf("%d", &N);
  for (int i = 0; i < N; i++)
    scanf("%d%d", &A[i].first, &A[i].second);
  sort(A, A + N, [](const pair<int, int> &a, const pair<int, int> &b) {
    return a.first + a.second > b.first + b.second;
  });
  memset(dp2, -1, sizeof dp2);
  long long ans = 0x3f3f3f3f3f3f3f3fLL;
  for (int i = 1; i < N; i++) {
    dp1[i - 1] = new long long[min((N - 1) / 2 + 1, i) + 1];
    for (int j = 0; j <= min((N - 1) / 2 + 1, i); j++)
      dp1[i - 1][j] = -1;
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j <= min((N - 1) / 2, i); j++)
      ans = min(ans, 1LL * A[i].first * ((N - 1) / 2) +
                         1LL * A[i].second * (N - 1 - (N - 1) / 2) +
                         prefix(i - 1, j) + suffix1(i + 1, j));
  }
  memset(dp2, -1, sizeof dp2);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j <= min((N - 1) / 2 + 1, i); j++)
      ans = min(ans, 1LL * A[i].first * ((N - 1) / 2 + 1) +
                         1LL * A[i].second * (N - 1 - ((N - 1) / 2 + 1)) +
                         prefix(i - 1, j) + suffix2(i + 1, j));
  }
  printf("%lld\\n", ans);
  return 0;
}