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

#include <cmath>
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>

#define EPS 1e-10
#define PI 3.141592654

class Point {
  double x;
  double y;

public:
  Point(double a, double b) : x(a), y(b) {}
  double X() const { return x; }
  double Y() const { return y; }
  double Norm() const { return sqrt(pow(x, 2) + pow(y, 2)); }
};

typedef Point Vector;

class Circle {
  Point o;
  double r;

public:
  Circle(double x, double y, double rad) : o(x, y), r(rad) {}
  Point O() { return o; }
  double R() { return r; }
};

double getDistance(const Point &a, const Point &b) {
  return sqrt(pow(a.X() - b.X(), 2) + pow(a.Y() - b.Y(), 2));
}

double getAreaOfTri(const Point &a, const Point &b, const Point &c) {
  double ab = getDistance(a, b);
  double bc = getDistance(b, c);
  double ca = getDistance(c, a);
  double s = (ab + bc + ca) / 2.0;
  double Area = sqrt(s * (s - ab) * (s - bc) * (s - ca));
  if (s - ab < EPS || s - bc < EPS || s - ca < EPS) {
    Area = 0;
  }
  return Area;
}

double getDistancePointLine(const Point &o, const Point &a, const Point &b) {
  double area = getAreaOfTri(o, a, b);
  double ab = getDistance(a, b);
  double h = 2 * area / ab;
  return h;
}

Point getMiddlePoint(const Point &a, const Point &b) {
  double middleX = (a.X() + b.X()) / 2.0;
  double middleY = (a.Y() + b.Y()) / 2.0;
  Point middle(middleX, middleY);
  return middle;
}

double getDotProduct(const Vector &a, const Vector &b) {
  return a.X() * b.X() + a.Y() * b.Y();
}

double getAngle(const Vector &a, const Vector &b) {
  double cosAngleAB = getDotProduct(a, b) / (a.Norm() * b.Norm());
  if (cosAngleAB < -1) {
    cosAngleAB = -1.0;
  } else if (cosAngleAB > 1) {
    cosAngleAB = 1.0;
  }
  double angleAB = acos(cosAngleAB);
  return angleAB;
}

bool isWall(const Point &t, const Point &s, Circle wall) {
  Vector ts(s.X() - t.X(), s.Y() - t.Y());
  Vector to(wall.O().X() - t.X(), wall.O().Y() - t.Y());
  Vector st(t.X() - s.X(), t.Y() - s.Y());
  Vector so(wall.O().X() - s.X(), wall.O().Y() - s.Y());

  if (ts.Norm() < EPS || st.Norm() < EPS) {
    return false;
  }
  if (to.Norm() < EPS || so.Norm() < EPS) {
    if (to.Norm() < EPS) {
      if (so.Norm() <= wall.R() + EPS) {
        return false;
      } else {
        return true;
      }
    }
    if (so.Norm() < EPS) {
      if (to.Norm() <= wall.R() + EPS) {
        return false;
      } else {
        return true;
      }
    }
  }

  double angleOTS = getAngle(ts, to);
  double angleOST = getAngle(st, so);

  // 壁になるときにtrueを返す。
  if (wall.R() > getDistance(t, wall.O()) &&
      wall.R() > getDistance(s, wall.O())) {
    return false;
  } else if (wall.R() < getDistance(t, wall.O()) &&
             wall.R() < getDistance(s, wall.O())) {
    if (!(angleOTS < PI / 2 && angleOST < PI / 2 &&
          getDistancePointLine(wall.O(), t, s) <= wall.R() + EPS)) {
      return false;
    } else {
      return true;
    }
  } else {
    return true;
  }
}

struct TEST_CASE {
  int ox;
  int oy;
  int r;
  int tx;
  int ty;
  int sx;
  int sy;
  std::string ans;
  TEST_CASE(){};
  void SetTestCase(int ox, int oy, int r, int tx, int ty, int sx, int sy,
                   std::string ans) {
    this->ox = ox;
    this->oy = oy;
    this->r = r;
    this->tx = tx;
    this->ty = ty;
    this->sx = sx;
    this->sy = sy;
    this->ans = ans;
  }
};

void test(void) {
  TEST_CASE testCase[100];

  testCase[0].SetTestCase(6, 6, 3, 3, 9, 3, 3, "Safe");
  testCase[1].SetTestCase(6, 6, 3, 3, 9, 9, 9, "Safe");
  testCase[2].SetTestCase(6, 6, 3, 6, 1, 11, 6, "Danger");
  testCase[3].SetTestCase(6, 6, 3, 3, 10, 9, 10, "Danger");
  testCase[4].SetTestCase(6, 6, 3, 4, 7, 8, 7, "Danger");
  testCase[5].SetTestCase(6, 6, 3, 4, 2, 5, 5, "Safe");
  testCase[6].SetTestCase(6, 6, 3, 5, 2, 10, 7, "Safe");
  testCase[7].SetTestCase(6, 6, 3, 2, 5, 10, 7, "Safe");
  testCase[8].SetTestCase(6, 6, 3, 6, 6, 6, 6, "Danger");
  testCase[9].SetTestCase(6, 6, 3, 11, 9, 11, 9, "Danger");
  testCase[10].SetTestCase(6, 6, 3, 6, 6, 8, 8, "Danger");
  testCase[11].SetTestCase(6, 6, 3, 5, 9, 7, 9, "Safe");
  testCase[12].SetTestCase(20, 20, 12, 20, 5, 40, 20, "Safe");
  testCase[13].SetTestCase(20, 20, 12, 20, 5, 39, 20, "Safe");
  testCase[14].SetTestCase(20, 20, 12, 20, 5, 41, 20, "Danger");
  testCase[15].SetTestCase(127, 127, 127, 126, 0, 128, 0, "Safe");

  for (int i = 0; i < 16; i++) {
    Circle wall(testCase[i].ox, testCase[i].oy, testCase[i].r);
    Point t(testCase[i].tx, testCase[i].ty);
    Point s(testCase[i].sx, testCase[i].sy);
    std::string ans = isWall(t, s, wall) ? "Safe" : "Danger";
    std::cout << "testCase" << i << " : "
              << (ans == testCase[i].ans ? "OK" : "NG") << std::endl;
  }
}

