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

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

// * XY座標
#define X real()
#define Y imag()

// * 点の表現
typedef complex<double> P;

// * complex<double> の順序を定義する
namespace std {
bool operator<(const P &a, const P &b) {
  return (real(a) != real(b)) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

// * 許容する誤差ε
const double EPS = 1e-10;
// * Infinity
const double INF = 1e12;
// * 円周率
const double PI = acos(-1.0);
// * Infinity 2
const P INF_P(INF, INF);

// * 2乗する
double sq(double x) { return x * x; }

// * 2点間の距離
double dist(P p1, P p2) { return abs(p1 - p2); }

// * 2つのスカラーが等しいかどうか
bool equal(double a, double b) { return (fabs(a - b) < EPS); }
// * 2つのベクトルが等しいかどうか
bool eq_v(P a, P b) { return (equal(a.X, b.X) && equal(a.Y, b.Y)); }

// * 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) { return real(conj(a) * b); }

// * 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) { return imag(conj(a) * b); }

// CCW : 反時計回り (Counter Clock Wise)
// CW : 時計回り (Clock Wise)
enum { CCW = 1, CW = -1, ON = 0 };
// * 3点がどちら回りであるか返す, 3点が1直線に乗っているときは ON を返す
int ccw(const P &a, P b, P c) {
  b -= a, c -= a;
  if (cross(b, c) > EPS)
    return CCW; // CCW : 反時計回り
  if (cross(b, c) < -EPS)
    return CW; // CW : 時計回り
  if (dot(b, c) < -EPS)
    return +2; // c--a--b on line
  if (dot(b, b) + EPS < dot(c, c))
    return -2; // a--b--c on line ???
  return ON;
}

// 直線の表現 ((*this)[0]) と ((*this)[1]) を通る直線
struct Line : public vector<P> {
  Line(const P &a, const P &b) {
    push_back(a);
    push_back(b);
  }
  Line(vector<P> v) {
    push_back(v[0]);
    push_back(v[1]);
  }
  Line() {}
  // 2直線の平行判定
  bool parallel(const Line &l) {
    return equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 点 p が直線上に乗っているか
  bool contain(P p) {
    return equal(cross((*this)[1] - (*this)[0], p - (*this)[0]), 0.0);
  }
  // 直線の交差判定
  bool is_intersection(const Line &l) {
    return !equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 直線の交差判定と交点計算
  bool intersection(Line l, P &p) {
    bool result = this->is_intersection(l);
    if (result) {
      P a = (*this)[1] - (*this)[0];
      P b = l[1] - l[0];
      p = (*this)[0] + a * cross(b, l[0] - (*this)[0]) / cross(b, a);
    } else {
      p = INF_P;
    }
    return result;
  }
};

int main() {
  int n;
  while (cin >> n, n) {
    int ans = 1;
    vector<Line> v;
    for (int i = 0; i < n; i++) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      v.push_back(Line(P(x1, y1), P(x2, y2)));
    }
    for (int i = 0; i < v.size(); i++) {
      Line l = v[i];
      vector<P> vp;
      // (増加する領域数) = (交差する線分数) - (重複交点数) + 1
      int cnt = 0;
      for (int j = 0; j < i; j++) {
        // 平行かどうかチェック
        if (v[j].parallel(l))
          continue;
        P p;
        // 交点計算
        if (v[j].intersection(l, p)) {
          // (-100,-100) - (100,100) の矩形の領域に交点があるかチェック
          // 交点が境界のときは交差していない扱い
          if (abs(p.X) > 100.0 - EPS)
            continue;
          if (abs(p.Y) > 100.0 - EPS)
            continue;

          // 交点 p と重なる交点があるかチェック
          bool flag = false;
          for (int k = 0; k < vp.size(); k++) {
            if (eq_v(p, vp[k])) {
              flag = true;
              break;
            }
          }
          // 交点が重複しない線分の個数を数える
          if (!flag) {
            cnt++;
            vp.push_back(p);
          }
        }
      }
      ans += cnt + 1;
    }
    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

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

// * XY座標
#define X real()
#define Y imag()

// * 点の表現
typedef complex<double> P;

// * complex<double> の順序を定義する
namespace std {
bool operator<(const P &a, const P &b) {
  return (real(a) != real(b)) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

// * 許容する誤差ε
const double EPS = 1e-10;
// * Infinity
const double INF = 1e12;
// * 円周率
const double PI = acos(-1.0);
// * Infinity 2
const P INF_P(INF, INF);

// * 2乗する
double sq(double x) { return x * x; }

// * 2点間の距離
double dist(P p1, P p2) { return abs(p1 - p2); }

// * 2つのスカラーが等しいかどうか
bool equal(double a, double b) { return (fabs(a - b) < EPS); }
// * 2つのベクトルが等しいかどうか
bool eq_v(P a, P b) { return (equal(a.X, b.X) && equal(a.Y, b.Y)); }

// * 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) { return real(conj(a) * b); }

// * 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) { return imag(conj(a) * b); }

// CCW : 反時計回り (Counter Clock Wise)
// CW : 時計回り (Clock Wise)
enum { CCW = 1, CW = -1, ON = 0 };
// * 3点がどちら回りであるか返す, 3点が1直線に乗っているときは ON を返す
int ccw(const P &a, P b, P c) {
  b -= a, c -= a;
  if (cross(b, c) > EPS)
    return CCW; // CCW : 反時計回り
  if (cross(b, c) < -EPS)
    return CW; // CW : 時計回り
  if (dot(b, c) < -EPS)
    return +2; // c--a--b on line
  if (dot(b, b) + EPS < dot(c, c))
    return -2; // a--b--c on line ???
  return ON;
}

// 直線の表現 ((*this)[0]) と ((*this)[1]) を通る直線
struct Line : public vector<P> {
  Line(const P &a, const P &b) {
    push_back(a);
    push_back(b);
  }
  Line(vector<P> v) {
    push_back(v[0]);
    push_back(v[1]);
  }
  Line() {}
  // 2直線の平行判定
  bool parallel(const Line &l) {
    return equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 点 p が直線上に乗っているか
  bool contain(P p) {
    return equal(cross((*this)[1] - (*this)[0], p - (*this)[0]), 0.0);
  }
  // 直線の交差判定
  bool is_intersection(const Line &l) {
    return !equal(cross((*this)[0] - (*this)[1], l[0] - l[1]), 0.0);
  }
  // 直線の交差判定と交点計算
  bool intersection(Line l, P &p) {
    bool result = this->is_intersection(l);
    if (result) {
      P a = (*this)[1] - (*this)[0];
      P b = l[1] - l[0];
      p = (*this)[0] + a * cross(b, l[0] - (*this)[0]) / cross(b, a);
    } else {
      p = INF_P;
    }
    return result;
  }
};

int main() {
  int n;
  while (cin >> n, n) {
    int cnt = 1;
    vector<Line> v;
    vector<P> vp;
    for (int i = 0; i < n; i++) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      Line l(P(x1, y1), P(x2, y2));

      // (増加する領域数) = (交差する線分数 a) - (重複交点数 b) + 1
      int a = 0, b = 0;
      for (int j = 0; j < v.size(); j++) {
        // 平行かどうかチェック
        if (v[j].parallel(l))
          continue;
        P p;
        // 交点計算
        if (v[j].intersection(l, p)) {
          // (-100,-100) - (100,100) の矩形の領域に交点があるかチェック
          // 交点が境界のときは交差していない扱い
          if (abs(p.X) > 100.0 - EPS)
            continue;
          if (abs(p.Y) > 100.0 - EPS)
            continue;
          a++;
          // 交点 p と重なる交点があるかチェック
          for (int k = 0; k < vp.size(); k++) {
            if (eq_v(p, vp[k]))
              b++;
          }
          vp.push_back(p);
          sort(vp.begin(), vp.end());
          unique(vp.begin(), vp.end());
        }
      }
      v.push_back(l);
      cnt += a - b + 1;
    }
    cout << cnt << endl;
  }
}