QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#672017#7521. Find the GapForever_Young#Compile Error//C++2020.4kb2024-10-24 15:21:292024-10-24 15:21:29

Judging History

你现在查看的是最新测评结果

  • [2024-10-24 15:21:29]
  • 评测
  • [2024-10-24 15:21:29]
  • 提交

answer

#include <cmath>
const double EPS = 1e-8;
struct Point3D {
  double x, y, z;
};
struct Line3D {
  Point3D a, b;
};
struct Plane {
  Point3D a, b, c;
};
struct PlaneF {
  // ax + by + cz + d = 0
  double a, b, c, d;
};
inline bool zero(double x) { return (x > 0 ? x : -x) < EPS; }
// 平方
inline double sqr(double d) { return d * d; }
// 计算cross product U x V
inline Point3D xmult(const Point3D& u, const Point3D& v) {
  Point3D ret;
  ret.x = u.y * v.z - v.y * u.z;
  ret.y = u.z * v.x - u.x * v.z;
  ret.z = u.x * v.y - u.y * v.x;
  return ret;
}
// 计算dot product U . V
inline double dmult(const Point3D& u, const Point3D& v) {
  return u.x * v.x + u.y * v.y + u.z * v.z;
}
// 矢量差 U - V
inline Point3D subt(const Point3D& u, const Point3D& v) {
  Point3D ret;
  ret.x = u.x - v.x;
  ret.y = u.y - v.y;
  ret.z = u.z - v.z;
  return ret;
}
// 取平面法向量
inline Point3D pvec(const Plane& s) {
  return xmult(subt(s.a, s.b), subt(s.b, s.c));
}
inline Point3D pvec(const Point3D& s1, const Point3D& s2, const Point3D& s3) {
  return xmult(subt(s1, s2), subt(s2, s3));
}
inline Point3D pvec(const PlaneF& p) {
  Point3D ret;
  ret.x = p.a;
  ret.y = p.b;
  ret.z = p.c;
  return ret;
}
// 两点距离
inline double dis(const Point3D& p1, const Point3D& p2) {
  return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) +
              (p1.z - p2.z) * (p1.z - p2.z));
}
// 向量大小
inline double vlen(const Point3D& p) {
  return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
}
// 向量大小的平方
inline double sqrlen(const Point3D& p) {
  return (p.x * p.x + p.y * p.y + p.z * p.z);
}
// 判三点共线
bool dotsInline(const Point3D& p1, const Point3D& p2, const Point3D& p3) {
  return sqrlen(xmult(subt(p1, p2), subt(p2, p3))) < EPS;
}
// 判四点共面
bool dotsOnplane(const Point3D& a, const Point3D& b, const Point3D& c,
                 const Point3D& d) {
  return zero(dmult(pvec(a, b, c), subt(d, a)));
}
// 判点是否在线段上, 包括端点和共线
bool dotOnlineIn(const Point3D& p, const Line3D& l) {
  return zero(sqrlen(xmult(subt(p, l.a), subt(p, l.b)))) &&
         (l.a.x - p.x) * (l.b.x - p.x) < EPS &&
         (l.a.y - p.y) * (l.b.y - p.y) < EPS &&
         (l.a.z - p.z) * (l.b.z - p.z) < EPS;
}
bool dotOnlineIn(const Point3D& p, const Point3D& l1, const Point3D& l2) {
  return zero(sqrlen(xmult(subt(p, l1), subt(p, l2)))) &&
         (l1.x - p.x) * (l2.x - p.x) < EPS &&
         (l1.y - p.y) * (l2.y - p.y) < EPS && (l1.z - p.z) * (l2.z - p.z) < EPS;
}

