Problem p02978 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>

using namespace std;

using int64 = long long;

template <typename T>
vector<vector<T>> Make2DVector(int d1, int d2, T default_value) {
  return vector<vector<T>>(d1, vector<T>(d2, default_value));
}

struct PairHash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2> &p) const {
    auto h1 = std::hash<T1>{}(p.first);
    auto h2 = std::hash<T2>{}(p.second);

    // Mainly for demonstration purposes, i.e. works but is overly simple
    // In the real world, use sth. like boost.hash_combine
    return h1 ^ h2;
  }
};

template <class T> inline bool UpdateMin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

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

  int n;
  cin >> n;
  vector<int64> xs(n);
  for (int i = 0; i < n; i++)
    cin >> xs[i];

  // auto hash_fn = [](pair<int64, int64> p) {
  //   return hash<int64>()(p.first) * 1000000007 + hash<int64>()(p.second);
  // };
  auto dp = Make2DVector(n, n, vector<pair<int64, int64>>());
  function<void(int, int)> solve = [&](int l, int r) {
    // cout << "l: " << l << " r: " << r << endl;
    if (!dp[l][r].empty())
      return;
    if (r - l == 1) {
      dp[l][r].push_back(make_pair(0, 0));
      return;
    }

    for (int m = l + 1; m <= r - 1; m++) {
      solve(l, m);
      solve(m, r);
      for (const auto &pair1 : dp[l][m]) {
        for (const auto &pair2 : dp[m][r]) {
          int64 next_l = pair1.first + xs[m] + pair1.second + pair2.first;
          int64 next_r = xs[m] + pair1.second + pair2.first + pair2.second;
          dp[l][r].push_back(make_pair(next_l, next_r));
        }
      }
    }
  };
  solve(0, n - 1);
  int64 ans = INT64_MAX;
  for (const auto &pair : dp[0][n - 1]) {
    // cout << pair.first << " " << pair.second << endl;
    UpdateMin(ans, xs[0] + pair.first + xs[n - 1] + pair.second);
  }
  // cout << "size: " << dp[0][n - 1].size() << endl;
  cout << ans << endl;
}


Fixed submission:
#include <bits/stdc++.h>

using namespace std;

using int64 = long long;

template <typename T>
vector<vector<T>> Make2DVector(int d1, int d2, T default_value) {
  return vector<vector<T>>(d1, vector<T>(d2, default_value));
}

struct PairHash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2> &p) const {
    auto h1 = std::hash<T1>{}(p.first);
    auto h2 = std::hash<T2>{}(p.second);

    // Mainly for demonstration purposes, i.e. works but is overly simple
    // In the real world, use sth. like boost.hash_combine
    return h1 ^ h2;
  }
};

template <class T> inline bool UpdateMin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

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

  int n;
  cin >> n;
  vector<int64> xs(n);
  for (int i = 0; i < n; i++)
    cin >> xs[i];

  // auto hash_fn = [](pair<int64, int64> p) {
  //   return hash<int64>()(p.first) * 1000000007 + hash<int64>()(p.second);
  // };
  auto dp = Make2DVector(n, n, vector<pair<int64, int64>>());
  function<void(int, int)> solve = [&](int l, int r) {
    // cout << "l: " << l << " r: " << r << endl;
    if (!dp[l][r].empty())
      return;
    if (r - l == 1) {
      dp[l][r].push_back(make_pair(0, 0));
      return;
    }

    for (int m = l + 1; m <= r - 1; m++) {
      solve(l, m);
      solve(m, r);
      for (const auto &pair1 : dp[l][m]) {
        for (const auto &pair2 : dp[m][r]) {
          int64 next_l = pair1.first + xs[m] + pair1.second + pair2.first;
          int64 next_r = xs[m] + pair1.second + pair2.first + pair2.second;
          dp[l][r].push_back(make_pair(next_l, next_r));
        }
      }
      vector<pair<int64, int64>> &v = dp[l][r];
      sort(v.begin(), v.end());
      vector<pair<int64, int64>> new_v;
      int64 min_second = INT64_MAX;
      for (const auto &p : v) {
        if (UpdateMin(min_second, p.second)) {
          new_v.push_back(p);
        }
      }
      dp[l][r] = new_v;
    }
  };
  solve(0, n - 1);
  int64 ans = INT64_MAX;
  for (const auto &pair : dp[0][n - 1]) {
    // cout << pair.first << " " << pair.second << endl;
    UpdateMin(ans, xs[0] + pair.first + xs[n - 1] + pair.second);
  }
  // cout << "size: " << dp[0][n - 1].size() << endl;
  cout << ans << endl;
}