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

#include <bits/stdc++.h>

using namespace std;

// typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;

// container util
//------------------------------------------
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define SZ(a) int((a).size())
#define EACH(i, c)                                                             \\
  for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort((c).begin(), (c).end())

// repetition
//------------------------------------------
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// constant
//--------------------------------------------
const double mEPS = 1e-10;
const double PI = acos(-1.0);

int f(VS &vs, int x, int y) {
  string str = vs[y].substr(x, 1) + vs[y].substr(x + 1, 1) +
               vs[y + 1].substr(x, 1) + vs[y + 1].substr(x + 1, 1);
  if (str == "..#." || str == "##.#")
    return 1;
  if (str == ".#.." || str == "#.##")
    return -1;
  return 0;
}

int main() {
  int H, W;
  cin >> H >> W;
  VS vs(H + 2, string(W + 2, '.'));
  REP(i, H) {
    string s;
    cin >> s;
    vs[i + 1] = "." + s + ".";
  }
  reverse(ALL(vs));

  vector<pair<double, int>> ev;
  FOR(y, 0, H + 1) FOR(x, 0, W + 1) {
    int n = f(vs, x, y);
    if (n)
      ev.PB(MP(atan2(y, x), n));
  }
  SORT(ev);
  int ans = 2, tmp = 1;
  for (auto &e : ev)
    ans = max(ans, tmp += e.second);

  cout << ans << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

// typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;

// container util
//------------------------------------------
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define SZ(a) int((a).size())
#define EACH(i, c)                                                             \\
  for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort((c).begin(), (c).end())

// repetition
//------------------------------------------
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// constant
//--------------------------------------------
const double mEPS = 1e-10;
const double PI = acos(-1.0);

class Point {
public:
  double x, y;

  Point(double x = 0.0, double y = 0.0) : x(x), y(y) {}

  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double a) { return Point(a * x, a * y); }
  Point operator/(double a) { return Point(x / a, y / a); }

  double abs() { return sqrt(norm()); }
  double norm() { return x * x + y * y; }

  bool operator<(const Point &p) const { return x != p.x ? x < p.x : y < p.y; }

  // EPS???????????°??????????
  bool operator==(const Point &p) const {
    return fabs(x - p.x) < mEPS && fabs(y - p.y) < mEPS;
  }

  friend ostream &operator<<(ostream &os, const Point &p);
};
ostream &operator<<(ostream &os, const Point &p) {
  os << "(" << p.x << "," << p.y << ")";
  return os;
}

class Segment {
public:
  Point p1, p2;
};

typedef vector<Point> Polygon;

//????????????¨?????????±???
typedef Point Vector;
//????????????´??????¨?????????±???
typedef Segment Line;

//??????
double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }

//????????????§??????
double cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }

int ccw(Point p0, Point p1, Point p2) {

  // p0->p1???p0??§???????p1??????????????????????????????¨?????????¨???

  // p0->p2???????????¨???????????????????¨???
  static const int COUNTER_CLOCKWISE = 1;
  // p0->p2????????¨???????????????????¨???
  static const int CLOCKWISE = -1;
  // p2,p0,p1?????????§?????????´??????????????????¨???
  static const int ONLINE_BACK = 2;
  // p0,p1,p2 ?????????§?????????´??????????????????´???
  static const int ONLINE_FRONT = -2;
  // p2 ????????? p0p1 ???????????????´???
  static const int ON_SEGMENT = 0;

  Vector a = p1 - p0;
  Vector b = p2 - p0;

  if (cross(a, b) > mEPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -mEPS)
    return CLOCKWISE;
  if (dot(a, b) < -mEPS)
    return ONLINE_BACK;
  if (a.norm() < b.norm())
    return ONLINE_FRONT;

  return ON_SEGMENT;
}

bool intersect(Segment s1, Segment s2) {
  return (ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 &&
          ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0);
}

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int H, W;
  cin >> H >> W;
  VS str(H);
  REP(i, H) cin >> str[i];
  reverse(ALL(str));
  vector<Segment> ls;
  REP(y, H) REP(x, W) {
    if (str[y][x] == '#' && (y == 0 || str[y - 1][x] == '.')) {
      int t = x;
      for (; t < W; ++t)
        if (str[y][t] == '.' || (y > 0 && str[y - 1][t] == '#'))
          break;
      Point p1, p2;
      p1.x = x;
      p1.y = y;
      p2.x = t, p2.y = y;
      Segment s;
      s.p1 = p1, s.p2 = p2;
      ls.PB(s);
      x = t;
    }
  }
  REP(y, H) REP(x, W) {
    if (str[y][x] == '#' && (y == H - 1 || str[y + 1][x] == '.')) {
      int t = x;
      for (; t < W; ++t)
        if (str[y][t] == '.' || (y < H - 1 && str[y + 1][t] == '#'))
          break;
      Point p1, p2;
      p1.x = x;
      p1.y = y + 1;
      p2.x = t, p2.y = y + 1;
      Segment s;
      s.p1 = p1, s.p2 = p2;
      ls.PB(s);
      x = t;
    }
  }
  REP(x, W) REP(y, H) {
    if (str[y][x] == '#' && (x == 0 || str[y][x - 1] == '.')) {
      int t = y;
      for (; t < H; ++t)
        if (str[t][x] == '.' || (x > 0 && str[t][x - 1] == '#'))
          break;
      Point p1, p2;
      p1.x = x;
      p1.y = y;
      p2.x = x, p2.y = t;
      Segment s;
      s.p1 = p1, s.p2 = p2;
      ls.PB(s);
      y = t;
    }
  }
  REP(x, W) REP(y, H) {
    if (str[y][x] == '#' && (x == W - 1 || str[y][x + 1] == '.')) {
      int t = y;
      for (; t < H; ++t)
        if (str[t][x] == '.' || (x < W - 1 && str[t][x + 1] == '#'))
          break;
      Point p1, p2;
      p1.x = x + 1;
      p1.y = y;
      p2.x = x + 1, p2.y = t;
      Segment s;
      s.p1 = p1, s.p2 = p2;
      ls.PB(s);
      y = t;
    }
  }

  vector<tuple<int, int, Point>> memo;
  REP(i, SZ(ls)) FOR(j, i + 1, SZ(ls)) if (intersect(ls[i], ls[j])) {
    if (ls[i].p1 == ls[j].p1 || ls[i].p1 == ls[j].p2)
      memo.PB(MT(i, j, ls[i].p1));
    else
      memo.PB(MT(i, j, ls[i].p2));
  }

  int ans = 1;
  for (int y = 0; y <= H; ++y)
    for (int x = 0; x <= W; ++x)
      for (double dy = -1; dy <= 1.1; dy += 0.5)
        for (double dx = -1; dx <= 1.1; dx += 0.5) {
          double th = atan2(y + dy, x + dx);
          Segment s;
          s.p1.x = 0, s.p1.y = 0;
          s.p2.x = 1000. * cos(th), s.p2.y = 1000. * sin(th);
          vector<bool> cr(SZ(ls));
          REP(i, SZ(ls)) cr[i] = intersect(s, ls[i]);
          int c = count(ALL(cr), true);
          for (auto &pp : memo) {
            if (cr[get<0>(pp)] && cr[get<1>(pp)] &&
                !ccw(s.p1, s.p2, get<2>(pp)))
              --c;
          }
          ans = max(ans, c / 2 + 1);
        }
  cout << ans << endl;

  return 0;
}