// 判点是否在线段上, 不包括端点
bool dotOnlineEx(const Point3D& p, const Line3D& l) {
  return dotOnlineIn(p, l) &&
         (!zero(p.x - l.a.x) || !zero(p.y - l.a.y) || !zero(p.z - l.a.z)) &&
         (!zero(p.x - l.b.x) || !zero(p.y - l.b.y) || !zero(p.z - l.b.z));
}
bool dotOnlineEx(const Point3D& p, const Point3D& l1, const Point3D& l2) {
  return dotOnlineIn(p, l1, l2) &&
         (!zero(p.x - l1.x) || !zero(p.y - l1.y) || !zero(p.z - l1.z)) &&
         (!zero(p.x - l2.x) || !zero(p.y - l2.y) || !zero(p.z - l2.z));
}
// 判点是否在空间三角形上, 包括边界, 三点共线无意义
bool dotInplaneIn(const Point3D& p, const Plane& s) {
  return zero(vlen(xmult(subt(s.a, s.b), subt(s.a, s.c))) -
              vlen(xmult(subt(p, s.a), subt(p, s.b))) -
              vlen(xmult(subt(p, s.b), subt(p, s.c))) -
              vlen(xmult(subt(p, s.c), subt(p, s.a))));
}
bool dotInplaneIn(const Point3D& p, const Point3D& s1, const Point3D& s2,
                  const Point3D& s3) {
  return zero(vlen(xmult(subt(s1, s2), subt(s1, s3))) -
              vlen(xmult(subt(p, s1), subt(p, s2))) -
              vlen(xmult(subt(p, s2), subt(p, s3))) -
              vlen(xmult(subt(p, s3), subt(p, s1))));
}
// 判点是否在空间三角形上, 不包括边界, 三点共线无意义
bool dotInplaneEx(const Point3D& p, const Plane& s) {
  return dotInplaneIn(p, s) &&
         sqrlen(xmult(subt(p, s.a), subt(p, s.b))) > EPS &&
         sqrlen(xmult(subt(p, s.b), subt(p, s.c))) > EPS &&
         sqrlen(xmult(subt(p, s.c), subt(p, s.a))) > EPS;
}
bool dotInplaneEx(const Point3D& p, const Point3D& s1, const Point3D& s2,
                  const Point3D& s3) {
  return dotInplaneIn(p, s1, s2, s3) &&
         sqrlen(xmult(subt(p, s1), subt(p, s2))) > EPS &&
         sqrlen(xmult(subt(p, s2), subt(p, s3))) > EPS &&
         sqrlen(xmult(subt(p, s3), subt(p, s1))) > EPS;
}
// 判两点在线段同侧, 点在线段上返回0, 不共面无意义
bool sameSide(const Point3D& p1, const Point3D& p2, const Line3D& l) {
  return dmult(xmult(subt(l.a, l.b), subt(p1, l.b)),
               xmult(subt(l.a, l.b), subt(p2, l.b))) > EPS;
}
bool sameSide(const Point3D& p1, const Point3D& p2, const Point3D& l1,
              const Point3D& l2) {
  return dmult(xmult(subt(l1, l2), subt(p1, l2)),
               xmult(subt(l1, l2), subt(p2, l2))) > EPS;
}
// 判两点在线段异侧, 点在线段上返回0, 不共面无意义
bool oppositeSide(const Point3D& p1, const Point3D& p2, const Line3D& l) {
  return dmult(xmult(subt(l.a, l.b), subt(p1, l.b)),
               xmult(subt(l.a, l.b), subt(p2, l.b))) < -EPS;
}
bool oppositeSide(const Point3D& p1, const Point3D& p2, const Point3D& l1,
                  const Point3D& l2) {
  return dmult(xmult(subt(l1, l2), subt(p1, l2)),
               xmult(subt(l1, l2), subt(p2, l2))) < -EPS;
}
// 判两点在平面同侧, 点在平面上返回0
bool sameSide(const Point3D& p1, const Point3D& p2, const Plane& s) {
  return dmult(pvec(s), subt(p1, s.a)) * dmult(pvec(s), subt(p2, s.a)) > EPS;
}
bool sameSide(const Point3D& p1, const Point3D& p2, const Point3D& s1,
              const Point3D& s2, const Point3D& s3) {
  return dmult(pvec(s1, s2, s3), subt(p1, s1)) *
             dmult(pvec(s1, s2, s3), subt(p2, s1)) >
         EPS;
}
bool sameSide(const Point3D& p1, const Point3D& p2, const PlaneF& s) {
  return (s.a * p1.x + s.b * p1.y + s.c * p1.z + s.d) *
             (s.a * p2.x + s.b * p2.y + s.c * p2.z + s.d) >
         EPS;
}
// 判两点在平面异侧, 点在平面上返回0
bool oppositeSide(const Point3D& p1, const Point3D& p2, const Plane& s) {
  return dmult(pvec(s), subt(p1, s.a)) * dmult(pvec(s), subt(p2, s.a)) < -EPS;
}
bool oppositeSide(const Point3D& p1, const Point3D& p2, const Point3D& s1,
                  const Point3D& s2, const Point3D& s3) {
  return dmult(pvec(s1, s2, s3), subt(p1, s1)) *
             dmult(pvec(s1, s2, s3), subt(p2, s1)) <
         -EPS;
}
bool oppositeSide(const Point3D& p1, const Point3D& p2, const PlaneF& s) {
  return (s.a * p1.x + s.b * p1.y + s.c * p1.z + s.d) *
             (s.a * p2.x + s.b * p2.y + s.c * p2.z + s.d) <
         -EPS;
}
// 判两直线平行
bool parallel(const Line3D& u, const Line3D& v) {
  return sqrlen(xmult(subt(u.a, u.b), subt(v.a, v.b))) < EPS;
}
bool parallel(const Point3D& u1, const Point3D& u2, const Point3D& v1,
              const Point3D& v2) {
  return sqrlen(xmult(subt(u1, u2), subt(v1, v2))) < EPS;
}
// 判两平面平行
bool parallel(const Plane& u, const Plane& v) {
  return sqrlen(xmult(pvec(u), pvec(v))) < EPS;
}
bool parallel(const Point3D& u1, const Point3D& u2, const Point3D& u3,
              const Point3D& v1, const Point3D& v2, const Point3D& v3) {
  return sqrlen(xmult(pvec(u1, u2, u3), pvec(v1, v2, v3))) < EPS;
}
bool parallel(const PlaneF& u, const PlaneF& v) {
  return sqrlen(xmult(pvec(u), pvec(v))) < EPS;
}
// 判直线与平面平行
bool parallel(const Line3D& l, const Plane& s) {
  return zero(dmult(subt(l.a, l.b), pvec(s)));
}
bool parallel(const Point3D& l1, const Point3D& l2, const Point3D& s1,
              const Point3D& s2, const Point3D& s3) {
  return zero(dmult(subt(l1, l2), pvec(s1, s2, s3)));
}
bool parallel(const Line3D& l, const PlaneF& s) {
  return zero(dmult(subt(l.a, l.b), pvec(s)));
}
// 判两直线垂直
bool perpendicular(const Line3D& u, const Line3D& v) {
  return zero(dmult(subt(u.a, u.b), subt(v.a, v.b)));
}
bool perpendicular(const Point3D& u1, const Point3D& u2, const Point3D& v1,
                   const Point3D& v2) {
  return zero(dmult(subt(u1, u2), subt(v1, v2)));
}
// 判两平面垂直
bool perpendicular(const Plane& u, const Plane& v) {
  return zero(dmult(pvec(u), pvec(v)));
}
bool perpendicular(const Point3D& u1, const Point3D& u2, const Point3D& u3,
                   const Point3D& v1, const Point3D& v2, const Point3D& v3) {
  return zero(dmult(pvec(u1, u2, u3), pvec(v1, v2, v3)));
}
bool perpendicular(const PlaneF& u, const PlaneF& v) {
  return zero(dmult(pvec(u), pvec(v)));
}
// 判直线与平面垂直
bool perpendicular(const Line3D& l, const Plane& s) {
  return sqrlen(xmult(subt(l.a, l.b), pvec(s))) < EPS;
}
bool perpendicular(const Point3D& l1, const Point3D& l2, const Point3D& s1,
                   const Point3D& s2, const Point3D& s3) {
  return sqrlen(xmult(subt(l1, l2), pvec(s1, s2, s3))) < EPS;
}
bool perpendicular(const Line3D& l, const PlaneF& s) {
  return sqrlen(xmult(subt(l.a, l.b), pvec(s))) < EPS;
}
// 判两线段相交, 包括端点和部分重合
bool intersectIn(const Line3D& u, const Line3D& v) {
  if (!dotsOnplane(u.a, u.b, v.a, v.b)) {
    return 0;
  } else if (!dotsInline(u.a, u.b, v.a) || !dotsInline(u.a, u.b, v.b)) {
    return !sameSide(u.a, u.b, v) && !sameSide(v.a, v.b, u);
  } else {
    return dotOnlineIn(u.a, v) || dotOnlineIn(u.b, v) || dotOnlineIn(v.a, u) ||
           dotOnlineIn(v.b, u);
  }
}
bool intersectIn(const Point3D& u1, const Point3D& u2, const Point3D& v1,
                 const Point3D& v2) {
  if (!dotsOnplane(u1, u2, v1, v2)) {
    return 0;
  } else if (!dotsInline(u1, u2, v1) || !dotsInline(u1, u2, v2)) {
    return !sameSide(u1, u2, v1, v2) && !sameSide(v1, v2, u1, u2);
  } else {
    return dotOnlineIn(u1, v1, v2) || dotOnlineIn(u2, v1, v2) ||
           dotOnlineIn(v1, u1, u2) || dotOnlineIn(v2, u1, u2);
  }
}
// 判两线段相交, 不包括端点和部分重合
bool intersectEx(const Line3D& u, const Line3D& v) {
  return dotsOnplane(u.a, u.b, v.a, v.b) && oppositeSide(u.a, u.b, v) &&
         oppositeSide(v.a, v.b, u);
}
bool intersectEx(const Point3D& u1, const Point3D& u2, const Point3D& v1,
                 const Point3D& v2) {
  return dotsOnplane(u1, u2, v1, v2) && oppositeSide(u1, u2, v1, v2) &&
         oppositeSide(v1, v2, u1, u2);
}
// 判线段与空间三角形相交, 包括交于边界和(部分)包含
bool intersectIn(const Line3D& l, const Plane& s) {
  return !sameSide(l.a, l.b, s) && !sameSide(s.a, s.b, l.a, l.b, s.c) &&
         !sameSide(s.b, s.c, l.a, l.b, s.a) &&
         !sameSide(s.c, s.a, l.a, l.b, s.b);
}
bool intersectIn(const Point3D& l1, const Point3D& l2, const Point3D& s1,
                 const Point3D& s2, const Point3D& s3) {
  return !sameSide(l1, l2, s1, s2, s3) && !sameSide(s1, s2, l1, l2, s3) &&
         !sameSide(s2, s3, l1, l2, s1) && !sameSide(s3, s1, l1, l2, s2);
}
// 判线段与空间三角形相交, 不包括交于边界和(部分)包含
bool intersectEx(const Line3D& l, const Plane& s) {
  return oppositeSide(l.a, l.b, s) && oppositeSide(s.a, s.b, l.a, l.b, s.c) &&
         oppositeSide(s.b, s.c, l.a, l.b, s.a) &&
         oppositeSide(s.c, s.a, l.a, l.b, s.b);
}
bool intersectEx(const Point3D& l1, const Point3D& l2, const Point3D& s1,
                 const Point3D& s2, const Point3D& s3) {
  return oppositeSide(l1, l2, s1, s2, s3) && oppositeSide(s1, s2, l1, l2, s3) &&
         oppositeSide(s2, s3, l1, l2, s1) && oppositeSide(s3, s1, l1, l2, s2);
}
// 计算两直线交点, 注意事先判断直线是否共面和平行!
// 线段交点请另外判线段相交(同时还是要判断是否平行!)
#include <algorithm>
using namespace std;
Point3D intersection(Point3D u1, Point3D u2, Point3D v1, Point3D v2) {
  double dxu = u2.x - u1.x;
  double dyu = u2.y - u1.y;
  double dzu = u2.z - u1.z;
  double dxv = v2.x - v1.x;
  double dyv = v2.y - v1.y;
  double dzv = v2.z - v1.z;
  double t;
  if (!zero(dxu * dyv - dyu * dxv)) {
    t = (dyv * (v1.x - u1.x) + dxv * (u1.y - v1.y)) / (dxu * dyv - dyu * dxv);
  } else if (!zero(dxu * dzv - dzu * dxv)) {
    t = (dzv * (v1.x - u1.x) + dxv * (u1.z - v1.z)) / (dxu * dzv - dzu * dxv);
  } else {
    t = (dzv * (v1.y - u1.y) + dyv * (u1.z - v1.z)) / (dyu * dzv - dzu * dyv);
  }
  Point3D ret;
  ret.x = u1.x + dxu * t;
  ret.y = u1.y + dyu * t;
  ret.z = u1.z + dzu * t;
  return ret;
}
// 计算直线与平面交点, 注意事先判断是否平行, 并保证三点不共线!
// 线段和空间三角形交点请另外判断
Point3D intersection(const Line3D& l, const Plane& s) {
  Point3D ret = pvec(s);
  double t = (ret.x * (s.a.x - l.a.x) + ret.y * (s.a.y - l.a.y) +
              ret.z * (s.a.z - l.a.z)) /
             (ret.x * (l.b.x - l.a.x) + ret.y * (l.b.y - l.a.y) +
              ret.z * (l.b.z - l.a.z));
  ret.x = l.a.x + (l.b.x - l.a.x) * t;
  ret.y = l.a.y + (l.b.y - l.a.y) * t;
  ret.z = l.a.z + (l.b.z - l.a.z) * t;
  return ret;
}
Point3D intersection(const Point3D& l1, const Point3D& l2, const Point3D& s1,
                     const Point3D& s2, const Point3D& s3) {
  Point3D ret = pvec(s1, s2, s3);
  double t =
      (ret.x * (s1.x - l1.x) + ret.y * (s1.y - l1.y) + ret.z * (s1.z - l1.z)) /
      (ret.x * (l2.x - l1.x) + ret.y * (l2.y - l1.y) + ret.z * (l2.z - l1.z));
  ret.x = l1.x + (l2.x - l1.x) * t;
  ret.y = l1.y + (l2.y - l1.y) * t;
  ret.z = l1.z + (l2.z - l1.z) * t;
  return ret;
}
Point3D intersection(const Line3D& l, const PlaneF& s) {
  Point3D ret = subt(l.b, l.a);
  double t = -(dmult(pvec(s), l.a) + s.d) / (dmult(pvec(s), ret));
  ret.x = ret.x * t + l.a.x;
  ret.y = ret.y * t + l.a.y;
  ret.z = ret.z * t + l.a.z;
  return ret;
}
// 计算两平面交线, 注意事先判断是否平行, 并保证三点不共线!
Line3D intersection(const Plane& u, const Plane& v) {
  Line3D ret;
  ret.a = parallel(v.a, v.b, u.a, u.b, u.c)
              ? intersection(v.b, v.c, u.a, u.b, u.c)
              : intersection(v.a, v.b, u.a, u.b, u.c);
  ret.b = parallel(v.c, v.a, u.a, u.b, u.c)
              ? intersection(v.b, v.c, u.a, u.b, u.c)
              : intersection(v.c, v.a, u.a, u.b, u.c);
  return ret;
}
Line3D intersection(const Point3D& u1, const Point3D& u2, const Point3D& u3,
                    const Point3D& v1, const Point3D& v2, const Point3D& v3) {
  Line3D ret;
  ret.a = parallel(v1, v2, u1, u2, u3) ? intersection(v2, v3, u1, u2, u3)
                                       : intersection(v1, v2, u1, u2, u3);
  ret.b = parallel(v3, v1, u1, u2, u3) ? intersection(v2, v3, u1, u2, u3)
                                       : intersection(v3, v1, u1, u2, u3);
  return ret;
}
// 点到直线距离
double disptoline(const Point3D& p, const Line3D& l) {
  return vlen(xmult(subt(p, l.a), subt(l.b, l.a))) / dis(l.a, l.b);
}
double disptoline(const Point3D& p, const Point3D& l1, const Point3D& l2) {
  return vlen(xmult(subt(p, l1), subt(l2, l1))) / dis(l1, l2);
}
// 点到直线最近点
Point3D ptoline(const Point3D& p, const Line3D& l) {
  Point3D ab = subt(l.b, l.a);
  double t = -dmult(subt(p, l.a), ab) / sqrlen(ab);
  ab.x *= t;
  ab.y *= t;
  ab.z *= t;
  return subt(l.a, ab);
}
// 点到平面距离
double disptoplane(const Point3D& p, const Plane& s) {
  return fabs(dmult(pvec(s), subt(p, s.a))) / vlen(pvec(s));
}
double disptoplane(const Point3D& p, const Point3D& s1, const Point3D& s2,
                   const Point3D& s3) {
  return fabs(dmult(pvec(s1, s2, s3), subt(p, s1))) / vlen(pvec(s1, s2, s3));
}
double disptoplane(const Point3D& p, const PlaneF& s) {
  return fabs((dmult(pvec(s), p) + s.d) / vlen(pvec(s)));
}
// 点到平面最近点
Point3D ptoplane(const Point3D& p, const PlaneF& s) {
  Line3D l;
  l.a = p;
  l.b = pvec(s);
  l.b.x += p.x;
  l.b.y += p.y;
  l.b.z += p.z;
  return intersection(l, s);
}
// 直线到直线距离
double dislinetoline(const Line3D& u, const Line3D& v) {
  Point3D n = xmult(subt(u.a, u.b), subt(v.a, v.b));
  return fabs(dmult(subt(u.a, v.a), n)) / vlen(n);
}
double dislinetoline(const Point3D& u1, const Point3D& u2, const Point3D& v1,
                     const Point3D& v2) {
  Point3D n = xmult(subt(u1, u2), subt(v1, v2));
  return fabs(dmult(subt(u1, v1), n)) / vlen(n);
}
// 直线到直线的最近点对
// p1在u上,p2在v上,p1到p2是uv之间的最近距离
// 注意,保证两直线不平行
void linetoline(const Line3D& u, const Line3D& v, Point3D& p1, Point3D& p2) {
  Point3D ab = subt(u.b, u.a), cd = subt(v.b, v.a), ac = subt(v.a, u.a);
  double r = (dmult(ab, cd) * dmult(ac, ab) - sqrlen(ab) * dmult(ac, cd)) /
             (sqrlen(ab) * sqrlen(cd) - sqr(dmult(ab, cd)));
  p2.x = v.a.x + r * cd.x;
  p2.y = v.a.y + r * cd.y;
  p2.z = v.a.z + r * cd.z;
  p1 = ptoline(p2, u);
}
// 两直线夹角cos值
double angleCos(const Line3D& u, const Line3D& v) {
  return dmult(subt(u.a, u.b), subt(v.a, v.b)) / vlen(subt(u.a, u.b)) /
         vlen(subt(v.a, v.b));
}
double angleCos(const Point3D& u1, const Point3D& u2, const Point3D& v1,
                const Point3D& v2) {
  return dmult(subt(u1, u2), subt(v1, v2)) / vlen(subt(u1, u2)) /
         vlen(subt(v1, v2));
}
// 两平面夹角cos值
double angleCos(const Plane& u, const Plane& v) {
  return dmult(pvec(u), pvec(v)) / vlen(pvec(u)) / vlen(pvec(v));
}
double angleCos(const Point3D& u1, const Point3D& u2, const Point3D& u3,
                const Point3D& v1, const Point3D& v2, const Point3D& v3) {
  return dmult(pvec(u1, u2, u3), pvec(v1, v2, v3)) / vlen(pvec(u1, u2, u3)) /
         vlen(pvec(v1, v2, v3));
}
double angleCos(const PlaneF& u, const PlaneF& v) {
  return dmult(pvec(u), pvec(v)) / (vlen(pvec(u)) * vlen(pvec(v)));
}
// 直线平面夹角sin值
double angleSin(const Line3D& l, const Plane& s) {
  return dmult(subt(l.a, l.b), pvec(s)) / vlen(subt(l.a, l.b)) / vlen(pvec(s));
}
double angleSin(const Point3D& l1, const Point3D& l2, const Point3D& s1,
                const Point3D& s2, const Point3D& s3) {
  return dmult(subt(l1, l2), pvec(s1, s2, s3)) / vlen(subt(l1, l2)) /
         vlen(pvec(s1, s2, s3));
}
double angleSin(Line3D l, const PlaneF& s) {
  return dmult(subt(l.a, l.b), pvec(s)) /
         (vlen(subt(l.a, l.b)) * vlen(pvec(s)));
}
// 平面方程形式转化 Plane -> PlaneF
PlaneF planeToPlaneF(const Plane& p) {
  PlaneF ret;
  Point3D m = xmult(subt(p.b, p.a), subt(p.c, p.a));
  ret.a = m.x;
  ret.b = m.y;
  ret.c = m.z;
  ret.d = -m.x * p.a.x - m.y * p.a.y - m.z * p.a.z;
  return ret;
}

