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

#include "bits/stdc++.h"
#include <unordered_map>
#pragma warning(disable : 4996)
using namespace std;

struct Point3 {
  long double x;
  long double y;
  long double z;
  Point3() : x(0), y(0), z(0) {}
  Point3(const long double _x, const long double _y, const long double _z)
      : x(_x), y(_y), z(_z) {}
};

Point3 operator+(const Point3 &l, const Point3 &r) {
  return Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator+=(Point3 &l, const Point3 &r) {
  return l = Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator-(const Point3 &l, const Point3 &r) {
  return Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator-=(Point3 &l, const Point3 &r) {
  return l = Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator*(const Point3 &l, const long double r) {
  return Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator*(const long double r, const Point3 &l) { return l * r; }
Point3 operator*=(Point3 &l, const long double r) {
  return l = Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator/(const Point3 &l, const long double r) {
  return Point3(l.x / r, l.y / r, l.z / r);
}
Point3 operator/=(Point3 &l, const long double r) {
  return l = Point3(l.x / r, l.y / r, l.z / r);
}
const long double eps = 1e-9, pi = acos(-1.0);
const long double dtop = pi / 180.;
const long double ptod = 1. / dtop;

namespace std {
bool operator<(const Point3 &lhs, const Point3 &rhs) {
  if (lhs.x < rhs.x - eps)
    return true;
  if (lhs.x > rhs.x + eps)
    return false;
  if (lhs.y < rhs.y - eps)
    return true;
  if (lhs.y > rhs.y + eps)
    return false;
  return lhs.z < rhs.z;
}
} // namespace std

// 点の入力
Point3 input_point() {
  long double x, y, z;
  cin >> x >> y >> z;
  return Point3(x, y, z);
}

// 誤差つき等号判定
bool eq(const long double a, const long double b) { return (abs(a - b) < eps); }

// 内積
long double dot(const Point3 &a, const Point3 &b) {
  return a.x * b.x + a.y * b.y + a.z * b.z;
}

// 外積
Point3 cross(const Point3 &a, const Point3 &b) {
  return Point3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z,
                a.x * b.y - a.y * b.x);
}

// ノルム
long double norm(const Point3 &p) {
  return (p.x * p.x + p.y * p.y + p.z * p.z);
}

long double abs(const Point3 &p) {

  return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
}

// 球
struct Sphere {
  Point3 p;
  long double r;
  Sphere() : p(), r(0) {}
  Sphere(const Point3 _point, const long double _radius)
      : p(_point), r(_radius) {}
};

// 直線の定義
class Line3 {
public:
  Point3 a, b;
  Line3() : a(Point3(0, 0, 0)), b(Point3(0, 0, 0)) {}
  Line3(Point3 a, Point3 b) : a(a), b(b) {}
  Point3 operator[](const int _num) const {
    if (_num == 0)
      return a;
    else if (_num == 1)
      return b;
    else
      assert(false);
  }
};

// 点の線分上判定
bool isis_sp(const Line3 &s, const Point3 &p) {
  return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// 垂線の足
Point3 proj(const Line3 &l, const Point3 &p) {
  long double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
  return l.a + t * (l.a - l.b);
}
// 直線と点の距離
long double dist_lp3(const Line3 &l, const Point3 &p) {
  return abs(p - proj(l, p));
}
// 球と直線の交点
vector<Point3> is_lsp(const Sphere &c, const Line3 &l) {
  vector<Point3> res;
  long double d = dist_lp3(l, c.p);
  if (d < c.r + eps) {
    long double len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); // safety;
    Point3 nor = (l.a - l.b) / abs(l.a - l.b);
    res.push_back(proj(l, c.p) + len * nor);
    res.push_back(proj(l, c.p) - len * nor);
  }
  return res;
}
// 球と線分の交点
vector<Point3> is_ssp(const Sphere &c, const Line3 &l) {
  vector<Point3> res(is_lsp(c, l));
  vector<Point3> nres;
  for (auto p : res) {
    if (isis_sp(l, p))
      nres.emplace_back(p);
  }
  return nres;
}
int main() {
  while (1) {

    int N, M, R;
    cin >> N >> M >> R;
    if (!N)
      break;
    vector<Sphere> obs;
    for (int i = 0; i < N; ++i) {
      long double x, y, z, r;
      cin >> x >> y >> z >> r;
      obs.emplace_back(Point3(x, y, z), r);
    }
    vector<Point3> lis;
    vector<long double> lumis;
    for (int i = 0; i < M; ++i) {
      long double x, y, z, b;
      cin >> x >> y >> z >> b;
      lis.emplace_back(x, y, z);
      lumis.emplace_back(b);
    }
    long double x, y, z;
    cin >> x >> y >> z;
    Point3 goal(x, y, z);
    for (int i = 0; i < M; ++i) {
      lumis[i] = lumis[i] / norm(goal - lis[i]);
    }
    vector<vector<int>> blocks(lis.size());
    for (int i = 0; i < obs.size(); ++i) {
      for (int j = 0; j < lis.size(); ++j) {
        Point3 li(lis[j]);
        const Line3 ltoob(li, goal);
        if (!is_ssp(obs[i], ltoob).empty()) {
          blocks[j].push_back(i);
        }
      }
    }
    long double ans = 0;
    for (int i = 0; i < (1 << M); ++i) {
      bitset<15> bs(i);
      vector<bool> need(N, false);
      set<int> needremove;
      for (int j = 0; j < M; ++j) {
        if (bs[j]) {
          for (int k = 0; k < blocks[j].size(); ++k) {
            need[blocks[j][k]] = true;
          }
        }
      }
      int num = 0;
      if (count(need.begin(), need.end(), true) <= R) {
        long double nowans = 0;
        for (int j = 0; j < M; ++j) {
          if (bs[j]) {
            nowans += lumis[j];
          }
        }
        ans = max(ans, nowans);
      }
    }
    cout << setprecision(22) << fixed << ans << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include "bits/stdc++.h"
#include <unordered_map>
#pragma warning(disable : 4996)
using namespace std;

struct Point3 {
  long double x;
  long double y;
  long double z;
  Point3() : x(0), y(0), z(0) {}
  Point3(const long double _x, const long double _y, const long double _z)
      : x(_x), y(_y), z(_z) {}
};

Point3 operator+(const Point3 &l, const Point3 &r) {
  return Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator+=(Point3 &l, const Point3 &r) {
  return l = Point3(l.x + r.x, l.y + r.y, l.z + r.z);
}
Point3 operator-(const Point3 &l, const Point3 &r) {
  return Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator-=(Point3 &l, const Point3 &r) {
  return l = Point3(l.x - r.x, l.y - r.y, l.z - r.z);
}
Point3 operator*(const Point3 &l, const long double r) {
  return Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator*(const long double r, const Point3 &l) { return l * r; }
Point3 operator*=(Point3 &l, const long double r) {
  return l = Point3(l.x * r, l.y * r, l.z * r);
}
Point3 operator/(const Point3 &l, const long double r) {
  return Point3(l.x / r, l.y / r, l.z / r);
}
Point3 operator/=(Point3 &l, const long double r) {
  return l = Point3(l.x / r, l.y / r, l.z / r);
}
const long double eps = 1e-9, pi = acos(-1.0);
const long double dtop = pi / 180.;
const long double ptod = 1. / dtop;

namespace std {
bool operator<(const Point3 &lhs, const Point3 &rhs) {
  if (lhs.x < rhs.x - eps)
    return true;
  if (lhs.x > rhs.x + eps)
    return false;
  if (lhs.y < rhs.y - eps)
    return true;
  if (lhs.y > rhs.y + eps)
    return false;
  return lhs.z < rhs.z;
}
} // namespace std

// 点の入力
Point3 input_point() {
  long double x, y, z;
  cin >> x >> y >> z;
  return Point3(x, y, z);
}

// 誤差つき等号判定
bool eq(const long double a, const long double b) { return (abs(a - b) < eps); }

// 内積
long double dot(const Point3 &a, const Point3 &b) {
  return a.x * b.x + a.y * b.y + a.z * b.z;
}

// 外積
Point3 cross(const Point3 &a, const Point3 &b) {
  return Point3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z,
                a.x * b.y - a.y * b.x);
}

// ノルム
long double norm(const Point3 &p) {
  return (p.x * p.x + p.y * p.y + p.z * p.z);
}

long double abs(const Point3 &p) {

  return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
}

// 球
struct Sphere {
  Point3 p;
  long double r;
  Sphere() : p(), r(0) {}
  Sphere(const Point3 _point, const long double _radius)
      : p(_point), r(_radius) {}
};

// 直線の定義
class Line3 {
public:
  Point3 a, b;
  Line3() : a(Point3(0, 0, 0)), b(Point3(0, 0, 0)) {}
  Line3(Point3 a, Point3 b) : a(a), b(b) {}
  Point3 operator[](const int _num) const {
    if (_num == 0)
      return a;
    else if (_num == 1)
      return b;
    else
      assert(false);
  }
};

// 点の線分上判定
bool isis_sp(const Line3 &s, const Point3 &p) {
  return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// 垂線の足
Point3 proj(const Line3 &l, const Point3 &p) {
  long double t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
  return l.a + t * (l.a - l.b);
}
// 直線と点の距離
long double dist_lp3(const Line3 &l, const Point3 &p) {
  return abs(p - proj(l, p));
}
// 球と直線の交点
vector<Point3> is_lsp(const Sphere &c, const Line3 &l) {
  vector<Point3> res;
  long double d = dist_lp3(l, c.p);
  if (d < c.r + eps) {
    long double len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); // safety;
    Point3 nor = (l.a - l.b) / abs(l.a - l.b);
    res.push_back(proj(l, c.p) + len * nor);
    res.push_back(proj(l, c.p) - len * nor);
  }
  return res;
}
// 球と線分の交点
vector<Point3> is_ssp(const Sphere &c, const Line3 &l) {
  vector<Point3> res(is_lsp(c, l));
  vector<Point3> nres;
  for (auto p : res) {
    if (isis_sp(l, p))
      nres.emplace_back(p);
  }
  return nres;
}
int main() {
  while (1) {

    int N, M, R;
    cin >> N >> M >> R;
    if (!N)
      break;
    vector<Sphere> obs;
    for (int i = 0; i < N; ++i) {
      long double x, y, z, r;
      cin >> x >> y >> z >> r;
      obs.emplace_back(Point3(x, y, z), r);
    }
    vector<Point3> lis;
    vector<long double> lumis;
    for (int i = 0; i < M; ++i) {
      long double x, y, z, b;
      cin >> x >> y >> z >> b;
      lis.emplace_back(x, y, z);
      lumis.emplace_back(b);
    }
    long double x, y, z;
    cin >> x >> y >> z;
    Point3 goal(x, y, z);
    for (int i = 0; i < M; ++i) {
      lumis[i] = lumis[i] / norm(goal - lis[i]);
    }
    vector<vector<int>> blocks(lis.size());
    for (int i = 0; i < obs.size(); ++i) {
      for (int j = 0; j < lis.size(); ++j) {
        Point3 li(lis[j]);
        const Line3 ltoob(li, goal);
        if (!is_ssp(obs[i], ltoob).empty()) {
          blocks[j].push_back(i);
        }
      }
    }
    long double ans = 0;
    for (int i = 0; i < (1 << M); ++i) {
      bitset<15> bs(i);
      set<int> needremove;
      for (int j = 0; j < M; ++j) {
        if (bs[j]) {
          for (int k = 0; k < blocks[j].size(); ++k) {
            needremove.emplace(blocks[j][k]);
          }
        }
      }
      long double nowans = 0;
      if (needremove.size() <= R) {
        for (int j = 0; j < M; ++j) {
          if (bs[j]) {
            nowans += lumis[j];
          }
        }
      }
      ans = max(ans, nowans);
    }
    cout << setprecision(22) << fixed << ans << endl;
  }
  return 0;
}