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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

#define EPS (1e-10)
#define EQ(a, b) (abs((a) - (b)) < EPS)
#define EQV(a, b) (EQ((a).real(), (b).real()) && EQ((a).imag(), (b).imag()))

typedef complex<double> P;
typedef long long ll;

const double PI = 4 * atan(1.0);
const int MAX_SIZE = 10000;

// àÏ
double dot(P a, P b) { return (a.real() * b.real() + a.imag() * b.imag()); }
// OÏ
double cross(P a, P b) { return (a.real() * b.imag() - a.imag() * b.real()); }
// ½p`ÌÊÏö®
double calcPolygonArea(vector<P> p) {
  double sum = 0;
  for (int i = 0; i < p.size(); i++)
    sum += cross(p[i], p[(i + 1) % (p.size())]);
  return sum / 2;
}

P points[50];
int n, m;
double dp[41][41][41][41];

const double INF = 1000000;

// idxÈ~ÅleftÂIñÅÅÉfirstIdxÌàÌðIð
double calcMaxS(int idx, int left, int prvSelIdx, int firstIdx) {
  if (!EQ(dp[idx][left][prvSelIdx][firstIdx], 0))
    return dp[idx][left][prvSelIdx][firstIdx];
  double maxSum = -INF;
  bool ok = false;
  if (left == 0) {
    maxSum = (cross(points[prvSelIdx], points[firstIdx]));
    ok = true;
  } else if (idx == n) {
    maxSum = INF;
    ok = true;
  } else {
    double res = calcMaxS(idx + 1, left - 1, idx, firstIdx);
    if (!EQ(res, INF)) {
      maxSum = max(maxSum, res + (cross(points[prvSelIdx], points[idx])));
      ok = true;
    }
    double res2 = calcMaxS(idx + 1, left, prvSelIdx, firstIdx);
    if (!EQ(res2, INF)) {
      maxSum = max(maxSum, res2);
      ok = true;
    }
  }
  if (!ok)
    maxSum = INF;
  return dp[idx][left][prvSelIdx][firstIdx] = maxSum;
}