int n;
Point3D p[51];

double eq(double a, double b) { return fabs(a - b) < 1e-7; }

bool cmp(const Point3D& a, const Point3D& b) {
  if (eq(a.x, b.x)) {
    if (eq(a.y, b.y)) {
      return a.z < b.z;
    }
    return a.y < b.y;
  }
  return a.x < b.x;
}

double gao(const Point3D& vec) {
  Line3D line = {Point3D({0, 0, 0}), vec};
  Point3D maxp {-1e9, -1e9, -1e9}, minp {1e9, 1e9, 1e9};
  for (int i = 1; i <= n; i++) {
    auto pp = ptoline(p[i], line);
    if (cmp(pp, minp)) {
      minp = pp;
    }
    if (cmp(maxp, pp)) {
      maxp = pp;
    }
  }
  /*
  printf("line = (%.5f,%.5f,%.5f) (%.5f,%.5f,%.5f)\n", line.a.x, line.a.y,
         line.a.z, line.b.x, line.b.y, line.b.z);
  printf("min=(%.5f,%.5f,%.5f), max=(%.5f,%.5f,%.5f)\n", minp.x, minp.y, minp.z,
         maxp.x, maxp.y, maxp.z);
  printf("d = %.5f\n", dis(maxp, minp));
  */
  return dis(maxp, minp);
}

