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

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

const double eps = 1e-8;

bool equals(double a, double b) { return abs(a - b) < eps; }

struct P3D {
private:
  double v[3];

public:
  P3D() { v[0] = v[1] = v[2] = 0; }

  P3D(double a, double b, double c) {
    v[0] = a;
    v[1] = b;
    v[2] = c;
  }

  P3D(const double _v[]) {
    for (int i = 0; i < 3; ++i) {
      v[i] = _v[i];
    }
  }

  double &operator[](int x) { return v[x]; }

  const double &operator[](int x) const { return v[x]; }

  P3D operator+(const P3D &p) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] + p[i];
    }
    return res;
  }

  P3D operator-(const P3D &p) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] - p[i];
    }
    return res;
  }

  P3D operator*(const double &d) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] * d;
    }
    return res;
  }

  P3D operator/(const double &d) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] / d;
    }
    return res;
  }

  P3D &operator=(const P3D &p) {
    for (int i = 0; i < 3; ++i) {
      (*this)[i] = p[i];
    }
    return (*this);
  }
};

double dot(const P3D &a, const P3D &b) {
  double res = 0;
  for (int i = 0; i < 3; ++i)
    res += a[i] * b[i];
  return res;
}

double cross(const P3D &a, const P3D &b) {
  double res = 0;
  for (int i = 0; i < 3; ++i) {
    double t = a[i] * b[(i + 1) % 3] - a[(i + 1) % 3] * b[i];
    res += t * t;
  }
  return sqrt(res);
}

double norm(const P3D &a) { return dot(a, a); }

double abs(const P3D &a) { return sqrt(norm(a)); }

double getDistance(const P3D &a, const P3D &b) { return abs(a - b); }

double getDistanceLP(const P3D &s1, const P3D &s2, const P3D &p) {
  return abs(cross(s2 - s1, p - s1) / abs(s2 - s1));
}

double getDistanceSP(const P3D &s1, const P3D &s2, const P3D &p) {
  if (dot(s2 - s1, p - s1) < 0.0)
    return getDistance(s1, p);
  if (dot(s1 - s2, p - s2) < 0.0)
    return getDistance(s2, p);
  return getDistanceLP(s1, s2, p);
}

bool isIn(const P3D &p, const P3D &o, const double &r) {
  double d = abs(p - o);
  return equals(d, r) || d < r;
}

void show(const P3D &p) {
  cout << "(";
  for (int i = 0; i < 3; ++i) {
    if (i)
      cout << ", ";
    cout << p[i];
  }
  cout << ")" << endl;
}

const int MAXN = 2001;
const int MAXM = 16;
int N, M, R;
P3D S[MAXN];
double Sr[MAXN];
P3D T[MAXM];
double Tb[MAXM];
P3D E;
set<int> rballoon[MAXM];
double mem[1 << MAXM];

void makeRballoon() {
  for (int k = 0; k < M; ++k) {
    rballoon[k].clear();
    for (int i = 0; i < N; ++i) {
      double d = getDistanceSP(T[k], E, S[i]);
      if (!equals(d, Sr[i]) && d < Sr[i]) {
        if (isIn(T[k], S[i], Sr[i]) && isIn(E, S[i], Sr[i]))
          continue;
        rballoon[k].insert(i);
      }
    }
  }
}

double test(int b) {
  double res = 0;
  set<int> s;
  for (int i = 0; i < M; ++i) {
    if (b & (1 << i))
      ;
    else
      continue;
    s.insert(rballoon[i].begin(), rballoon[i].end());
    if (s.size() > R)
      return -1.0;
    res += Tb[i];
  }
  return res;
}

double rec(int b) {
  double &res = mem[b];
  if (res != -1.0)
    return res;
  if (b == 0)
    return res = 0.0;
  res = test(b);
  if (res == -1.0) {
    for (int i = 0; i < M; ++i) {
      if (b & (1 << i)) {
        res = max(res, rec(b & ~(1 << i)));
      }
    }
  }
  return res;
}

int main() {
  while (cin >> N >> M >> R && (N | M | R)) {
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < 3; ++j)
        cin >> S[i][j];
      cin >> Sr[i];
    }
    for (int i = 0; i < M; ++i) {
      for (int j = 0; j < 3; ++j)
        cin >> T[i][j];
      cin >> Tb[i];
    }
    for (int j = 0; j < 3; ++j)
      cin >> E[j];

    for (int i = 0; i < M; ++i) {
      Tb[i] = Tb[i] / norm(T[i] - E);
    }

    makeRballoon();

    fill(mem, mem + (1 << M), -1.0);
    printf("%.8f\\n", rec((1 << M) - 1));
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

