Problem p00115 (C++) — buggy submission, verdict: Runtime Error

#include <cmath>
#include <cstdio>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const double EPS = 1e-8;

struct point3 {
  double x, y, z;
  point3() : x(0), y(0), z(0) {}
  point3(double x, double y, double z) : x(x), y(y), z(z) {}
  point3 operator-(const point3 &a) const {
    return point3(x - a.x, y - a.y, z - a.z);
  }
};

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);
}

double abs(const point3 &a) { return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }

double area(const point3 &a, const point3 &b, const point3 &c) {
  return abs(cross(b - a, c - a)) / 2;
}

int main() {
  point3 p0, p1, q1, q2, q3;
  scanf("%lf%lf%lf", &p0.x, &p0.y, &p0.z);
  scanf("%lf%lf%lf", &p1.x, &p1.y, &p1.z);
  scanf("%lf%lf%lf", &q1.x, &q1.y, &q1.z);
  scanf("%lf%lf%lf", &q2.x, &q2.y, &q2.z);
  scanf("%lf%lf%lf", &q3.x, &q3.y, &q3.z);

  // line: (x-x0)/a = (y-y0)/b = (z-z0)/c = t
  double a = (p1 - p0).x, b = (p1 - p0).y, c = (p1 - p0).z;
  double x0 = p0.x, y0 = p0.y, z0 = p0.z;

  // plane: d*(x-x1) + e*(y-y1) + f*(z-z1) = 0
  point3 r = cross(q2 - q1, q3 - q1);
  double d = r.x, e = r.y, f = r.z;
  double x1 = q1.x, y1 = q1.y, z1 = q1.z;

  // the laser direction is parallel to the normal of the plane which contains
  // triangle
  if (abs(a * d + b * e + c * f) < EPS) {
    puts("HIT");
    return 0;
  }

  // x = a*t + x0, y = b*t + y0, z = c*t + z0
  // d*(a*t+x0-x1) + e*(b*t+y0-y1) + f*(c*t+z0-z1) = 0
  double t =
      (d * (x1 - x0) + e * (y1 - y0) + f * (z1 - z0)) / (a * d + b * e + c * f);
  point3 s(a * t + x0, b * t + y0, c * t + z0);

  if (area(s, q1, q2) + area(s, q2, q3) + area(s, q3, q1) >
      area(q1, q2, q3) + EPS) {
    puts("HIT");
  } else {
    puts(dot(p0 - s, p1 - s) > EPS ? "HIT" : "MISS");
  }

  return 0;
}

Error: 0

Fixed submission:

#include <cassert>
#include <cmath>
#include <cstdio>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

const double EPS = 1e-8;

struct point3 {
  double x, y, z;
  point3() : x(0), y(0), z(0) {}
  point3(double x, double y, double z) : x(x), y(y), z(z) {}
  point3 operator-(const point3 &a) const {
    return point3(x - a.x, y - a.y, z - a.z);
  }
  bool operator==(const point3 &a) const {
    return abs(x - a.x) < EPS && abs(y - a.y) < EPS && abs(z - a.z) < EPS;
  }
  bool operator!=(const point3 &a) const {
    return abs(x - a.x) > EPS || abs(y - a.y) > EPS || abs(z - a.z) > EPS;
  }
};

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);
}

double abs(const point3 &a) { return sqrt(a.x * a.x + a.y * a.y + a.z * a.z); }

double area(const point3 &a, const point3 &b, const point3 &c) {
  return abs(cross(b - a, c - a)) / 2;
}

int main() {
  point3 p0, p1, q1, q2, q3;
  scanf("%lf%lf%lf", &p0.x, &p0.y, &p0.z);
  scanf("%lf%lf%lf", &p1.x, &p1.y, &p1.z);
  scanf("%lf%lf%lf", &q1.x, &q1.y, &q1.z);
  scanf("%lf%lf%lf", &q2.x, &q2.y, &q2.z);
  scanf("%lf%lf%lf", &q3.x, &q3.y, &q3.z);

  assert(p0 != p1);

  // line: (x-x0)/a = (y-y0)/b = (z-z0)/c = t
  double a = (p1 - p0).x, b = (p1 - p0).y, c = (p1 - p0).z;
  double x0 = p0.x, y0 = p0.y, z0 = p0.z;

  // plane: d*(x-x1) + e*(y-y1) + f*(z-z1) = 0
  point3 r = cross(q2 - q1, q3 - q1);
  double d = r.x, e = r.y, f = r.z;
  double x1 = q1.x, y1 = q1.y, z1 = q1.z;

  assert(abs(r) > EPS);
  assert(abs(a * d + b * e + c * f) > EPS);

  // x = a*t + x0, y = b*t + y0, z = c*t + z0
  // d*(a*t+x0-x1) + e*(b*t+y0-y1) + f*(c*t+z0-z1) = 0
  double t =
      (d * (x1 - x0) + e * (y1 - y0) + f * (z1 - z0)) / (a * d + b * e + c * f);
  point3 s(a * t + x0, b * t + y0, c * t + z0);

  if (area(s, q1, q2) + area(s, q2, q3) + area(s, q3, q1) >
      area(q1, q2, q3) + EPS) {
    puts("HIT");
  } else {
    //		assert(s!=p0);
    puts(dot(p0 - s, p1 - s) > EPS ? "HIT" : "MISS");
  }

  return 0;
}