int main() {
  while (cin >> n >> m && !(n == 0 && m == 0)) {
    double maxS = 0;
    memset(dp, 0, sizeof(dp));
    vector<double> tmp;
    for (int i = 0; i < n; i++) {
      double p;
      cin >> p;
      tmp.push_back(p);
    }
    sort(tmp.begin(), tmp.end());
    for (int i = 0; i < n; i++)
      points[i] = P(cos(tmp[i] * 2 * PI), sin(tmp[i] * 2 * PI));
    for (int i = 0; i < n - m + 1; i++) {
      double res = abs(calcMaxS(i + 1, m - 1, i, i));
      if (!EQ(res, INF))
        maxS = max(maxS, res / 2);
    }
    printf("%.6f\\n", maxS);
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

#define EPS (1e-10)
#define EQ(a, b) (abs((a) - (b)) < EPS)
#define EQV(a, b) (EQ((a).real(), (b).real()) && EQ((a).imag(), (b).imag()))

typedef complex<double> P;
typedef long long ll;

const double PI = 4 * atan(1.0);
const int MAX_SIZE = 10000;

// àÏ
double dot(P a, P b) { return (a.real() * b.real() + a.imag() * b.imag()); }
// OÏ
double cross(P a, P b) { return (a.real() * b.imag() - a.imag() * b.real()); }
// _cª¼üabãÉ é©È¢©
int is_point_on_line(P a, P b, P c) { return EQ(cross(b - a, c - a), 0.0); }
// 2¼üÌ¼s»è
int is_orthogonal(P a1, P a2, P b1, P b2) {
  return EQ(dot(a1 - a2, b1 - b2), 0.0);
}
// 2¼üÌ½s»è
int is_parallel(P a1, P a2, P b1, P b2) {
  return EQ(cross(a1 - a2, b1 - b2), 0.0);
}
// _a,bðÊé¼üÆ_cÌÔÌ£
double distance_l_p(P a, P b, P c) {
  return abs(cross(b - a, c - a)) / abs(b - a);
}
// _a,bð[_Æ·éüªÆ_cÆÌ£
double distance_ls_p(P a, P b, P c) {
  if (dot(b - a, c - a) < EPS)
    return abs(c - a);
  if (dot(a - b, c - b) < EPS)
    return abs(c - b);
  return abs(cross(b - a, c - a)) / abs(b - a);
}
// a1,a2ð[_Æ·éüªÆb1,b2ð[_Æ·éüªÌð·»è
int is_intersected_ls(P a1, P a2, P b1, P b2) {
  // üªª½sÈêÍdÈÁÄ¢È¢±ÆÉ·é
  if (abs(cross(a2 - a1, b2 - b1)) < EPS) {
    return 0;
  }
  return (cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS) &&
         (cross(b2 - b1, a1 - b1) * cross(b2 - b1, a2 - b1) < EPS);
}
// a1,a2ð[_Æ·éüªÆb1,b2ð[_Æ·éüªÌð_vZ
P intersection_ls(P a1, P a2, P b1, P b2) {
  P b = b2 - b1;
  double d1 = abs(cross(b, a1 - b1));
  double d2 = abs(cross(b, a2 - b1));
  double t = d1 / (d1 + d2);

  return a1 + (a2 - a1) * t;
}
// a1,a2ðÊé¼üÆb1,b2ðÊé¼üÌð·»è
int is_intersected_l(P a1, P a2, P b1, P b2) {
  return !EQ(cross(a1 - a2, b1 - b2), 0.0);
}
// a1,a2ðÊé¼üÆb1,b2ðÊé¼üÌð_vZ
P intersection_l(P a1, P a2, P b1, P b2) {
  P a = a2 - a1;
  P b = b2 - b1;
  return a1 + a * cross(b, b1 - a1) / cross(b, a);
}
/*
~üÆüªÌð·»è
*/
bool isCircleCrossLine(P a, P b, P c, double r) {
  double d1 = abs(a - c);
  double d2 = abs(b - c);
  // üªªÉÜÜêéÆ«A±±ÌRgAEgðÍ¸¹Îtrue(ð·)ÆÈé
  double d = distance_ls_p(a, b, c);
  return (EQ(d, r) || d < r);
}
// Op`ÌàÉ_ª é©Ç¤©
// OÏÌ³ª·×Ä¯¶ÈçàÉ_ è
bool isInTriangle(P p1, P p2, P p3, P s) {
  P a = p1 - s;
  P b = p2 - s;
  P c = p3 - s;
  return ((cross(a, b) > 0 && cross(b, c) > 0 && cross(c, a) > 0) ||
          (cross(a, b) < 0 && cross(b, c) < 0 && cross(c, a) < 0));
}
// é`ÌÉ_ª¶Ý·é©Ç¤©
bool isInRectangle(P p1, P p2, P p3, P p4, P s) {
  P a = p1 - s;
  P b = p2 - s;
  P c = p3 - s;
  P d = p4 - s;
  return ((cross(a, b) > 0 && cross(b, c) > 0 && cross(c, d) > 0 &&
           cross(d, a) > 0) ||
          (cross(a, b) < 0 && cross(b, c) < 0 && cross(c, d) < 0 &&
           cross(d, a) < 0));
}
// Op`ÌÊÏðÀW©çvZ
double calcAreaOfTriangle(P a, P b, P c) {
  return abs((b.real() - a.real()) * (c.imag() - a.imag()) -
             (c.real() - a.real()) * (b.imag() - a.imag())) /
         2;
}
// ^¦çê½~ÌÍÍàÉ_ª¶Ý·é©Ç¤©
bool isContainingDot(P c, double r, P a) {
  return (((c.real() - a.real()) * (c.real() - a.real()) +
               (c.imag() - a.imag()) * (c.imag() - a.imag()) <
           r * r) ||
          EQ((c.real() - a.real()) * (c.real() - a.real()) +
                 (c.imag() - a.imag()) * (c.imag() - a.imag()),
             r * r));
}
// ½p`ÌÊÏö®
double calcPolygonArea(vector<P> p) {
  double sum = 0;
  for (int i = 0; i < p.size(); i++)
    sum += cross(p[i], p[(i + 1) % (p.size())]);
  return sum / 2;
}
// 2xNgÔÌpx
// a©çbÖ¶üèÅ½x©(0->2*PI)
double diffAngle(P a, P b) {
  double angle = atan2(cross(a, b), dot(a, b));
  if (angle < 0)
    return 2 * PI + angle;
  return angle;
}

P points[50];
int n, m;
double dp[50][50][50][50];

const double INF = 1000000;

// idxÈ~ÅleftÂIñÅÅÉfirstIdxÌàÌðIð
double calcMaxS(int idx, int left, int prvSelIdx, int firstIdx) {
  if (!EQ(dp[idx][left][prvSelIdx][firstIdx], 0))
    return dp[idx][left][prvSelIdx][firstIdx];
  double maxSum = -INF;
  bool ok = false;
  if (left == 0) {
    maxSum = (cross(points[prvSelIdx], points[firstIdx]));
    ok = true;
  } else if (idx == n) {
    maxSum = INF;
    ok = true;
  } else {
    double res = calcMaxS(idx + 1, left - 1, idx, firstIdx);
    if (!EQ(res, INF)) {
      maxSum = max(maxSum, res + (cross(points[prvSelIdx], points[idx])));
      ok = true;
    }
    double res2 = calcMaxS(idx + 1, left, prvSelIdx, firstIdx);
    if (!EQ(res2, INF)) {
      maxSum = max(maxSum, res2);
      ok = true;
    }
  }
  if (!ok)
    maxSum = INF;
  return dp[idx][left][prvSelIdx][firstIdx] = maxSum;
}

int main() {
  while (cin >> n >> m && !(n == 0 && m == 0)) {
    double maxS = 0;
    memset(dp, 0, sizeof(dp));
    vector<double> tmp;
    for (int i = 0; i < n; i++) {
      double p;
      cin >> p;
      tmp.push_back(p);
    }
    sort(tmp.begin(), tmp.end());
    for (int i = 0; i < n; i++)
      points[i] = P(cos(tmp[i] * 2 * PI), sin(tmp[i] * 2 * PI));
    for (int i = 0; i < n - m + 1; i++) {
      double res = abs(calcMaxS(i + 1, m - 1, i, i));
      maxS = max(maxS, res);
    }
    printf("%.6f\\n", maxS / 2);
  }
  return 0;
}