int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
  }
  double ans = 1e9;
  for (int i = 1; i <= n; i++) {
    for (int j = i + 1; j <= n; j++) {
      for (int k = j + 1; k <= n; k++) {
        Plane pl;
        pl.a = p[i];
        pl.b = p[j];
        pl.c = p[k];
        Point3D vec = pvec(pl);
        ans = min(ans, gao(vec));
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = i + 1; j <= n; j++) {
      for (int k = 1; k <= n; k++) {
        if (k == i || k == j) continue;
        for (int l = k + 1; l <= n; l++) {
          if (l == i || l == j) continue;
          Point3D delta = subt(p[l], p[k]);
          Point3D p3 = {p[i].x + delta.x, p[i].y + delta.y, p[i].z + delta.z};
          if (zero(dis(p3, p[j]))) continue;
          Plane pl = {p[i], p[j], p3};
          Point3D vec = pvec(pl);
          ans = min(ans, gao(vec));
        }
      }
    }
  }
  printf("%.12f\n", ans);
}

Details

answer.code: In function ‘int main()’:
answer.code:511:3: error: ‘scanf’ was not declared in this scope
  511 |   scanf("%d", &n);
      |   ^~~~~
answer.code:544:3: error: ‘printf’ was not declared in this scope
  544 |   printf("%.12f\n", ans);
      |   ^~~~~~
answer.code:294:1: note: ‘printf’ is defined in header ‘<cstdio>’; did you forget to ‘#include <cstdio>’?
  293 | #include <algorithm>
  +++ |+#include <cstdio>
  294 | using namespace std;