const double eps = 1e-8;

bool equals(double a, double b) { return abs(a - b) < eps; }

struct P3D {
private:
  double v[3];

public:
  P3D() { v[0] = v[1] = v[2] = 0; }

  P3D(double a, double b, double c) {
    v[0] = a;
    v[1] = b;
    v[2] = c;
  }

  P3D(const double _v[]) {
    for (int i = 0; i < 3; ++i) {
      v[i] = _v[i];
    }
  }

  double &operator[](int x) { return v[x]; }

  const double &operator[](int x) const { return v[x]; }

  P3D operator+(const P3D &p) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] + p[i];
    }
    return res;
  }

  P3D operator-(const P3D &p) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] - p[i];
    }
    return res;
  }

  P3D operator*(const double &d) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] * d;
    }
    return res;
  }

  P3D operator/(const double &d) const {
    P3D res;
    for (int i = 0; i < 3; ++i) {
      res[i] = (*this)[i] / d;
    }
    return res;
  }

  P3D &operator=(const P3D &p) {
    for (int i = 0; i < 3; ++i) {
      (*this)[i] = p[i];
    }
    return (*this);
  }
};

double dot(const P3D &a, const P3D &b) {
  double res = 0;
  for (int i = 0; i < 3; ++i)
    res += a[i] * b[i];
  return res;
}

double cross(const P3D &a, const P3D &b) {
  double res = 0;
  for (int i = 0; i < 3; ++i) {
    double t = a[i] * b[(i + 1) % 3] - a[(i + 1) % 3] * b[i];
    res += t * t;
  }
  return sqrt(res);
}

double norm(const P3D &a) { return dot(a, a); }

double abs(const P3D &a) { return sqrt(norm(a)); }

double getDistance(const P3D &a, const P3D &b) { return abs(a - b); }

double getDistanceLP(const P3D &s1, const P3D &s2, const P3D &p) {
  return abs(cross(s2 - s1, p - s1) / abs(s2 - s1));
}

double getDistanceSP(const P3D &s1, const P3D &s2, const P3D &p) {
  if (dot(s2 - s1, p - s1) < 0.0)
    return getDistance(s1, p);
  if (dot(s1 - s2, p - s2) < 0.0)
    return getDistance(s2, p);
  return getDistanceLP(s1, s2, p);
}

bool isIn(const P3D &p, const P3D &o, const double &r) {
  double d = abs(p - o);
  return equals(d, r) || d < r;
}

void show(const P3D &p) {
  cout << "(";
  for (int i = 0; i < 3; ++i) {
    if (i)
      cout << ", ";
    cout << p[i];
  }
  cout << ")" << endl;
}

const int MAXN = 2001;
const int MAXM = 16;
int N, M, R;
P3D S[MAXN];
double Sr[MAXN];
P3D T[MAXM];
double Tb[MAXM];
P3D E;
set<int> rballoon[MAXM];

void makeRballoon() {
  for (int k = 0; k < M; ++k) {
    rballoon[k].clear();
    for (int i = 0; i < N; ++i) {
      double d = getDistanceSP(T[k], E, S[i]);
      if (!equals(d, Sr[i]) && d < Sr[i]) {
        if (isIn(T[k], S[i], Sr[i]) && isIn(E, S[i], Sr[i]))
          continue;
        rballoon[k].insert(i);
      }
    }
  }
}

double test(int b) {
  double res = 0;
  set<int> s;
  for (int i = 0; i < M; ++i) {
    if (b & (1 << i))
      ;
    else
      continue;
    s.insert(rballoon[i].begin(), rballoon[i].end());
    if (s.size() > R)
      return 0.0;
    res += Tb[i];
  }
  return res;
}

int main() {
  while (cin >> N >> M >> R && (N | M | R)) {
    for (int i = 0; i < N; ++i) {
      for (int j = 0; j < 3; ++j)
        cin >> S[i][j];
      cin >> Sr[i];
    }
    for (int i = 0; i < M; ++i) {
      for (int j = 0; j < 3; ++j)
        cin >> T[i][j];
      cin >> Tb[i];
    }
    for (int j = 0; j < 3; ++j)
      cin >> E[j];

    for (int i = 0; i < M; ++i) {
      Tb[i] = Tb[i] / norm(T[i] - E);
    }

    makeRballoon();

    double res = 0;
    for (int b = 0; b < (1 << M); ++b) {
      res = max(res, test(b));
    }

    printf("%.8f\\n", res);
  }
  return 0;
}