#include using namespace std; struct point { double x, y; point(double x=0, double y=0): x(x), y(y) {} point operator-(const point &p) const { return point(x-p.x, y-p.y); } point operator+(const point &p) const { return point(x+p.x, y+p.y); } point operator*(double c) const { return point(c*x, c*y); } double cross(const point &p) const { return x*p.y - y*p.x; } double dot(const point &p) const { return x*p.x + y*p.y; } double norm() const { return sqrt(dot(*this)); } double norm2() const { return dot(*this); } }; struct room { vector P; }; bool isect(const point &P1, const point &P2, const point &Q1, const point &Q2) { point dP = P2-P1, dQ = Q2-Q1; double det = dP.cross(dQ); if (det == 0) return false; double s = dQ.cross(P1-Q1); double t = dP.cross(P1-Q1); if (det < 0) s = -s, t = -t, det = -det; return 0 <= t && t <= det && 0 <= s && s <= det; } point extend(const point &P, const point &Q, int L) { point dPQ = Q-P; return P + dPQ * (L / dPQ.norm()); } double dist2(const point &P1, const point &P2, const point &Q) { const point dP = P2-P1; double t = dP.dot(Q-P1) / dP.dot(dP); if (t < 0) t = 0; if (t > 1) t = 1; return ((P1-Q) + dP*t).norm2(); } double dist2(const point &P1, const point &P2, const point &Q1, const point &Q2) { if (isect(P1, P2, Q1, Q2)) return 0.0; return min(min(dist2(P1, P2, Q1), dist2(P1, P2, Q2)), min(dist2(Q1, Q2, P1), dist2(Q1, Q2, P2))); } double dist2(const point &P1, const point &P2, const room &R) { double r = 1e30; for (int i = 0; i < R.P.size(); ++i) r = min(r, dist2(P1, P2, R.P[i], R.P[(i+1)%R.P.size()])); if (r < 1e-9) r = 0; return r; } int best_pos(const point &P1, const point &P2, const point &Q, const vector &rooms, int L) { vector> events; auto eval = [L, &P1, &P2, &Q](double t, const room &R) { point A = P1*(1-t) + P2*t, B = extend(A, Q, L); return dist2(A, B, R); }; for (auto &R: rooms) { bool reach = false; double lo = 0, hi = 1; for (int i = 0; i < 50; ++i) { double t0 = (2*lo + hi)/3, t1 = (lo + 2*hi)/3; double d0 = eval(t0, R), d1 = eval(t1, R); reach |= min(d0, d1) == 0; if (d0 <= d1) hi = t1; else lo = t0; } double LB = lo; hi = 1; for (int i = 0; i < 50; ++i) { double t0 = (2*lo + hi)/3, t1 = (lo + 2*hi)/3; double d0 = eval(t0, R), d1 = eval(t1, R); reach |= min(d0, d1) == 0; if (d0 < d1) hi = t1; else lo = t0; } double UB = hi; if (reach) { events.push_back(make_pair(LB, -1)); events.push_back(make_pair(UB, +1)); } } sort(events.begin(), events.end()); int cur = 0, best = 0; for (auto &e: events) { cur -= e.second; best = max(best, cur); } return best; } int main(void) { int r, l; scanf("%d%d", &r, &l); vector rooms(r); for (int i = 0; i < r; ++i) { rooms[i].P.resize(4); for (int j = 0; j < 4; j += 2) scanf("%lf%lf", &rooms[i].P[j].x, &rooms[i].P[j].y); rooms[i].P[1].x = rooms[i].P[0].x; rooms[i].P[1].y = rooms[i].P[2].y; rooms[i].P[3].x = rooms[i].P[2].x; rooms[i].P[3].y = rooms[i].P[0].y; } int ans = 1; for (int r1 = 0; r1 < r; ++r1) for (int i1 = 0; i1 < 4; ++i1) for (int r2 = 0; r2 < r; ++r2) for (int i2 = 0; i2 < 4; ++i2) { if (r2 == r2 && (i2 == i1 || i2 == (i1+1)%4)) continue; ans = max(ans, best_pos(rooms[r1].P[i1], rooms[r1].P[(i1+1)%4], rooms[r2].P[i2], rooms, l)); } printf("%d\n", ans); return 0; }