int main(void) {
  int n, m;

  // test();

  while (1) {
    std::vector<Circle> wall;
    std::cin >> n;

    if (n == 0) {
      break;
    }
    for (int i = 0; i < n; i++) {
      int x, y, r;
      std::cin >> x >> y >> r;
      Circle cir(x, y, r);
      wall.push_back(cir);
    }
    std::cin >> m;

    for (int i = 0; i < m; i++) {
      int tx, ty, sx, sy;
      std::cin >> tx >> ty >> sx >> sy;

      Point t(tx, ty);
      Point s(sx, sy);
      int flag = 0;
      for (int j = 0; j < n; j++) {
        if (isWall(t, s, wall[j])) {
          flag = 1;
          break;
        }
      }
      std::cout << (flag == 1 ? "Safe" : "Danger") << std::endl;
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cmath>
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>

#define EPS 1e-10
#define PI 3.141592654

class Point {
  double x;
  double y;

public:
  Point(double a, double b) : x(a), y(b) {}
  double X() const { return x; }
  double Y() const { return y; }
  double Norm() const { return sqrt(pow(x, 2) + pow(y, 2)); }
};

typedef Point Vector;

class Circle {
  Point o;
  double r;

public:
  Circle(double x, double y, double rad) : o(x, y), r(rad) {}
  Point O() { return o; }
  double R() { return r; }
};

double getDistance(const Point &a, const Point &b) {
  return sqrt(pow(a.X() - b.X(), 2) + pow(a.Y() - b.Y(), 2));
}

double getAreaOfTri(const Point &a, const Point &b, const Point &c) {
  double ab = getDistance(a, b);
  double bc = getDistance(b, c);
  double ca = getDistance(c, a);
  double s = (ab + bc + ca) / 2.0;
  double Area = sqrt(s * (s - ab) * (s - bc) * (s - ca));
  if (s - ab < EPS || s - bc < EPS || s - ca < EPS) {
    Area = 0;
  }
  return Area;
}

double getDistancePointLine(const Point &o, const Point &a, const Point &b) {
  double area = getAreaOfTri(o, a, b);
  double ab = getDistance(a, b);
  double h = 2 * area / ab;
  return h;
}

Point getMiddlePoint(const Point &a, const Point &b) {
  double middleX = (a.X() + b.X()) / 2.0;
  double middleY = (a.Y() + b.Y()) / 2.0;
  Point middle(middleX, middleY);
  return middle;
}

double getDotProduct(const Vector &a, const Vector &b) {
  return a.X() * b.X() + a.Y() * b.Y();
}

double getAngle(const Vector &a, const Vector &b) {
  double cosAngleAB = getDotProduct(a, b) / (a.Norm() * b.Norm());
  if (cosAngleAB < 0) {
    cosAngleAB += EPS;
  } else if (cosAngleAB > 0) {
    cosAngleAB -= EPS;
  }
  double angleAB = acos(cosAngleAB);
  return angleAB;
}

bool isWall(const Point &t, const Point &s, Circle wall) {
  Vector ts(s.X() - t.X(), s.Y() - t.Y());
  Vector to(wall.O().X() - t.X(), wall.O().Y() - t.Y());
  Vector st(t.X() - s.X(), t.Y() - s.Y());
  Vector so(wall.O().X() - s.X(), wall.O().Y() - s.Y());

  double angleOTS = getAngle(ts, to);
  double angleOST = getAngle(st, so);

  // 壁になるときにtrueを返す。
  if (wall.R() > getDistance(t, wall.O()) &&
      wall.R() > getDistance(s, wall.O())) {
    return false;
  } else if (wall.R() < getDistance(t, wall.O()) &&
             wall.R() < getDistance(s, wall.O())) {
    if (!(angleOTS < PI / 2 && angleOST < PI / 2 &&
          getDistancePointLine(wall.O(), t, s) <= wall.R() + EPS)) {
      return false;
    }
  } else {
    return true;
  }
}

int main(void) {
  int n, m;
  std::vector<Circle> wall;
  while (1) {
    std::cin >> n;
    if (n == 0) {
      break;
    }
    for (int i = 0; i < n; i++) {
      int x, y, r;
      std::cin >> x >> y >> r;
      Circle cir(x, y, r);
      wall.push_back(cir);
    }
    std::cin >> m;
    for (int i = 0; i < 256 * 256; i++) {
      int tx, ty, sx, sy;
      std::cin >> tx >> ty >> sx >> sy;
      Point t(tx, ty);
      Point s(sx, sy);
      int flag = 0;
      for (int j = 0; j < n; j++) {
        if (isWall(t, s, wall[j])) {
          flag = 1;
          break;
        }
      }
      std::cout << (flag == 1 ? "Safe" : "Danger") << std::endl;
    }
  }

  return 0;
}