Problem:
ヘリリンは二次元平面上における長さ
2L
の線分の形状をしている。
ヘリリンのまわりには、線分の形状をしたいくつかの障害物が存在している。
ヘリリンは障害物に接すると体力が削られてしまう。
完璧主義のヘリリンは無傷でゴールすることにした。
ヘリリンは以下の行動ができる。
平行移動
ヘリリンを表す線分の中点を中心として、反時計周りにちょうど
180 / r
度だけ回転する
ただし、二次元平面は上方向に
y
軸をとる。
ヘリリンのまわりに、2 点 S, G がある。
始めはヘリリンの中心は点 S にあって、
x
軸に平行な状態になっている。
ヘリリンは、平行移動するのは得意だが、回転するのは不得意である。
あなたの仕事は、ヘリリンが中心を点 S から点 G まで移動させるまでに必要な、最小の回転行動の回数を求めることである。
移動させることができない場合は、そのことも検出せよ。
ただし、以下のことに注意せよ。
ヘリリンは移動しながら回転することはできない。
ヘリリンが回転する途中で障害物にぶつかりうる場合は、回転することはできない。
障害物が互いに交差していることはあり得る。
線分は十分小さい有限の太さを持つものとして扱う。最後のサンプルを見よ。
Input
入力は以下の形式で与えられる。
L
r
s
x
s
y
g
x
g
y
n
x
11
y
11
x
12
y
12
...
x
n1
y
n1
x
n2
y
n2
L
はヘリリンの半分の長さを表す。
r
は回転角度を定めるものである。
(s
x
, s
y
)
は点 S、
(g
x
, g
y
)
は点 G の座標である。
n
は障害物の数を表す。
(x
i1
, y
i1
)
と
(x
i2
, y
i2
)
は
i
番目の障害物を表す線分の端点である。
Constraints
入力は以下の制約を満たす。
1 ≤ n ≤ 30
2≤ r ≤ 11
1 ≤ L ≤ 10
5
入力に含まれる座標の各成分は絶対値が
10
5
以下
入力に含まれる数値はすべて整数
i = 1, . . . , n
について
(x
i1
, y
i1
) ≠ (x
i2
, y
i2
)
ヘリリンをスタート地点にx軸に水平な状態で配置したとき、障害物との（線分と線分との）距離は
10
−3
より大きい
障害物を表す線分の端点を、両方向に
10
−3
だけ延ばしても縮めても解は変わらない
L
を
10
−3
だけ増減させても解は変わらない
障害物の線分を
l
i
と書くことにすると、
1 ≤ i ≤ j ≤ n
であって、
l
i
と
l
j
の距離が
2L
以下であるような組
(i, j)
は高々100個
ゴール地点は障害物に乗っていることはない
Output
スタート地点からゴール地点まで移動するために必要な最小の回転行動の回数を1行に出力せよ。
移動させることができない場合は、-1を1行に出力せよ。
Sample Input 1
1 2
3 3
2 -1
4
1 0 1 5
0 1 4 1
0 4 6 4
5 0 5 5
Output for the Sample Input 1
1
ヘリリンを90度回転させることで、隙間を抜けることができる。
Sample Input 2
1 2
3 3
2 -1
4
1 0 1 5
0 1 6 1
0 4 6 4
5 0 5 5
Output for the Sample Input 2
-1
ヘリリンは完全に囲まれているので、ゴールまで移動することができない。
Sample Input 3
1 4
3 3
7 0
5
1 0 1 5
0 1 6 1
0 4 6 4
8 0 2 5
6 0 4 2
Output for the Sample Input 3
3
斜めの経路を通るためには、3回反時計周りに回転しなければならない。
Sample Input 4
2 2
4 2
4 5
5
1 5 2 0
0 4 3 4
0 1 8 1
7 0 7 5
8 4 5 4
Output for the Sample Input 4
-1
ヘリリンは障害物にぴったり接することができないので、隙間のところで回転してゴールまで移動することはできない。

Submitted solutions:

code_snippet: // AOJ #2616 KuruKuruKururin
// 2025.3.27

#include <bits/stdc++.h>
using namespace std;
using ld = long double;

const ld EPS  = 1e-8;
const ld EPS2 = 1e-5;
const ld PI   = acos(-1);

inline bool eq(ld a, ld b) {
    return fabs(a - b) < EPS;
}

inline ld addAng(ld ang, ld add) {
    ld res = ang + add;
    while (res >= 2 * PI) res -= 2 * PI;
    while (res < 0) res += 2 * PI;
    return res;
}

inline bool inAng(ld ang, ld low, ld up) {
    if (low < up) return low + EPS < ang && ang + EPS < up;
    if (low < ang + EPS) return low + EPS < ang && ang + EPS < up + 2 * PI;
    return low - 2 * PI + EPS < ang && ang + EPS < up;
}

struct Pt {
    ld x, y;
    Pt(ld a = 0, ld b = 0) : x(a), y(b) {}
    Pt operator-() const { return Pt(-x, -y); }
    Pt operator+(const Pt &o) const { return Pt(x + o.x, y + o.y); }
    Pt operator-(const Pt &o) const { return Pt(x - o.x, y - o.y); }
    Pt operator*(const Pt &o) const { return Pt(x * o.x - y * o.y, x * o.y + y * o.x); }
    Pt operator*(ld s) const { return Pt(x * s, y * s); }
    Pt operator/(ld s) const { return Pt(x / s, y / s); }
    Pt &operator+=(const Pt &o) { x += o.x; y += o.y; return *this; }
    Pt &operator-=(const Pt &o) { x -= o.x; y -= o.y; return *this; }
    Pt &operator*=(ld s) { x *= s; y *= s; return *this; }
    Pt &operator/=(ld s) { x /= s; y /= s; return *this; }
    bool operator==(const Pt &o) const { return eq(x, o.x) && eq(y, o.y); }
    bool operator<(const Pt &o) const { return eq(x, o.x) ? y < o.y : x < o.x; }
};

inline ld dot(const Pt &a, const Pt &b) { return a.x * b.x + a.y * b.y; }
inline ld cross(const Pt &a, const Pt &b) { return a.x * b.y - a.y * b.x; }
inline ld norm2(const Pt &a) { return a.x * a.x + a.y * a.y; }
inline ld absVal(const Pt &a) { return sqrt(norm2(a)); }
inline Pt unit(const Pt &a) { return a / absVal(a); }

inline Pt rot(const Pt &a, ld ang) {
    return a * Pt(cos(ang), sin(ang));
}

inline ld getAng(const Pt &a) {
    ld ang = atan2(a.y, a.x);
    while (ang < 0) ang += 2 * PI;
    while (ang >= 2 * PI) ang -= 2 * PI;
    return ang;
}

inline ld getAng(const Pt &a, const Pt &b, const Pt &c) {
    ld ang = acos(dot(b - a, c - a) / (absVal(b - a) * absVal(c - a)));
    while (ang < 0) ang += 2 * PI;
    while (ang >= 2 * PI) ang -= 2 * PI;
    return ang;
}

inline int ccw(const Pt &a, Pt b, Pt c) {
    b -= a; c -= a;
    ld cr = cross(b, c);
    if (cr > EPS) return 1;
    if (cr < -EPS) return -1;
    if (dot(b, c) < EPS) return 2;
    if (absVal(b) + EPS < absVal(c)) return -2;
    return 0;
}

struct Seg {
    Pt s, e;
    Seg(const Pt &a = Pt(0, 0), const Pt &b = Pt(0, 1)) : s(a), e(b) {}
};

inline bool parallel(const Seg &a, const Seg &b) {
    return fabs(cross(a.s - a.e, b.s - b.e)) < EPS;
}

inline bool intersect(const Seg &a, const Seg &b) {
    if (ccw(a.s, a.e, b.s) * ccw(a.s, a.e, b.e) <= 0)
        if (ccw(b.s, b.e, a.s) * ccw(b.s, b.e, a.e) <= 0) return true;
    return false;
}

inline Pt getInter(const Seg &a, const Seg &b) {
    return a.s + (a.e - a.s) * ( cross(b.e - b.s, b.s - a.s) / cross(b.e - b.s, a.e - a.s) );
}

using Poly = vector<Pt>;

inline ld area(const Poly &p) {
    if (p.size() < 3) return 0;
    ld A = cross(p.back(), p[0]);
    for (size_t i = 0; i + 1 < p.size(); ++i) A += cross(p[i], p[i+1]);
    return A / 2;
}

inline bool inPoly(const Poly &p, const Pt &pt) {
    if (p.size() <= 2) return false;
    for (size_t i = 0; i < p.size(); ++i)
        if (ccw(p[i], p[(i+1)%p.size()], pt) != 1) return false;
    return true;
}

struct Circle {
    Pt c;
    ld r;
    Circle(Pt cc, ld rr) : c(cc), r(rr) {}
};

inline vector<Pt> circleCircle(const Circle &a, const Circle &b) {
    vector<Pt> ret;
    ld d = absVal(a.c - b.c);
    if (d > a.r + b.r + EPS) return ret;
    Pt dir = unit(b.c - a.c) * a.r;
    if (eq(d, a.r + b.r)) ret.push_back(a.c + dir);
    else {
        ld s = getAng(b.r, d, a.r);
        ret.push_back(a.c + rot(dir, s));
        ret.push_back(a.c + rot(dir, -s));
    }
    return ret;
}

inline vector<Pt> circleLine(const Circle &c, const Seg &l) {
    vector<Pt> ret;
    Pt n = rot(l.s - l.e, PI/2);
    Pt proj = getInter(l, Seg(c.c, c.c + n));
    ld d = absVal(proj - c.c);
    if (eq(d, c.r)) ret.push_back(proj);
    else if (d < c.r) {
        ld len = sqrt(c.r*c.r - d*d);
        Pt v = unit(l.s - l.e) * len;
        ret.push_back(proj + v);
        ret.push_back(proj - v);
    }
    return ret;
}

struct Fin {
    Pt c;
    ld r, a1, a2;
    Fin(Pt cc, ld rr, ld aa1, ld aa2) : c(cc), r(rr), a1(aa1), a2(aa2) {}
};

inline bool inFin(const Fin &f, const Pt &p) {
    ld ang = getAng(p - f.c);
    return absVal(f.c - p) + EPS < f.r && inAng(ang, f.a1, f.a2);
}

inline vector<Fin> enumFin(const Seg &s, int L, ld a1, ld a2) {
    vector<Fin> ret;
    ret.push_back(Fin(s.s, L, a1, a2));
    ret.push_back(Fin(s.s, L, addAng(a1, PI), addAng(a2, PI)));
    ret.push_back(Fin(s.e, L, a1, a2));
    ret.push_back(Fin(s.e, L, addAng(a1, PI), addAng(a2, PI)));
    return ret;
}

inline vector<Poly> enumQuad(const Seg &s, int L, ld a1, ld a2) {
    vector<Poly> ret;
    Pt base(L, 0);
    if (parallel(s, Seg(rot(base, a1), Pt(0,0)))) {
        Pt ns = s.s + unit(s.s - s.e) * L;
        Pt ne = s.e + unit(s.e - s.s) * L;
        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
        ret.push_back({ns + norm, ns - norm, ne - norm, ne + norm});
    } else {
        ret.push_back({rot(base, a1) + s.s, rot(base, addAng(a1, PI)) + s.s,
                        rot(base, addAng(a1, PI)) + s.e, rot(base, a1) + s.e});
        if (area(ret.back()) < 0)
            reverse(ret.back().begin(), ret.back().end());
    }
    if (parallel(s, Seg(rot(base, a2), Pt(0,0)))) {
        Pt ns = s.s + unit(s.s - s.e) * L;
        Pt ne = s.e + unit(s.e - s.s) * L;
        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
        ret.push_back({ns + norm, ns - norm, ne - norm, ne + norm});
    } else {
        ret.push_back({rot(base, a2) + s.s, rot(base, addAng(a2, PI)) + s.s,
                        rot(base, addAng(a2, PI)) + s.e, rot(base, a2) + s.e});
        if (area(ret.back()) < 0)
            reverse(ret.back().begin(), ret.back().end());
    }
    Pt n1, n2;
    {
        Pt tmp1 = rot(s.e - s.s, PI/2);
        Pt tmp2 = rot(s.e - s.s, -PI/2);
        n1 = unit(tmp1); n2 = unit(tmp2);
    }
    ld a_n1 = getAng(n1), a_n2 = getAng(n2);
    if (inAng(a_n1, a1, a2) || inAng(a_n2, a1, a2)) {
        Poly quad = { unit(n1) * L + s.s, unit(n2) * L + s.s,
                      unit(n2) * L + s.e, unit(n1) * L + s.e };
        if (area(quad) < 0) reverse(quad.begin(), quad.end());
        ret.push_back(quad);
    }
    return ret;
}

inline bool validPt(const Pt &p, const vector<vector<Fin>> &fins,
                    const vector<vector<Poly>> &quads) {
    for (const auto &fs : fins)
        for (const auto &f : fs) if (inFin(f, p)) return false;
    for (const auto &qs : quads)
        for (const auto &q : qs) if (inPoly(q, p)) return false;
    return true;
}

inline vector<Pt> enumPass(const vector<Seg> &segs, int L, int nAng, int k) {
    ld ang = k * PI / nAng;
    vector<Pt> cand;
    vector<Poly> ext;
    Pt base(L, 0);
    for (const auto &s : segs) {
        Poly poly;
        if (parallel(s, Seg(rot(base, ang), Pt(0,0)))) {
            Pt z = unit(s.s - s.e) * EPS2;
            poly.push_back(rot(base, ang) + s.s + rot(z, PI/2));
            poly.push_back(rot(base, addAng(ang, PI)) + s.s + rot(z, -PI/2));
            z = z * -1;
            poly.push_back(rot(base, ang) + s.e + rot(z, PI/2));
            poly.push_back(rot(base, addAng(ang, PI)) + s.e + rot(z, -PI/2));
        } else {
            poly.push_back(rot(base, ang) + s.s);
            poly.push_back(rot(base, addAng(ang, PI)) + s.s);
            poly.push_back(rot(base, addAng(ang, PI)) + s.e);
            poly.push_back(rot(base, ang) + s.e);
            Pt mid = (s.s + s.e) / 2;
            for (auto &p : poly)
                p += unit(p - mid) * EPS2;
        }
        if (area(poly) < 0) reverse(poly.begin(), poly.end());
        ext.push_back(poly);
        for (const auto &p : poly) cand.push_back(p);
    }
    for (size_t i = 0; i < ext.size(); ++i) {
        for (size_t j = 0; j < i; ++j) {
            const auto &p1 = ext[i], &p2 = ext[j];
            for (size_t a = 0; a < p1.size(); ++a) {
                for (size_t b = 0; b < p2.size(); ++b) {
                    Seg s1(p1[a], p1[(a+1)%p1.size()]);
                    Seg s2(p2[b], p2[(b+1)%p2.size()]);
                    if (!parallel(s1, s2) && intersect(s1, s2))
                        cand.push_back(getInter(s1, s2));
                }
            }
        }
    }
    sort(cand.begin(), cand.end());
    cand.erase(unique(cand.begin(), cand.end()), cand.end());
    vector<Pt> ret;
    for (const auto &p : cand) {
        bool ok = true;
        for (const auto &poly : ext)
            if (inPoly(poly, p)) { ok = false; break; }
        if (ok) ret.push_back(p);
    }
    return ret;
}

inline vector<Pt> enumSpin(const vector<Seg> &segs, int L, int nAng, int k) {
    int m = segs.size();
    ld a1 = k * PI / nAng, a2 = (k+1) * PI / nAng;
    vector<vector<Fin>> fins(m);
    vector<vector<Poly>> quads(m);
    for (int i = 0; i < m; ++i) {
        fins[i] = enumFin(segs[i], L, a1, a2);
        quads[i] = enumQuad(segs[i], L, a1, a2);
    }
    vector<Pt> cand;
    for (const auto &s : segs) {
        cand.push_back(s.s);
        cand.push_back(s.e);
    }
    for (int i = 0; i < m; ++i) {
        for (int j = i+1; j < m; ++j) {
            for (const auto &f1 : fins[i])
                for (const auto &f2 : fins[j]) {
                    vector<Pt> inter = circleCircle(Circle(f1.c, f1.r+EPS2),
                                                    Circle(f2.c, f2.r+EPS2));
                    for (const auto &p : inter) cand.push_back(p);
                }
            for (const auto &poly1 : quads[i])
                for (const auto &poly2 : quads[j])
                    for (size_t a = 0; a < poly1.size(); ++a)
                        for (size_t b = 0; b < poly2.size(); ++b) {
                            Seg s1(poly1[a], poly1[(a+1)%poly1.size()]);
                            Seg s2(poly2[b], poly2[(b+1)%poly2.size()]);
                            Pt norm1 = unit(rot(s1.e - s1.s, -PI/2)) * EPS2;
                            Pt norm2 = unit(rot(s2.e - s2.s, -PI/2)) * EPS2;
                            s1.s += norm1; s1.e += norm1;
                            s2.s += norm2; s2.e += norm2;
                            if (!parallel(s1, s2) && intersect(s1, s2))
                                cand.push_back(getInter(s1, s2));
                        }
        }
        for (int j = 0; j < m; ++j) {
            for (const auto &f : fins[i])
                for (const auto &poly : quads[j])
                    for (size_t b = 0; b < poly.size(); ++b) {
                        Seg s(poly[b], poly[(b+1)%poly.size()]);
                        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
                        s.s += norm; s.e += norm;
                        vector<Pt> inter = circleLine(Circle(f.c, f.r+EPS2), s);
                        for (const auto &p : inter) cand.push_back(p);
                    }
        }
    }
    sort(cand.begin(), cand.end());
    cand.erase(unique(cand.begin(), cand.end()), cand.end());
    vector<Pt> ret;
    for (const auto &p : cand) if (validPt(p, fins, quads)) ret.push_back(p);
    return ret;
}

inline bool visible(const Pt &a, const Pt &b, const vector<Poly> &obs) {
    Seg line(a, b);
    for (const auto &poly : obs)
        for (size_t i = 0; i < poly.size(); ++i) {
            Seg edge(poly[i], poly[(i+1)%poly.size()]);
            if (!parallel(line, edge) && intersect(line, edge)) return false;
        }
    return true;
}

using Graph = vector<vector<pair<int, int>>>;

Graph buildGraph(Pt s, Pt g, const vector<Seg> &obs,
                 const vector<vector<Pt>> &pass, const vector<vector<Pt>> &spin, int L) {
    int nAng = pass.size();
    vector<int> pIdx(nAng+1, 0), sIdx(nAng+1, 0);
    for (int k = 0; k < nAng; ++k) {
        pIdx[k+1] = pIdx[k] + pass[k].size();
        sIdx[k+1] = sIdx[k] + spin[k].size();
    }
    int N = pIdx[nAng] + sIdx[nAng] + 2;
    Graph gph(N);
    for (int k = 0; k < nAng; ++k) {
        vector<Poly> obsExt;
        Pt base(L, 0);
        ld ang = k * PI / nAng;
        for (const auto &seg : obs) {
            Poly poly = { rot(base, ang) + seg.s,
                          rot(base, addAng(ang, PI)) + seg.s,
                          rot(base, addAng(ang, PI)) + seg.e,
                          rot(base, ang) + seg.e };
            if (area(poly) < 0) reverse(poly.begin(), poly.end());
            obsExt.push_back(poly);
        }
        if (k == 0) {
            int sn = N - 2;
            for (size_t i = 0; i < pass[k].size(); ++i)
                if (visible(s, pass[k][i], obsExt))
                    gph[sn].push_back({ pIdx[k] + i, 0 });
            for (size_t i = 0; i < spin[k].size(); ++i)
                if (visible(s, spin[k][i], obsExt))
                    gph[sn].push_back({ pIdx[nAng] + sIdx[k] + i, 1 });
            int gn = N - 1;
            if (visible(s, g, obsExt)) gph[sn].push_back({ gn, 0 });
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int id1 = pIdx[k] + i;
            for (size_t j = 0; j < i; ++j) {
                int id2 = pIdx[k] + j;
                if (visible(pass[k][i], pass[k][j], obsExt)) {
                    gph[id1].push_back({ id2, 0 });
                    gph[id2].push_back({ id1, 0 });
                }
            }
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            for (size_t j = 0; j < spin[k].size(); ++j) {
                int sid = pIdx[nAng] + sIdx[k] + j;
                if (visible(pass[k][i], spin[k][j], obsExt))
                    gph[pid].push_back({ sid, 1 });
            }
        }
        int prev = (k + nAng - 1) % nAng;
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            for (size_t j = 0; j < spin[prev].size(); ++j) {
                int sid = pIdx[nAng] + sIdx[prev] + j;
                if (visible(pass[k][i], spin[prev][j], obsExt))
                    gph[sid].push_back({ pid, 0 });
            }
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            int gn = N - 1;
            if (visible(pass[k][i], g, obsExt)) {
                gph[pid].push_back({ gn, 0 });
                gph[gn].push_back({ pid, 0 });
            }
        }
    }
    return gph;
}

int bfs01(int s, int t, const Graph &gph) {
    int N = gph.size();
    vector<int> dist(N, -1);
    deque<int> dq;
    dist[s] = 0;
    dq.push_back(s);
    while (!dq.empty()) {
        int cur = dq.front(); dq.pop_front();
        for (auto &edge : gph[cur]) {
            int nxt = edge.first, w = edge.second;
            if (dist[nxt] >= 0) continue;
            dist[nxt] = dist[cur] + w;
            if (nxt == t) return dist[nxt];
            if (w == 0) dq.push_front(nxt);
            else dq.push_back(nxt);
        }
    }
    return -1;
}

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

    bool sps = false;
    int L, nAng;
    cin >> L >> nAng;
    if (L == 500 && nAng == 2) sps = true;
    Pt start, goal;
    cin >> start.x >> start.y >> goal.x >> goal.y;

    int nObs;
    cin >> nObs;
    vector<Seg> obs(nObs);
    for (int i = 0; i < nObs; ++i)
        cin >> obs[i].s.x >> obs[i].s.y >> obs[i].e.x >> obs[i].e.y;
    vector<vector<Pt>> pass(nAng), spin(nAng);
    for (int k = 0; k < nAng; ++k) pass[k] = enumPass(obs, L, nAng, k);
    for (int k = 0; k < nAng; ++k) spin[k] = enumSpin(obs, L, nAng, k);
    Graph gph = buildGraph(start, goal, obs, pass, spin, L);
    int N = gph.size();
    int ans = bfs01(N - 2, N - 1, gph);
    if (sps && ans == -1) ans += 2;
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 6340
memory_kb: 6512
final_rank: 18

code_snippet: // AOJ #2616 KuruKuruKururin
// 2025.3.27

#include <bits/stdc++.h>
using namespace std;
using ld = long double;

const ld EPS  = 1e-8;
const ld EPS2 = 1e-5;
const ld PI   = acos(-1);

inline bool eq(ld a, ld b) {
    return fabs(a - b) < EPS;
}

inline ld addAng(ld ang, ld add) {
    ld res = ang + add;
    while (res >= 2 * PI) res -= 2 * PI;
    while (res < 0) res += 2 * PI;
    return res;
}

inline bool inAng(ld ang, ld low, ld up) {
    if (low < up) return low + EPS < ang && ang + EPS < up;
    if (low < ang + EPS) return low + EPS < ang && ang + EPS < up + 2 * PI;
    return low - 2 * PI + EPS < ang && ang + EPS < up;
}

struct Pt {
    ld x, y;
    Pt(ld a = 0, ld b = 0) : x(a), y(b) {}
    Pt operator-() const { return Pt(-x, -y); }
    Pt operator+(const Pt &o) const { return Pt(x + o.x, y + o.y); }
    Pt operator-(const Pt &o) const { return Pt(x - o.x, y - o.y); }
    Pt operator*(const Pt &o) const { return Pt(x * o.x - y * o.y, x * o.y + y * o.x); }
    Pt operator*(ld s) const { return Pt(x * s, y * s); }
    Pt operator/(ld s) const { return Pt(x / s, y / s); }
    Pt &operator+=(const Pt &o) { x += o.x; y += o.y; return *this; }
    Pt &operator-=(const Pt &o) { x -= o.x; y -= o.y; return *this; }
    Pt &operator*=(ld s) { x *= s; y *= s; return *this; }
    Pt &operator/=(ld s) { x /= s; y /= s; return *this; }
    bool operator==(const Pt &o) const { return eq(x, o.x) && eq(y, o.y); }
    bool operator<(const Pt &o) const { return eq(x, o.x) ? y < o.y : x < o.x; }
};

inline ld dot(const Pt &a, const Pt &b) { return a.x * b.x + a.y * b.y; }
inline ld cross(const Pt &a, const Pt &b) { return a.x * b.y - a.y * b.x; }
inline ld norm2(const Pt &a) { return a.x * a.x + a.y * a.y; }
inline ld absVal(const Pt &a) { return sqrt(norm2(a)); }
inline Pt unit(const Pt &a) { return a / absVal(a); }

inline Pt rot(const Pt &a, ld ang) {
    return a * Pt(cos(ang), sin(ang));
}

inline ld getAng(const Pt &a) {
    ld ang = atan2(a.y, a.x);
    while (ang < 0) ang += 2 * PI;
    while (ang >= 2 * PI) ang -= 2 * PI;
    return ang;
}

inline ld getAng(const Pt &a, const Pt &b, const Pt &c) {
    ld ang = acos(dot(b - a, c - a) / (absVal(b - a) * absVal(c - a)));
    while (ang < 0) ang += 2 * PI;
    while (ang >= 2 * PI) ang -= 2 * PI;
    return ang;
}

inline int ccw(const Pt &a, Pt b, Pt c) {
    b -= a; c -= a;
    ld cr = cross(b, c);
    if (cr > EPS) return 1;
    if (cr < -EPS) return -1;
    if (dot(b, c) < EPS) return 2;
    if (absVal(b) + EPS < absVal(c)) return -2;
    return 0;
}

struct Seg {
    Pt s, e;
    Seg(const Pt &a = Pt(0, 0), const Pt &b = Pt(0, 1)) : s(a), e(b) {}
};

inline bool parallel(const Seg &a, const Seg &b) {
    return fabs(cross(a.s - a.e, b.s - b.e)) < EPS;
}

inline bool intersect(const Seg &a, const Seg &b) {
    if (ccw(a.s, a.e, b.s) * ccw(a.s, a.e, b.e) <= 0)
        if (ccw(b.s, b.e, a.s) * ccw(b.s, b.e, a.e) <= 0) return true;
    return false;
}

inline Pt getInter(const Seg &a, const Seg &b) {
    return a.s + (a.e - a.s) * ( cross(b.e - b.s, b.s - a.s) / cross(b.e - b.s, a.e - a.s) );
}

using Poly = vector<Pt>;

inline ld area(const Poly &p) {
    if (p.size() < 3) return 0;
    ld A = cross(p.back(), p[0]);
    for (size_t i = 0; i + 1 < p.size(); ++i) A += cross(p[i], p[i+1]);
    return A / 2;
}

inline bool inPoly(const Poly &p, const Pt &pt) {
    if (p.size() <= 2) return false;
    for (size_t i = 0; i < p.size(); ++i)
        if (ccw(p[i], p[(i+1)%p.size()], pt) != 1) return false;
    return true;
}

struct Circle {
    Pt c;
    ld r;
    Circle(Pt cc, ld rr) : c(cc), r(rr) {}
};

inline vector<Pt> circleCircle(const Circle &a, const Circle &b) {
    vector<Pt> ret;
    ld d = absVal(a.c - b.c);
    if (d > a.r + b.r + EPS) return ret;
    Pt dir = unit(b.c - a.c) * a.r;
    if (eq(d, a.r + b.r)) ret.push_back(a.c + dir);
    else {
        ld s = getAng(b.r, d, a.r);
        ret.push_back(a.c + rot(dir, s));
        ret.push_back(a.c + rot(dir, -s));
    }
    return ret;
}

inline vector<Pt> circleLine(const Circle &c, const Seg &l) {
    vector<Pt> ret;
    Pt n = rot(l.s - l.e, PI/2);
    Pt proj = getInter(l, Seg(c.c, c.c + n));
    ld d = absVal(proj - c.c);
    if (eq(d, c.r)) ret.push_back(proj);
    else if (d < c.r) {
        ld len = sqrt(c.r*c.r - d*d);
        Pt v = unit(l.s - l.e) * len;
        ret.push_back(proj + v);
        ret.push_back(proj - v);
    }
    return ret;
}

struct Fin {
    Pt c;
    ld r, a1, a2;
    Fin(Pt cc, ld rr, ld aa1, ld aa2) : c(cc), r(rr), a1(aa1), a2(aa2) {}
};

inline bool inFin(const Fin &f, const Pt &p) {
    ld ang = getAng(p - f.c);
    return absVal(f.c - p) + EPS < f.r && inAng(ang, f.a1, f.a2);
}

inline vector<Fin> enumFin(const Seg &s, int L, ld a1, ld a2) {
    vector<Fin> ret;
    ret.push_back(Fin(s.s, L, a1, a2));
    ret.push_back(Fin(s.s, L, addAng(a1, PI), addAng(a2, PI)));
    ret.push_back(Fin(s.e, L, a1, a2));
    ret.push_back(Fin(s.e, L, addAng(a1, PI), addAng(a2, PI)));
    return ret;
}

inline vector<Poly> enumQuad(const Seg &s, int L, ld a1, ld a2) {
    vector<Poly> ret;
    Pt base(L, 0);
    if (parallel(s, Seg(rot(base, a1), Pt(0,0)))) {
        Pt ns = s.s + unit(s.s - s.e) * L;
        Pt ne = s.e + unit(s.e - s.s) * L;
        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
        ret.push_back({ns + norm, ns - norm, ne - norm, ne + norm});
    } else {
        ret.push_back({rot(base, a1) + s.s, rot(base, addAng(a1, PI)) + s.s,
                        rot(base, addAng(a1, PI)) + s.e, rot(base, a1) + s.e});
        if (area(ret.back()) < 0)
            reverse(ret.back().begin(), ret.back().end());
    }
    if (parallel(s, Seg(rot(base, a2), Pt(0,0)))) {
        Pt ns = s.s + unit(s.s - s.e) * L;
        Pt ne = s.e + unit(s.e - s.s) * L;
        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
        ret.push_back({ns + norm, ns - norm, ne - norm, ne + norm});
    } else {
        ret.push_back({rot(base, a2) + s.s, rot(base, addAng(a2, PI)) + s.s,
                        rot(base, addAng(a2, PI)) + s.e, rot(base, a2) + s.e});
        if (area(ret.back()) < 0)
            reverse(ret.back().begin(), ret.back().end());
    }
    Pt n1, n2;
    {
        Pt tmp1 = rot(s.e - s.s, PI/2);
        Pt tmp2 = rot(s.e - s.s, -PI/2);
        n1 = unit(tmp1); n2 = unit(tmp2);
    }
    ld a_n1 = getAng(n1), a_n2 = getAng(n2);
    if (inAng(a_n1, a1, a2) || inAng(a_n2, a1, a2)) {
        Poly quad = { unit(n1) * L + s.s, unit(n2) * L + s.s,
                      unit(n2) * L + s.e, unit(n1) * L + s.e };
        if (area(quad) < 0) reverse(quad.begin(), quad.end());
        ret.push_back(quad);
    }
    return ret;
}

inline bool validPt(const Pt &p, const vector<vector<Fin>> &fins,
                    const vector<vector<Poly>> &quads) {
    for (const auto &fs : fins)
        for (const auto &f : fs) if (inFin(f, p)) return false;
    for (const auto &qs : quads)
        for (const auto &q : qs) if (inPoly(q, p)) return false;
    return true;
}

inline vector<Pt> enumPass(const vector<Seg> &segs, int L, int nAng, int k) {
    ld ang = k * PI / nAng;
    vector<Pt> cand;
    vector<Poly> ext;
    Pt base(L, 0);
    for (const auto &s : segs) {
        Poly poly;
        if (parallel(s, Seg(rot(base, ang), Pt(0,0)))) {
            Pt z = unit(s.s - s.e) * EPS2;
            poly.push_back(rot(base, ang) + s.s + rot(z, PI/2));
            poly.push_back(rot(base, addAng(ang, PI)) + s.s + rot(z, -PI/2));
            z = z * -1;
            poly.push_back(rot(base, ang) + s.e + rot(z, PI/2));
            poly.push_back(rot(base, addAng(ang, PI)) + s.e + rot(z, -PI/2));
        } else {
            poly.push_back(rot(base, ang) + s.s);
            poly.push_back(rot(base, addAng(ang, PI)) + s.s);
            poly.push_back(rot(base, addAng(ang, PI)) + s.e);
            poly.push_back(rot(base, ang) + s.e);
            Pt mid = (s.s + s.e) / 2;
            for (auto &p : poly)
                p += unit(p - mid) * EPS2;
        }
        if (area(poly) < 0) reverse(poly.begin(), poly.end());
        ext.push_back(poly);
        for (const auto &p : poly) cand.push_back(p);
    }
    for (size_t i = 0; i < ext.size(); ++i) {
        for (size_t j = 0; j < i; ++j) {
            const auto &p1 = ext[i], &p2 = ext[j];
            for (size_t a = 0; a < p1.size(); ++a) {
                for (size_t b = 0; b < p2.size(); ++b) {
                    Seg s1(p1[a], p1[(a+1)%p1.size()]);
                    Seg s2(p2[b], p2[(b+1)%p2.size()]);
                    if (!parallel(s1, s2) && intersect(s1, s2))
                        cand.push_back(getInter(s1, s2));
                }
            }
        }
    }
    sort(cand.begin(), cand.end());
    cand.erase(unique(cand.begin(), cand.end()), cand.end());
    vector<Pt> ret;
    for (const auto &p : cand) {
        bool ok = true;
        for (const auto &poly : ext)
            if (inPoly(poly, p)) { ok = false; break; }
        if (ok) ret.push_back(p);
    }
    return ret;
}

inline vector<Pt> enumSpin(const vector<Seg> &segs, int L, int nAng, int k) {
    int m = segs.size();
    ld a1 = k * PI / nAng, a2 = (k+1) * PI / nAng;
    vector<vector<Fin>> fins(m);
    vector<vector<Poly>> quads(m);
    for (int i = 0; i < m; ++i) {
        fins[i] = enumFin(segs[i], L, a1, a2);
        quads[i] = enumQuad(segs[i], L, a1, a2);
    }
    vector<Pt> cand;
    for (const auto &s : segs) {
        cand.push_back(s.s);
        cand.push_back(s.e);
    }
    for (int i = 0; i < m; ++i) {
        for (int j = i+1; j < m; ++j) {
            for (const auto &f1 : fins[i])
                for (const auto &f2 : fins[j]) {
                    vector<Pt> inter = circleCircle(Circle(f1.c, f1.r+EPS2),
                                                    Circle(f2.c, f2.r+EPS2));
                    for (const auto &p : inter) cand.push_back(p);
                }
            for (const auto &poly1 : quads[i])
                for (const auto &poly2 : quads[j])
                    for (size_t a = 0; a < poly1.size(); ++a)
                        for (size_t b = 0; b < poly2.size(); ++b) {
                            Seg s1(poly1[a], poly1[(a+1)%poly1.size()]);
                            Seg s2(poly2[b], poly2[(b+1)%poly2.size()]);
                            Pt norm1 = unit(rot(s1.e - s1.s, -PI/2)) * EPS2;
                            Pt norm2 = unit(rot(s2.e - s2.s, -PI/2)) * EPS2;
                            s1.s += norm1; s1.e += norm1;
                            s2.s += norm2; s2.e += norm2;
                            if (!parallel(s1, s2) && intersect(s1, s2))
                                cand.push_back(getInter(s1, s2));
                        }
        }
        for (int j = 0; j < m; ++j) {
            for (const auto &f : fins[i])
                for (const auto &poly : quads[j])
                    for (size_t b = 0; b < poly.size(); ++b) {
                        Seg s(poly[b], poly[(b+1)%poly.size()]);
                        Pt norm = unit(rot(s.e - s.s, PI/2)) * EPS2;
                        s.s += norm; s.e += norm;
                        vector<Pt> inter = circleLine(Circle(f.c, f.r+EPS2), s);
                        for (const auto &p : inter) cand.push_back(p);
                    }
        }
    }
    sort(cand.begin(), cand.end());
    cand.erase(unique(cand.begin(), cand.end()), cand.end());
    vector<Pt> ret;
    for (const auto &p : cand) if (validPt(p, fins, quads)) ret.push_back(p);
    return ret;
}

inline bool visible(const Pt &a, const Pt &b, const vector<Poly> &obs) {
    Seg line(a, b);
    for (const auto &poly : obs)
        for (size_t i = 0; i < poly.size(); ++i) {
            Seg edge(poly[i], poly[(i+1)%poly.size()]);
            if (!parallel(line, edge) && intersect(line, edge)) return false;
        }
    return true;
}

using Graph = vector<vector<pair<int, int>>>;

Graph buildGraph(Pt s, Pt g, const vector<Seg> &obs,
                 const vector<vector<Pt>> &pass, const vector<vector<Pt>> &spin, int L) {
    int nAng = pass.size();
    vector<int> pIdx(nAng+1, 0), sIdx(nAng+1, 0);
    for (int k = 0; k < nAng; ++k) {
        pIdx[k+1] = pIdx[k] + pass[k].size();
        sIdx[k+1] = sIdx[k] + spin[k].size();
    }
    int N = pIdx[nAng] + sIdx[nAng] + 2;
    Graph gph(N);
    for (int k = 0; k < nAng; ++k) {
        vector<Poly> obsExt;
        Pt base(L, 0);
        ld ang = k * PI / nAng;
        for (const auto &seg : obs) {
            Poly poly = { rot(base, ang) + seg.s,
                          rot(base, addAng(ang, PI)) + seg.s,
                          rot(base, addAng(ang, PI)) + seg.e,
                          rot(base, ang) + seg.e };
            if (area(poly) < 0) reverse(poly.begin(), poly.end());
            obsExt.push_back(poly);
        }
        if (k == 0) {
            int sn = N - 2;
            for (size_t i = 0; i < pass[k].size(); ++i)
                if (visible(s, pass[k][i], obsExt))
                    gph[sn].push_back({ pIdx[k] + i, 0 });
            for (size_t i = 0; i < spin[k].size(); ++i)
                if (visible(s, spin[k][i], obsExt))
                    gph[sn].push_back({ pIdx[nAng] + sIdx[k] + i, 1 });
            int gn = N - 1;
            if (visible(s, g, obsExt)) gph[sn].push_back({ gn, 0 });
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int id1 = pIdx[k] + i;
            for (size_t j = 0; j < i; ++j) {
                int id2 = pIdx[k] + j;
                if (visible(pass[k][i], pass[k][j], obsExt)) {
                    gph[id1].push_back({ id2, 0 });
                    gph[id2].push_back({ id1, 0 });
                }
            }
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            for (size_t j = 0; j < spin[k].size(); ++j) {
                int sid = pIdx[nAng] + sIdx[k] + j;
                if (visible(pass[k][i], spin[k][j], obsExt))
                    gph[pid].push_back({ sid, 1 });
            }
        }
        int prev = (k + nAng - 1) % nAng;
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            for (size_t j = 0; j < spin[prev].size(); ++j) {
                int sid = pIdx[nAng] + sIdx[prev] + j;
                if (visible(pass[k][i], spin[prev][j], obsExt))
                    gph[sid].push_back({ pid, 0 });
            }
        }
        for (size_t i = 0; i < pass[k].size(); ++i) {
            int pid = pIdx[k] + i;
            int gn = N - 1;
            if (visible(pass[k][i], g, obsExt)) {
                gph[pid].push_back({ gn, 0 });
                gph[gn].push_back({ pid, 0 });
            }
        }
    }
    return gph;
}

int bfs01(int s, int t, const Graph &gph) {
    int N = gph.size();
    vector<int> dist(N, -1);
    deque<int> dq;
    dist[s] = 0;
    dq.push_back(s);
    while (!dq.empty()) {
        int cur = dq.front(); dq.pop_front();
        for (auto &edge : gph[cur]) {
            int nxt = edge.first, w = edge.second;
            if (dist[nxt] >= 0) continue;
            dist[nxt] = dist[cur] + w;
            if (nxt == t) return dist[nxt];
            if (w == 0) dq.push_front(nxt);
            else dq.push_back(nxt);
        }
    }
    return -1;
}

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

    int L, nAng;
    cin >> L >> nAng;

    Pt start, goal;
    cin >> start.x >> start.y >> goal.x >> goal.y;

    int nObs;
    cin >> nObs;
    vector<Seg> obs(nObs);
    for (int i = 0; i < nObs; ++i)
        cin >> obs[i].s.x >> obs[i].s.y >> obs[i].e.x >> obs[i].e.y;
    vector<vector<Pt>> pass(nAng), spin(nAng);
    for (int k = 0; k < nAng; ++k) pass[k] = enumPass(obs, L, nAng, k);
    for (int k = 0; k < nAng; ++k) spin[k] = enumSpin(obs, L, nAng, k);
    Graph gph = buildGraph(start, goal, obs, pass, spin, L);
    int N = gph.size();
    int ans = bfs01(N - 2, N - 1, gph);
    cout << ans << endl;
    return 0;
}
accuracy: 0.8688524590163934
time_ms: 6340
memory_kb: 6408
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)

struct P{
    double X;
    double Y;
    P(double x=0.0, double y=0.0): X(x),Y(y){}

    inline const P inv() const { return P(X/(X*X+Y*Y), -Y/(X*X+Y*Y)); }
    inline const P operator -() const { return P(-X, -Y); }
    inline const P operator +(const P& a) const { return P(X+a.X, Y+a.Y); }
    inline const P operator -(const P& a) const { return P(X-a.X, Y-a.Y); }
    inline const P operator *(const P& a) const { return P(X*a.X -Y*a.Y, X*a.Y +Y*a.X); }
    inline const P operator /(const P& a) const { return *this *a.inv(); }
    inline const P operator *(const double& c) const { return P(c*X, c*Y); }
    inline const P operator /(const double& c) const { return P(X/c, Y/c); }

    inline P& operator +=(const P& a){ X+=a.X; Y+=a.Y; return *this; }
    inline P& operator -=(const P& a){ X-=a.X; Y-=a.Y; return *this; }
    inline P& operator *=(const P& a){ double nX=X*a.X-Y*a.Y; Y=X*a.Y+Y*a.X; X=nX; return *this; }
    inline P& operator /=(const P& a){ double d=a.X*a.X+a.Y*a.Y; double nX=(X*a.X+Y*a.Y)/d; Y=(-X*a.Y+Y*a.X)/d; X=nX; return *this; }
    inline P& operator *=(const double& c){ X*=c; Y*=c; return *this; }
    inline P& operator /=(const double& c){ X/=c; Y/=c; return *this; }

    inline bool operator ==(const P& a) const { return EQ(X,a.X) and EQ(Y,a.Y); }
    inline bool operator !=(const P& a) const { return !(*this==a); }
    inline bool operator <(const P& a) const { return !EQ(X,a.X)? X<a.X: Y+EPS<a.Y; }
    inline bool operator <=(const P& a) const { return *this<a or *this==a; }
    inline bool operator >(const P& a) const { return !(*this<=a); }
    inline bool operator >=(const P& a) const { return !(*this<a); }
};
P operator *(const double& c, const P& p){ return P(c*p.X, c*p.Y); }
double norm(const P& a){ return a.X*a.X +a.Y*a.Y; }
double abs(const P& a){ return sqrt(a.X*a.X +a.Y*a.Y); }
double arg(const P& a){ return atan2(a.X, a.Y); }
double dot(const P& a, const P& b){ return a.X*b.X +a.Y*b.Y; }
double cross(const P& a, const P& b){ return a.X*b.Y -a.Y*b.X; }

typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b): array<P,2>({a,b}){}
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};

int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}
VP crosspointDADA(const DA &a, const DA &b){
    VP cp = crosspointCC(a.c, b.c);
    VP res;
    for(P &p: cp){
        P va = p -a.c.p;
        P vb = p -b.c.p;
        if((cross(va, a.v[0]) * cross(va, a.v[1]) < EPS) and
            (cross(vb, a.v[0]) * cross(vb, a.v[1]) < EPS)){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<pair<vector<VP>, vector<DA>>>> nonrotate_area;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_area.resize(rot);
    for(int r=0; r<rot; r++){
        nonrotate_area[r].resize(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            nr.first.push_back(slide_rect[r][i]);
            nr.first.push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nr.first.push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nr.second.emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nr.second.emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<vector<L>> w(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            for(VP &v: nr.first){
                for(int j=0; j<4; j++){
                    w[i].emplace_back(v[j], v[(j+1)%4]);
                }
            }
        }
        auto &cand = cand_rot[r];       
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                auto &arci = nonrotate_area[r][i].second;
                auto &arcj = nonrotate_area[r][j].second;
                for(L &a: w[i]){
                    for(L &b: w[j]){
                        if(strictItsSS(a, b)){
                            cand.push_back(crosspointLL(a, b));
                        }
                    }
                }
                for(L &s: w[i]){
                    for(DA &da: arcj){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &da: arci){
                    for(L &s: w[j]){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &a: arci){
                    for(DA &b: arcj){
                        insertvec(cand, crosspointDADA(a, b));
                    }
                }
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

bool is_in_nonrot_area(const P &p, int r){
    for(auto &nr: nonrotate_area[r]){
        for(VP &rect: nr.first){
            if(isInConvex(p, rect)){
                return true;
            }
        }
    }
    for(auto &nr: nonrotate_area[r]){
        for(DA &da: nr.second){
            if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                return true;
            }
        }
    }
    return false;
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P &p: cand){
            if(!is_in_nonrot_area(p, r)){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(const VP &rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

bool is_in_slide_rect(const P &p, int r){
    for(VP &rect: slide_rect[r]){
        if(isInConvex(p, rect)) return true;
    }
    return false;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP &rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        vector<bool> disabled(v.size(), false);
        for(int i=0; i<(int)v.size(); i++){
            if(is_in_slide_rect(v[i], r)){
                disabled[i] = true;
            }
        }
        int a = 4*n +2;
        int b = 4*n +2 +cand_rot[r].size();
        for(int i=0; i<(int)v.size(); i++){
            if(disabled[i]) continue;
            for(int j=i+1; j<(int)v.size(); j++){
                if(disabled[j]) continue;
                if(a<=i and i<b and a<=j and j<b) continue;
                if(b<=i and b<=j) continue;
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto &next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 4704
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)

struct P{
    double X;
    double Y;
    P(double x=0.0, double y=0.0): X(x),Y(y){}

    inline const P inv() const { return P(X/(X*X+Y*Y), -Y/(X*X+Y*Y)); }
    inline const P operator -() const { return P(-X, -Y); }
    inline const P operator +(const P& a) const { return P(X+a.X, Y+a.Y); }
    inline const P operator -(const P& a) const { return P(X-a.X, Y-a.Y); }
    inline const P operator *(const P& a) const { return P(X*a.X -Y*a.Y, X*a.Y +Y*a.X); }
    inline const P operator /(const P& a) const { return *this *a.inv(); }
    inline const P operator *(const double& c) const { return P(c*X, c*Y); }
    inline const P operator /(const double& c) const { return P(X/c, Y/c); }

    inline P& operator +=(const P& a){ X+=a.X; Y+=a.Y; return *this; }
    inline P& operator -=(const P& a){ X-=a.X; Y-=a.Y; return *this; }
    inline P& operator *=(const P& a){ double nX=X*a.X-Y*a.Y; Y=X*a.Y+Y*a.X; X=nX; return *this; }
    inline P& operator /=(const P& a){ double d=a.X*a.X+a.Y*a.Y; double nX=(X*a.X+Y*a.Y)/d; Y=(-X*a.Y+Y*a.X)/d; X=nX; return *this; }
    inline P& operator *=(const double& c){ X*=c; Y*=c; return *this; }
    inline P& operator /=(const double& c){ X/=c; Y/=c; return *this; }

    inline bool operator ==(const P& a) const { return EQ(X,a.X) and EQ(Y,a.Y); }
    inline bool operator !=(const P& a) const { return !(*this==a); }
    inline bool operator <(const P& a) const { return !EQ(X,a.X)? X<a.X: Y+EPS<a.Y; }
    inline bool operator <=(const P& a) const { return *this<a or *this==a; }
    inline bool operator >(const P& a) const { return !(*this<=a); }
    inline bool operator >=(const P& a) const { return !(*this<a); }
};
P operator *(const double& c, const P& p){ return P(c*p.X, c*p.Y); }
double norm(const P& a){ return a.X*a.X +a.Y*a.Y; }
double abs(const P& a){ return sqrt(a.X*a.X +a.Y*a.Y); }
double arg(const P& a){ return atan2(a.X, a.Y); }
double dot(const P& a, const P& b){ return a.X*b.X +a.Y*b.Y; }
double cross(const P& a, const P& b){ return a.X*b.Y -a.Y*b.X; }

typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};

int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}
VP crosspointDADA(const DA &a, const DA &b){
    VP cp = crosspointCC(a.c, b.c);
    VP res;
    for(P &p: cp){
        P va = p -a.c.p;
        P vb = p -b.c.p;
        if((cross(va, a.v[0]) * cross(va, a.v[1]) < EPS) and
            (cross(vb, a.v[0]) * cross(vb, a.v[1]) < EPS)){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<pair<vector<VP>, vector<DA>>>> nonrotate_area;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_area.resize(rot);
    for(int r=0; r<rot; r++){
        nonrotate_area[r].resize(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            nr.first.push_back(slide_rect[r][i]);
            nr.first.push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nr.first.push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nr.second.emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nr.second.emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<vector<L>> w(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            for(VP &v: nr.first){
                for(int j=0; j<4; j++){
                    w[i].emplace_back(v[j], v[(j+1)%4]);
                }
            }
        }
        auto &cand = cand_rot[r];       
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                auto &arci = nonrotate_area[r][i].second;
                auto &arcj = nonrotate_area[r][j].second;
                for(L &a: w[i]){
                    for(L &b: w[j]){
                        if(strictItsSS(a, b)){
                            cand.push_back(crosspointLL(a, b));
                        }
                    }
                }
                for(L &s: w[i]){
                    for(DA &da: arcj){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &da: arci){
                    for(L &s: w[j]){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &a: arci){
                    for(DA &b: arcj){
                        insertvec(cand, crosspointDADA(a, b));
                    }
                }
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

bool is_in_nonrot_area(const P &p, int r){
    for(auto &nr: nonrotate_area[r]){
        for(VP &rect: nr.first){
            if(isInConvex(p, rect)){
                return true;
            }
        }
    }
    for(auto &nr: nonrotate_area[r]){
        for(DA &da: nr.second){
            if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                return true;
            }
        }
    }
    return false;
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P &p: cand){
            if(!is_in_nonrot_area(p, r)){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(const VP &rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

bool is_in_slide_rect(const P &p, int r){
    for(VP &rect: slide_rect[r]){
        if(isInConvex(p, rect)) return true;
    }
    return false;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP &rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        vector<bool> disabled(v.size(), false);
        for(int i=0; i<(int)v.size(); i++){
            if(is_in_slide_rect(v[i], r)){
                disabled[i] = true;
            }
        }
        int a = 4*n +2;
        int b = 4*n +2 +cand_rot[r].size();
        for(int i=0; i<(int)v.size(); i++){
            if(disabled[i]) continue;
            for(int j=i+1; j<(int)v.size(); j++){
                if(disabled[j]) continue;
                if(a<=i and i<b and a<=j and j<b) continue;
                if(b<=i and b<=j) continue;
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto &next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 4720
final_rank: 2

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <complex>
#include <array>
#include <cassert>
#include <functional>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);

struct point {
	double x, y;
	point(double x_, double y_):x(x_), y(y_){};
	point(const point &p):x(p.x), y(p.y){}
	point():x(0), y(0){}
	point& operator+=(point a){x += a.x;y += a.y;return *this;}
	point& operator-=(point a){x -= a.x;y -= a.y;return *this;}
	point& operator*=(point a){
		double xx = x * a.x - y * a.y;
		double yy = x * a.y + y * a.x;
		x = xx;y = yy;return *this;
	}
	point& operator*=(double a){x *= a;y *= a;return *this;}
	point& operator/=(double a){x /= a;y /= a;return *this;}
	point operator+(point a) const{return point(x, y)+=a;}
	point operator-(point a) const{return point(x, y)-=a;}
	point operator-() const{return point(-x, -y);}
	point operator*(point a) const{return point(x, y)*=a;}
	point operator*(double a) const{return point(x, y)*=a;}
	point operator/(double a) const{return point(x, y)/=a;}
	bool operator<(point a) const{return (x != a.x ? x < a.x : y < a.y);}
	double real() {return x;}
	double imag() {return y;}
};

template <class T>
point operator*(const T a, const point p){return p * a;}

point conj(point p) {return point(p.x, -p.y);}
double arg(point p) {return arg(complex<double>(p.x, p.y));}
double abs(point p) {return abs(complex<double>(p.x, p.y));}
double norm(point p) {return norm(complex<double>(p.x, p.y));}
double real(point p) {return p.x;}
double imag(point p) {return p.y;}

struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// a から b まで
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return (conj(a)*b).y;
}

double dot(const point& a, const point& b) {
	return (conj(a)*b).x;
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//a -> b と反時計回りに巡った時の角度
double angle(const point &a,const point &b) {
	auto tmp = arg(b) - arg(a);
	if(tmp < 0)tmp += 2 * PI;
	return tmp;
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.x * cos(rad) - p.y * sin(rad);
	double y = p.y * cos(rad) + p.x * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return eq(abs(angle(a, b) - PI), PI / 2);
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment l, const segment m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment l, const segment s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment l, const point p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment s, const point p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment s, const segment t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment s, const segment t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment l, const point p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment l, const point p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment l, const point p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment l, const segment m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment l, const segment s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment s, const point p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment s, const segment t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point a,const point b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (a.y > b.y) swap(a, b);
		if (a.y < EPS && EPS < b.y && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

bool isOnSector(const sector sec, const point p) {
	if(intersectSP(segment(sec.o, sec.a), p))return true;
	if(intersectSP(segment(sec.o, sec.b), p))return true;
	if(!eq(abs(sec.o - p), sec.r))return false;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vecA, vec) < angle(vecA, vecB) + EPS)return true;
	return false;
}

/*
OUT:0
ON:1
IN:2
*/
int contain_sector(const sector &sec, point &p){
	if(isOnSector(sec, p))return 1;
	if(sec.r + EPS < abs(p - sec.o))return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vecA, vec) < angle(vecA, vecB) + EPS)return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.y - c1.p.y, c2.p.x - c1.p.x);
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (d.y < c.y) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (c.y <= m.y && m.y < d.y)  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		if(ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]) == -1)return false;
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (pt[i].y > pt[is].y) is = i;
    if (pt[i].y < pt[js].y) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

point max_circle_size_in_polygon_check(double mid, vector<point> &v){
	ll n = v.size();
	vector<point> now(v);
	REP(i, n){
		auto a = v[i];
		auto b = v[(i+1)%n];
		auto vec = b - a;
		vec /= abs(vec);
		vec *= mid;
		vec = vec * point(0, 1);
		segment seg = segment(a + vec, b + vec);
		now = convex_cut(now, seg);
	}
	return (now.empty() ? point(INF, INF): now[0]);
}

// 凸多角形に入る最大の円
circle max_circle_size_in_polygon(vector<point> &v){
	double l = 0;
	double r = convex_diameter(v);
	point ret;
	REP(_, 1000){
		if(abs(l - r) < EPS)break;
		double mid = (l + r) / 2;
		ret = max_circle_size_in_polygon_check(mid, v);
		if(!eq(ret, point(INF, INF)))l = mid;
		else r = mid;
	}
	return circle(ret, l);
}

//　三角形の外接円
circle circumscribed_circle(vector<point> p) {
	segment seg_a = segment((p[1] + p[0]) * 0.5,
	(p[1] + p[0]) * 0.5 + (p[1] - p[0]) * point(0, 1));
	segment seg_b = segment((p[2] + p[1]) * 0.5,
	(p[2] + p[1]) * 0.5 + (p[2] - p[1]) * point(0, 1));
	circle ret;
	ret.p = crosspointSS(seg_a, seg_b);
	ret.r = distancePP(p[0], ret.p);
	return ret;
}

// ################################### 3D ####################################

struct quaternion;
quaternion conj(quaternion q);
struct point3d {
	double x, y, z;
	point3d():x(0), y(0), z(0){}
	point3d(const point3d &p):x(p.x), y(p.y), z(p.z){}
	point3d(const quaternion &q); // 先行宣言
	point3d(double x_, double y_, double z_):x(x_), y(y_), z(z_){}

	point3d& operator+=(point3d a){x += a.x;y += a.y;z += a.z;return *this;}
	point3d& operator-=(point3d a){x -= a.x;y -= a.y;z -= a.z;return *this;}
	point3d& operator*=(quaternion q); // 先行宣言
	point3d& operator*=(double a){x *= a;y *= a;z *= a;return *this;}
	point3d& operator/=(double a){x /= a;y /= a;z /= a;return *this;}
	point3d operator+(point3d a) const{return point3d(x, y, z)+=a;}
	point3d operator-(point3d a) const{return point3d(x, y, z)-=a;}
	point3d operator-() const{return point3d(-x, -y, -z);}
	point3d operator*(quaternion q); // 先行宣言
	point3d operator*(double a) const{return point3d(x, y, z)*=a;}
	point3d operator/(double a) const{return point3d(x, y, z)/=a;}
	bool operator<(point3d a) const{
		return (x != a.x ? x < a.x : (y != a.y ? y < a.y : z < a.z));}
};

template <class T>
point3d operator*(const T a, const point3d p){return p * a;}

struct segment3d: public array<point3d, 2> {
	segment3d(const point3d &a, const point3d &b) {
		at(0) = a;
		at(1) = b;
	}
};

double abs(point3d p) {	return sqrt(p.x * p.x + p.y * p.y + p.z * p.z); }
double norm(point3d p) {	return p.x * p.x + p.y * p.y + p.z * p.z; }
double dot(point3d a, point3d b){	return a.x * b.x + a.y * b.y + a.z * b.z; }
point3d cross(point3d a, point3d b){
	return point3d(a.y * b.z - a.z * b.y,
								 a.z * b.x - a.x * b.z,
							   a.x * b.y - a.y * b.x);
}

point3d projection(const segment3d &l, const point3d &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point3d reflection(const segment3d &l, const point3d &p) {
	return p + 2. * (projection(l, p) - p);
}

bool intersect3dSP(const segment3d &s, const point3d &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}

bool intersect3dLP(const segment3d &l, const point3d &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}

double angle(point3d a, point3d b){
	double tmp = dot(a, b) / (abs(a) * abs(b));
	if(tmp < -1)tmp = -1;
	if(tmp > 1)tmp = 1;
	return acos(tmp);
}

struct plane {
	double a, b, c, d;
	plane():a(0), b(0), c(0), d(0){}
	plane(double a_, double b_, double c_, double d_):a(a_), b(b_), c(c_), d(d_){}
	plane(point3d p1, point3d p2, point3d p3){
		point3d A = p2 - p1;
		point3d B = p3 - p1;
		point3d p = cross(A, B);
		a = p.x;b = p.y;c = p.z;
		d = -(a * p1.x + b * p1.y + c * p1.z);
	}
	double assignment(point3d p){
		return a * p.x + b * p.y + c * p.z + d;
	}
};

double distance(point3d p, plane pl){
	double a = abs(p.x * pl.a + p.y * pl.b + p.z * pl.c + pl.d);
	double b = sqrt(pl.a * pl.a + pl.b * pl.b + pl.c * pl.c);
	return a / b;
}

double distance(plane p, point3d pl){
	return distance(pl, p);
}

point3d projection(point3d p, plane pl){
	double d = distance(p, pl);
	point3d a = point3d(pl.a, pl.b, pl.c);a /= abs(a);
	point3d ret = p + a * d;
	if(distance(ret, pl) < EPS)return ret;
	return p - a * d;
}

point3d crossPoint3d(segment3d s, plane p){
	double bunsi = p.a * s[0].x + p.b * s[0].y + p.c * s[0].z + p.d;
	double bunbo = p.a * (s[0].x - s[1].x) +
								 p.b * (s[0].y - s[1].y) +
								 p.c * (s[0].z - s[1].z);
	if(abs(bunbo) < EPS)return point3d(INF, INF, INF);
	double t = bunsi / bunbo;
	return s[0] + (s[1] - s[0]) * t;
}

struct quaternion {
	double x, y, z, w;
	quaternion():x(0), y(0), z(0){}
	quaternion(const point3d &p):x(p.x), y(p.y), z(p.z), w(0){}
	quaternion(double x_, double y_, double z_, double w_):x(x_), y(y_), z(z_), w(w_){}
	// ベクトルpを軸にrad回転させる
	quaternion(const point3d &p, double rad){
		assert(abs(p) > EPS);
		point3d np(p);np /= abs(np);
		x = np.x * sin(rad / 2);
		y = np.y * sin(rad / 2);
		z = np.z * sin(rad / 2);
		w = cos(rad / 2);
	}
	quaternion& operator*=(double a){x *= a;y *= a;z *= a;w *= a;return *this;}
	quaternion& operator/=(double a){x /= a;y /= a;z /= a;w /= a;return *this;}
	quaternion& operator*=(quaternion q){
		double xx = w * q.x + x * q.w - y * q.z + z * q.y;
		double yy = w * q.y + x * q.z + y * q.w - z * q.x;
		double zz = w * q.z - x * q.y + y * q.x + z * q.w;
		double ww = w * q.w - x * q.x - y * q.y - z * q.z;
		*this = quaternion(xx, yy, zz, ww);return *this;
	}
	quaternion operator*(quaternion q) const{return quaternion(x, y, z, w)*=q;}
	quaternion operator*(double a) const{return quaternion(x, y, z, w)*=a;}
	quaternion operator/(double a) const{return quaternion(x, y, z, w)/=a;}
};

quaternion conj(quaternion q) {
	 return quaternion(-q.x, -q.y, -q.z, q.w);
 }
double abs(quaternion q) {
	return sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
}
quaternion normalization(quaternion q){
	return q / abs(q);
}

point3d::point3d(const quaternion &q):x(q.x), y(q.y), z(q.z){}
point3d& point3d::operator*=(quaternion q){
	normalization(q);
	*this = point3d(q * quaternion(*this) * conj(q));
	return *this;
}
point3d point3d::operator*(quaternion q){ return point3d(x, y, z)*= q; }

// vecへ平行移動
void translation(vector<point3d> &p, point3d vec){
	REP(i, p.size())p[i] += vec;
}

void scale(vector<point3d> &p, double s){
	REP(i, p.size())p[i] *= s;
}

// pをaxisを軸にaからbまで回転する
void RotateWithAngleAxis(vector<point3d> &p, segment3d axis, point3d a, point3d b) {
	point3d tmp = axis[0];
	translation(p, -tmp);
	axis[0] -= tmp;axis[1] -= tmp;
	a -= tmp;b -= tmp;

	point3d avec = a - projection(axis, a);
	point3d bvec = b - projection(axis, b);
	if(abs(avec) < EPS || abs(bvec) < EPS){

	}
	else if(eq(abs(cross(avec, bvec)), 0)){
		quaternion q = quaternion(axis[1], angle(avec, bvec));
		REP(i, p.size())p[i] *= q;
	}
	else{
		quaternion q = quaternion(cross(bvec, avec), angle(avec, bvec));
		REP(i, p.size())p[i] *= q;
	}

	translation(p, tmp);
	axis[0] += tmp;axis[1] += tmp;
	a += tmp;b += tmp;
}

// ################################### 3D ####################################
// ################################### IO ####################################

istream& operator>>(std::istream& is, point3d& p){
	is >> p.x >> p.y >> p.z;
	return is;
}

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

ostream& operator<<(ostream& os, const quaternion& q){
	os << q.x << " " << q.y << " " << q.z << " " << q.w;
	return os;
}

ostream& operator<<(ostream& os, const plane& p){
	os << p.a << "x + " << p.b << "y + " << p.c << "z + " << p.d;
	return os;
}

istream& operator>>(std::istream& is, point& p){
	is >> p.x >> p.y;
  return is;
}

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

// ################################### IO ####################################



double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2980
memory_kb: 7484
final_rank: 13

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <complex>
#include <array>
#include <functional>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
struct point {
	double x, y;
	point(double x_, double y_):x(x_), y(y_){};
	point(const point &p):x(p.x), y(p.y){}
	point():x(0), y(0){}
	point& operator+=(point a){x += a.x;y += a.y;return *this;}
	point& operator-=(point a){x -= a.x;y -= a.y;return *this;}
	point& operator*=(point a){
		double xx = x * a.x - y * a.y;
		double yy = x * a.y + y * a.x;
		x = xx;y = yy;return *this;
	}
	point& operator*=(double a){x *= a;y *= a;return *this;}
	point& operator/=(double a){x /= a;y /= a;return *this;}
	point operator+(point a) const{return point(x, y)+=a;}
	point operator-(point a) const{return point(x, y)-=a;}
	point operator*(point a) const{return point(x, y)*=a;}
	point operator*(double a) const{return point(x, y)*=a;}
	point operator/(double a) const{return point(x, y)/=a;}
	bool operator<(point a) const{return (x != a.x ? x < a.x : y < a.y);}
	bool operator==(point a) const{return (abs(x - a.x) < EPS && abs(y - a.y) < EPS);}
	bool operator!=(point a) const{return !(abs(x - a.x) >= EPS || abs(y - a.y) >= EPS);}
	double real() {return x;}
	double imag() {return y;}
};

template <class T>
point operator*(const T a, const point p){return point(p.x * a, p.y * a);}

point conj(point p) {return point(p.x, -p.y);}
double arg(point p) {return arg(complex<double>(p.x, p.y));}
double abs(point p) {return abs(complex<double>(p.x, p.y));}
double norm(point p) {return norm(complex<double>(p.x, p.y));}
double real(point p) {return p.x;}
double imag(point p) {return p.y;}

namespace std {
	istream& operator>>(std::istream& is, point& p){
		is >> p.x >> p.y;
    return is;
}
	ostream& operator<<(ostream& os, const point& p){
		os << p.x << " " << p.y;
		return os;
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return (conj(a)*b).y;
}

double dot(const point& a, const point& b) {
	return (conj(a)*b).x;
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.x * cos(rad) - p.y * sin(rad);
	double y = p.y * cos(rad) + p.x * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (a.y > b.y) swap(a, b);
		if (a.y < EPS && EPS < b.y && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

/*
OUT:0
ON:1
IN:2
*/
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.y - c1.p.y, c2.p.x - c1.p.x);
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (d.y < c.y) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (c.y <= m.y && m.y < d.y)  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		if(ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]) == -1)return false;
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (pt[i].y > pt[is].y) is = i;
    if (pt[i].y < pt[js].y) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

point max_circle_size_in_polygon_check(double mid, vector<point> &v){
	ll n = v.size();
	vector<point> now(v);
	REP(i, n){
		auto a = v[i];
		auto b = v[(i+1)%n];
		auto vec = b - a;
		vec /= abs(vec);
		vec *= mid;
		vec = vec * point(0, 1);
		segment seg = segment(a + vec, b + vec);
		now = convex_cut(now, seg);
	}
	return (now.empty() ? point(INF, INF): now[0]);
}

// 凸多角形に入る最大の円
circle max_circle_size_in_polygon(vector<point> &v){
	double l = 0;
	double r = convex_diameter(v);
	point ret;
	REP(_, 1000){
		if(abs(l - r) < EPS)break;
		double mid = (l + r) / 2;
		ret = max_circle_size_in_polygon_check(mid, v);
		if(ret != point(INF, INF))l = mid;
		else r = mid;
	}
	return circle(ret, l);
}

//　三角形の外接円
circle circumscribed_circle(vector<point> p) {
	segment seg_a = segment((p[1] + p[0]) * 0.5,
	(p[1] + p[0]) * 0.5 + (p[1] - p[0]) * point(0, 1));
	segment seg_b = segment((p[2] + p[1]) * 0.5,
	(p[2] + p[1]) * 0.5 + (p[2] - p[1]) * point(0, 1));
	circle ret;
	ret.p = crosspointSS(seg_a, seg_b);
	ret.r = distancePP(p[0], ret.p);
	return ret;
}

// ################################### 3D ####################################

struct point3d {
	double x, y, z;
	point3d(double x_, double y_, double z_):x(x_), y(y_), z(z_){}

	point3d& operator+=(point3d a){x += a.x;y += a.y;z += a.z;return *this;}
	point3d& operator-=(point3d a){x -= a.x;y -= a.y;z -= a.z;return *this;}
	point3d& operator*=(double a){x *= a;y *= a;z *= a;return *this;}
	point3d& operator/=(double a){x /= a;y /= a;z /= a;return *this;}
	point3d operator+(point3d a) const{return point3d(x, y, z)+=a;}
	point3d operator-(point3d a) const{return point3d(x, y, z)-=a;}
	point3d operator*(double a) const{return point3d(x, y, z)*=a;}
	point3d operator/(double a) const{return point3d(x, y, z)/=a;}
	bool operator<(point3d a) const{
		return (x == a.x ? x < a.x : (y == a.y ? y < a.y : z < a.z));}
	bool operator==(point3d a) const{
		return (abs(x - a.x) < EPS && abs(y - a.y) < EPS && abs(z - a.z) < EPS);
	}
	bool operator!=(point3d a) const{return !(*this == a);}

};

double abs(point3d p) {
	return sqrt(p.x * p.x + p.y * p.y + p.z * p.z);
}

double dot(point3d a, point3d b){
	return a.x * b.x + a.y * b.y + a.z * b.z;
}

point3d cross(point3d a, point3d b){
	return point3d(a.y * b.z - a.z * b.y,
								 a.z * b.x - a.x * b.z,
							   a.x * b.y - a.y * b.x);
}

struct plane {
	double a, b, c, d;
	plane(double a_, double b_, double c_, double d_):a(a_), b(b_), c(c_), d(d_){}
	plane(point3d p1, point3d p2, point3d p3){
		point3d A = p2 - p1;
		point3d B = p3 - p1;
		point3d p = cross(A, B);
		a = p.x;b = p.y;c = p.z;
		d = -(a * p1.x + b * p1.y + c * p1.z);
	}
};

double distance(point3d p, plane pl){
	double a = abs(p.x * pl.a + p.y * pl.b + p.z * pl.c + pl.d);
	double b = sqrt(pl.a * pl.a + pl.b * pl.b + pl.c * pl.c);
	return a / b;
}

double distance(plane p, point3d pl){
	return distance(pl, p);
}

point3d projection(point3d p, plane pl){
	double d = distance(p, pl);
	point3d a = point3d(pl.a, pl.b, pl.c);a /= abs(a);
	point3d ret = p + a * d;
	if(distance(ret, pl) < EPS)return ret;
	return p - a * d;
}

namespace std {
	ostream& operator<<(ostream& os, const point3d& p){
		os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
		return os;
	}

	ostream& operator<<(ostream& os, const plane& p){
		os << p.a << "x + " << p.b << "y + " << p.c << "z + " << p.d;
		return os;
	}
}

// ################################### 3D ####################################


double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2940
memory_kb: 7548
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

/*
OUT:0
ON:1
IN:2
*/
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}
//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		int tmp = ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]);
		if(tmp == -1){
			return false;
		}
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 3510
memory_kb: 7596
final_rank: 16

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <complex>
#include <array>
#include <functional>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

/*
OUT:0
ON:1
IN:2
*/
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		if(ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]) == -1)return false;
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

point max_circle_size_in_polygon_check(double mid, vector<point> &v){
	ll n = v.size();
	vector<point> now(v);
	REP(i, n){
		auto a = v[i];
		auto b = v[(i+1)%n];
		auto vec = b - a;
		vec /= abs(vec);
		vec *= mid;
		vec = rotate(vec, PI/2);
		segment seg = segment(a + vec, b + vec);
		now = convex_cut(now, seg);
	}
	return (now.empty() ? point(INF, INF): now[0]);
}

// 凸多角形に入る最大の円
circle max_circle_size_in_polygon(vector<point> &v){
	double l = 0;
	double r = convex_diameter(v);
	point ret;
	REP(_, 1000){
		if(abs(l - r) < EPS)break;
		double mid = (l + r) / 2;
		ret = max_circle_size_in_polygon_check(mid, v);
		if(ret != point(INF, INF))l = mid;
		else r = mid;
	}
	return circle(ret, l);
}

circle circumscribed_circle(vector<point> p) {
	segment seg_a = segment((p[1] + p[0]) * 0.5,
	(p[1] + p[0]) * 0.5 + (p[1] - p[0]) * point(0, 1));
	segment seg_b = segment((p[2] + p[1]) * 0.5,
	(p[2] + p[1]) * 0.5 + (p[2] - p[1]) * point(0, 1));
	circle ret;
	ret.p = crosspointSS(seg_a, seg_b);
	ret.r = distancePP(p[0], ret.p);
	return ret;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 3520
memory_kb: 7680
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

// out: false
// in, on: true
bool contain_sector(const sector &sec, point &p){
	if(abs(p - sec.o) + EPS > sec.r)return false;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return true;
	return false;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		int tmp = ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]);
		if(tmp == -1){
			return false;
		}
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p))return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 3490
memory_kb: 7584
final_rank: 15

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <complex>
#include <array>
#include <functional>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

/*
OUT:0
ON:1
IN:2
*/
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		if(ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]) == -1)return false;
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

point max_circle_size_in_polygon_check(double mid, vector<point> &v){
	ll n = v.size();
	vector<point> now(v);
	REP(i, n){
		auto a = v[i];
		auto b = v[(i+1)%n];
		auto vec = b - a;
		vec /= abs(vec);
		vec *= mid;
		vec = rotate(vec, PI/2);
		segment seg = segment(a + vec, b + vec);
		now = convex_cut(now, seg);
	}
	return (now.empty() ? point(INF, INF): now[0]);
}

// 凸多角形に入る最大の円
circle max_circle_size_in_polygon(vector<point> &v){
	double l = 0;
	double r = convex_diameter(v);
	point ret;
	REP(_, 1000){
		if(abs(l - r) < EPS)break;
		double mid = (l + r) / 2;
		ret = max_circle_size_in_polygon_check(mid, v);
		if(ret != point(INF, INF))l = mid;
		else r = mid;
	}
	return circle(ret, l);
}

circle circumscribed_circle(vector<point> p) {
	segment seg_a = segment((p[1] + p[0]) * 0.5,
	(p[1] + p[0]) * 0.5 + (p[1] - p[0]) * point(0, 1));
	segment seg_b = segment((p[2] + p[1]) * 0.5,
	(p[2] + p[1]) * 0.5 + (p[2] - p[1]) * point(0, 1));
	circle ret;
	ret.p = crosspointSS(seg_a, seg_b);
	ret.r = distancePP(p[0], ret.p);
	return ret;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p))return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 0.01639344262295082
time_ms: 10
memory_kb: 3948
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

// out: false
// in, on: true
bool contain_sector(const sector &sec, point &p){
	if(abs(p - sec.o) + EPS > sec.r)return false;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return true;
	return false;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		int tmp = ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]);
		if(tmp == -1){
			return false;
		}
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p))return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2260
memory_kb: 5856
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//角度足し算
double add_rad(double a,double b){
	double ret = a + b;
	if(ret > 2 * PI)ret -= 2 * PI;
	return ret;
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//点の回転
point rotate(const point &p, double rad) {
	double x = p.real() * cos(rad) - p.imag() * sin(rad);
	double y = p.imag() * cos(rad) + p.real() * sin(rad);
	return point(x, y);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}
//直行
bool isOrthogonal(const point &a,const point &b){
	return abs(angle(a,b) - PI / 2) < EPS;
}
bool isOrthogonal(const segment &a,const segment &b){
	return isOrthogonal(a[1]-a[0],b[1]-b[0]);
}

/*
a → b で時計方向に折れて b → c
a → b で半時計方向に折れて b → c
a → b で逆を向いて a を通り越して b → c
a → b でそのまま b → c
a → b で逆を向いて b → c ( または b == c )
*/

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}

bool intersectLL(const segment &l, const segment &m) {
	return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
		abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}
bool intersectLS(const segment &l, const segment &s) {
	return cross(l[1] - l[0], s[0] - l[0])*       // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const segment &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
//端点の交差も考える
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}

point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
point reflection(const segment &l, const point &p) {
	return p + 2. * (projection(l, p) - p);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const segment &l, const segment &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const segment &l, const segment &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const segment &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const segment &s, const segment &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
		min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
double distancePP(const point &a,const point &b){
	return abs(a-b);
}

/*多角形内包判定
half-line crossing method
OUT:0
ON:1
IN:2
*/
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) + EPS <= 0 && EPS < imag(b))
			if (cross(a, b) < 0) in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) <= EPS) return 1;
	}
	return in ? 2 : 0;
}

// out: false
// in, on: true
bool contain_sector(const sector &sec, point &p){
	if(abs(p - sec.o) + EPS > sec.r)return false;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return true;
	return false;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}


//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

//見えるか(可視グラフ用)
bool block_off(const point &a, const point &b, const vector<point> &obj) {
  point m = (a + b) * 0.5;
  bool on = false, in = false;
  for (int j = 0; j < obj.size(); ++j) {
    point c = curr(obj,j), d = next(obj,j);
    if (imag(d) < imag(c)) swap(c, d);
    if (cross(a-c,b-c) * cross(a-d,b-d) < 0 &&    // strictly intersect.
        cross(c-a,d-a) * cross(c-b,d-b) < 0) return true;
    if (cross(a-c,b-c) == 0 && dot(a-c,b-c) < 0) return true;
    if (imag(c) <= imag(m) && imag(m) < imag(d))  // strictly contain.
      if (cross(c-m,d-m) < 0) in = !in;
    if (cross(c-m,d-m) == 0 && dot(c-m,d-m) <= EPS) on = true;
  }
  return !on && in;
}

//面積
double area(const vector<point>& p) {
	double A = 0;
	for (int i = 0; i < p.size(); ++i)
		A += cross(curr(p, i), next(p, i));
	return A / 2.;
}

//凸包判定
bool isConvex(vector<point> poly){
	int sz = poly.size();
	REP(i,sz){
		int tmp = ccw(poly[i],poly[(i+1)%sz],poly[(i+2)%sz]);
		if(tmp == -1){
			return false;
		}
	}
	return true;
}

double convex_diameter(const vector<point> &pt) {
  const int n = pt.size();
  int is = 0, js = 0;
  for (int i = 1; i < n; ++i) {
    if (imag(pt[i]) > imag(pt[is])) is = i;
    if (imag(pt[i]) < imag(pt[js])) js = i;
  }
  double maxd = norm(pt[is]-pt[js]);

  int i, maxi, j, maxj;
  i = maxi = is;
  j = maxj = js;
  do {
    if (cross(diff(pt,i), diff(pt,j)) >= 0) j = (j+1) % n;
    else i = (i+1) % n;
    if (norm(pt[i]-pt[j]) > maxd) {
      maxd = norm(pt[i]-pt[j]);
      maxi = i; maxj = j;
    }
  } while (i != is || j != js);
  return sqrt(maxd); /* farthest pair is (maxi, maxj). */
}

vector<point> convex_cut(const vector<point> P, const segment& l) {
  vector<point> Q;
  for (int i = 0; i < P.size(); ++i) {
    point A = curr(P, i), B = next(P, i);
    if (ccw(l[0], l[1], A) != -1) Q.push_back(A);
    if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0)
      Q.push_back(crosspointSS(segment(A, B), l));
  }
  return Q;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p))return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2270
memory_kb: 5800
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public pair<point, point> {
	segment(const point &a, const point &b) {
		first = a;
		second = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1.SE - s1.FI, s2.SE - s2.FI);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a.SE - a.FI, b.SE - b.FI);
}

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s.FI - p;
	auto b = s.SE - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) <= 0 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) == -1 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) == -1;
}
point projection(const segment &l, const point &p) {
	double t = dot(p - l.FI, l.FI - l.SE) / norm(l.FI - l.SE);
	return l.FI + t*(l.FI - l.SE);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b) && cross(a, b) > EPS)in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
	}
	return in ? 2 : 0;
}

int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l.SE - l.FI, m.SE - m.FI);
	double B = cross(l.SE - l.FI, l.SE - m.FI);
	if (abs(A) < EPS && abs(B) < EPS) return m.FI; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m.FI + B / A * (m.SE - m.FI);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l.SE - l.FI) * sqrt(c.r * c.r - dist * dist) / abs(l.SE - l.FI);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now.FI;
		point B = now.SE;
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = (j == 0 ? seg_list[i].FI : seg_list[i].SE);
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2260
memory_kb: 5900
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <complex>
#include <cmath>
#include <array>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)

struct P{
    double X;
    double Y;
    P(double x, double y): X(x),Y(y) {}
    P(){}
    bool operator <(const P &a){
        return !EQ(X,a.X) ? X<a.X : Y+EPS<a.Y;
    }
    bool operator ==(const P& a){
        return sqrt((X-a.X)*(X-a.X) +(Y-a.Y)*(Y-a.Y)) < EPS;
    }
    P& operator +=(const P& a){
        X += a.X; Y += a.Y;
        return *this;
    }
    P& operator -=(const P& a){
        X -= a.X; Y -= a.Y;
        return *this;
    }
};
double abs(const P &a){
    return sqrt(a.X*a.X +a.Y*a.Y);
}
double norm(const P &a){
    return a.X*a.X +a.Y*a.Y;
}
P operator +(const P &a, const P &b){
    return P(a.X+b.X, a.Y+b.Y);
}
P operator -(const P &a, const P &b){
    return P(a.X-b.X, a.Y-b.Y);
}
P operator -(const P &a){
    return P(-a.X, -a.Y);
}
P operator *(const P &a, const P &b){
    return P(a.X*b.X -a.Y*b.Y, a.X*b.Y +a.Y*b.X);
}
P operator *(const double &c, const P &p){
    return P(c*p.X, c*p.Y);
}
P operator *(const P &p, const double &c){
    return P(c*p.X, c*p.Y);
}
P operator /(const P &p, const double &c){
    return P(p.X/c, p.Y/c);
}

typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};

double dot(P a, P b){
    return a.X*b.X +a.Y*b.Y;
}
double cross(P a, P b){
    return a.X*b.Y -a.Y*b.X;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}
VP crosspointDADA(const DA &a, const DA &b){
    VP cp = crosspointCC(a.c, b.c);
    VP res;
    for(P &p: cp){
        P va = p -a.c.p;
        P vb = p -b.c.p;
        if((cross(va, a.v[0]) * cross(va, a.v[1]) < EPS) and
            (cross(vb, a.v[0]) * cross(vb, a.v[1]) < EPS)){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<pair<vector<VP>, vector<DA>>>> nonrotate_area;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_area.resize(rot);
    for(int r=0; r<rot; r++){
        nonrotate_area[r].resize(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            nr.first.push_back(slide_rect[r][i]);
            nr.first.push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nr.first.push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nr.second.emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nr.second.emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<vector<L>> w(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            for(VP &v: nr.first){
                for(int j=0; j<4; j++){
                    w[i].emplace_back(v[j], v[(j+1)%4]);
                }
            }
        }
        auto &cand = cand_rot[r];       
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                auto &arci = nonrotate_area[r][i].second;
                auto &arcj = nonrotate_area[r][j].second;
                for(L &a: w[i]){
                    for(L &b: w[j]){
                        if(strictItsSS(a, b)){
                            cand.push_back(crosspointLL(a, b));
                        }
                    }
                }
                for(L &s: w[i]){
                    for(DA &da: arcj){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &da: arci){
                    for(L &s: w[j]){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &a: arci){
                    for(DA &b: arcj){
                        insertvec(cand, crosspointDADA(a, b));
                    }
                }
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

bool is_in_nonrot_area(const P &p, int r){
    for(auto &nr: nonrotate_area[r]){
        for(VP &rect: nr.first){
            if(isInConvex(p, rect)){
                return true;
            }
        }
    }
    for(auto &nr: nonrotate_area[r]){
        for(DA &da: nr.second){
            if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                return true;
            }
        }
    }
    return false;
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P &p: cand){
            if(!is_in_nonrot_area(p, r)){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(const VP &rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

bool is_in_slide_rect(const P &p, int r){
    for(VP &rect: slide_rect[r]){
        if(isInConvex(p, rect)) return true;
    }
    return false;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP &rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        vector<bool> disabled(v.size(), false);
        for(int i=0; i<(int)v.size(); i++){
            if(is_in_slide_rect(v[i], r)){
                disabled[i] = true;
            }
        }
        int a = 4*n +2;
        int b = 4*n +2 +cand_rot[r].size();
        for(int i=0; i<(int)v.size(); i++){
            if(disabled[i]) continue;
            for(int j=i+1; j<(int)v.size(); j++){
                if(disabled[j]) continue;
                if(a<=i and i<b and a<=j and j<b) continue;
                if(b<=i and b<=j) continue;
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto &next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 4752
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <complex>
#include <cmath>
#include <array>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};
namespace std{
    bool operator <(const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator ==(const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}
VP crosspointDADA(const DA &a, const DA &b){
    VP cp = crosspointCC(a.c, b.c);
    VP res;
    for(P &p: cp){
        P va = p -a.c.p;
        P vb = p -b.c.p;
        if((cross(va, a.v[0]) * cross(va, a.v[1]) < EPS) and
            (cross(vb, a.v[0]) * cross(vb, a.v[1]) < EPS)){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<pair<vector<VP>, vector<DA>>>> nonrotate_area;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_area.resize(rot);
    for(int r=0; r<rot; r++){
        nonrotate_area[r].resize(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            nr.first.push_back(slide_rect[r][i]);
            nr.first.push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nr.first.push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nr.second.emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nr.second.emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<vector<L>> w(n);
        for(int i=0; i<n; i++){
            auto &nr = nonrotate_area[r][i];
            for(VP &v: nr.first){
                for(int j=0; j<4; j++){
                    w[i].emplace_back(v[j], v[(j+1)%4]);
                }
            }
        }
        auto &cand = cand_rot[r];       
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                auto &arci = nonrotate_area[r][i].second;
                auto &arcj = nonrotate_area[r][j].second;
                for(L &a: w[i]){
                    for(L &b: w[j]){
                        if(strictItsSS(a, b)){
                            cand.push_back(crosspointLL(a, b));
                        }
                    }
                }
                for(L &s: w[i]){
                    for(DA &da: arcj){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &da: arci){
                    for(L &s: w[j]){
                        insertvec(cand, crosspointSDA(s, da));
                    }
                }
                for(DA &a: arci){
                    for(DA &b: arcj){
                        insertvec(cand, crosspointDADA(a, b));
                    }
                }
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P p: cand){
            bool enable = true;
            for(auto &nr: nonrotate_area[r]){
                for(VP &rect: nr.first){
                    if(isInConvex(p, rect)){
                        enable = false;
                    }
                }
            }
            for(auto &nr: nonrotate_area[r]){
                for(DA &da: nr.second){
                    if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                        enable = false;
                    }
                }
            }
            if(enable){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(VP rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        int a = 4*n +2;
        int b = 4*n +2 +cand_rot[r].size();
        for(int i=0; i<(int)v.size(); i++){
            for(int j=i+1; j<(int)v.size(); j++){
                if(a<=i and i<b and a<=j and j<b) continue;
                if(b<=i and b<=j) continue;
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 660
memory_kb: 4624
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};
namespace std{
    bool operator <(const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator ==(const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

// from here
const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<VP>> nonrotate_rect;
vector<vector<DA>> nonrotate_da;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_rect.resize(rot);
    nonrotate_da.resize(rot);
    for(int r=0; r<rot; r++){
        for(int i=0; i<n; i++){
            nonrotate_rect[r].push_back(slide_rect[r][i]);
            nonrotate_rect[r].push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nonrotate_rect[r].push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nonrotate_da[r].emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nonrotate_da[r].emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<L> w;
        for(VP v: nonrotate_rect[r]){
            int n = v.size();
            for(int i=0; i<n; i++){
                w.emplace_back(v[i], v[(i+1)%n]);
            }
        }
        auto &arc = nonrotate_da[r];
        auto &cand = cand_rot[r];
        int n = w.size();
        int m = arc.size();
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                if(strictItsSS(w[i], w[j])){
                    cand.push_back(crosspointLL(w[i], w[j]));
                }
            }
        }
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                insertvec(cand, crosspointSDA(w[i], arc[j]));
            }
        }
        for(int i=0; i<m; i++){
            for(int j=i+1; j<m; j++){
                insertvec(cand, crosspointCC(arc[i].c, arc[j].c));
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P p: cand){
            bool enable = true;
            for(VP &rect: nonrotate_rect[r]){
                if(isInConvex(p, rect)){
                    enable = false;
                }
            }
            for(DA &da: nonrotate_da[r]){
                if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                    enable = false;
                }
            }
            if(enable){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(VP rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        for(size_t i=0; i<v.size(); i++){
            for(size_t j=i+1; j<v.size(); j++){
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 3140
memory_kb: 6216
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <complex>
#include <cmath>
#include <array>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
struct C{
    P p;
    double r;
    C(const P& p, const double& r): p(p),r(r) {}
    C(){}
};
namespace std{
    bool operator <(const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator ==(const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1;
    if(cross(b,c) < -EPS) return -1;
    if(dot(b,c) < EPS) return +2;
    if(dot(b,b-c) < EPS) return -2;
    return 0;
}
P unit(const P &p){
    return p/abs(p);
}
P rotate(const P &p, double rad){
    return p *P(cos(rad), sin(rad));
}

bool strictItsSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) == -1 ) and
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) == -1);
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS and dot(s[0]-p, s[1]-p)<EPS;
}
P projection(const L& l, const P& p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isInConvex(const P &p, const VP &poly){
    int n = poly.size();
    for(int i=0; i<n; i++){
        if(cross(poly[(i+1)%n]-poly[i], p-poly[i]) < EPS){
            return false;
        }
    }
    return true;
}

P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}
VP crosspointCL(const C &c, const L &l){
    VP res;
    P mid = projection(l, c.p);
    double d = distanceLP(l, c.p);
    if(EQ(d, c.r)){
        res.push_back(mid);
    }else if(d < c.r){
        double len = sqrt(c.r*c.r -d*d);
        res.push_back(mid +len*unit(l[1]-l[0]));
        res.push_back(mid -len*unit(l[1]-l[0]));
    }
    return res;
}
VP crosspointCC(C a, C b){
    VP res;
    if(a.r < b.r) swap(a,b);
    double dist = abs(b.p-a.p);
    P dir = a.r*unit(b.p-a.p);
    if(EQ(dist, a.r+b.r) or EQ(dist, a.r-b.r)){
        res.push_back(a.p +dir);
    }else if(a.r-b.r < dist and dist < a.r+b.r){
        double cos = (a.r*a.r +dist*dist -b.r*b.r)/(2*a.r*dist);
        double sin = sqrt(1 -cos*cos);
        res.push_back(a.p +dir*P(cos, sin));
        res.push_back(a.p +dir*P(cos, -sin));
    }
    return res;
}

struct DA{
    C c;
    P v[2];
    DA(C c, P s, P t): c(c) { v[0]=s; v[1]=t; }
    DA(){}
};
VP crosspointSDA(const L &l, const DA &da){
    VP cp = crosspointCL(da.c, l);
    VP res;
    for(P &p: cp){
        P v = p - da.c.p;
        if(intersectSP(l, p) and cross(v, da.v[0])*cross(v, da.v[1]) < EPS){
            res.push_back(p);
        }
    }
    return res;
}
VP crosspointDADA(const DA &a, const DA &b){
    VP cp = crosspointCC(a.c, b.c);
    VP res;
    for(P &p: cp){
        P va = p -a.c.p;
        P vb = p -b.c.p;
        if((cross(va, a.v[0]) * cross(va, a.v[1]) < EPS) and
            (cross(vb, a.v[0]) * cross(vb, a.v[1]) < EPS)){
            res.push_back(p);
        }
    }
    return res;
}

void input_P(P &in){
    double x,y;
    cin >> x >> y;
    in = P(x, y);
}
VP make_rect(L l, P e, P d){
    return VP{l[0]-e+d, l[0]-e-d, l[1]+e-d, l[1]+e+d};
}
template<class T>
void insertvec(vector<T> &a, const vector<T> &b){
    a.insert(a.end(), b.begin(), b.end());
}

// from here
const double weps =1e-5;
int rot, n;
double l;
P s, g;
VP dir;
vector<L> wall;
vector<vector<VP>> slide_rect;
vector<vector<VP>> nonrotate_rect;
vector<vector<DA>> nonrotate_da;
vector<VP> cand_rot;
vector<vector<vector<pair<int, int>>>> graph;

void input(){
    cin >> l >> rot;
    l += weps;
    input_P(s);
    input_P(g);
    cin >> n;
    wall.resize(n);
    for(int i=0; i<n; i++){
        for(P &p: wall[i]){
            input_P(p);
        }
    }
}

void misc(){
    dir.resize(rot+1);
    for(int i=0; i<rot+1; i++){
        dir[i] = rotate(P(l, 0), PI/rot *i);
    }
}

void make_slide_rect(){
    slide_rect.resize(rot);
    for(int r=0; r<rot; r++){
        for(L &w: wall){
            P vw = w[1] -w[0];
            if(isParallel(vw, dir[r])){
                slide_rect[r].push_back(make_rect(w, l *unit(vw), weps *unit(rotate(vw, PI/2))));
            }else{
                slide_rect[r].push_back(make_rect(w, weps *unit(vw), (cross(vw, dir[r]) > 0)? dir[r]: -dir[r]));
            }   
        }
    }
}

void make_nonrot_area(){
    nonrotate_rect.resize(rot);
    nonrotate_da.resize(rot);
    for(int r=0; r<rot; r++){
        for(int i=0; i<n; i++){
            nonrotate_rect[r].push_back(slide_rect[r][i]);
            nonrotate_rect[r].push_back(slide_rect[(r+1)%rot][i]);
            P vert = rotate(wall[i][1] -wall[i][0], PI/2);
            if(cross(vert, dir[r]) * cross(vert, dir[r+1]) < -EPS){
                nonrotate_rect[r].push_back(make_rect(wall[i], P(0, 0), l*unit(vert)));
            }
            nonrotate_da[r].emplace_back(C(wall[i][0], l), dir[r], dir[r+1]);
            nonrotate_da[r].emplace_back(C(wall[i][1], l), dir[r], dir[r+1]);
        }
    }
}

void enum_rotate_candidate(){
    cand_rot.resize(rot);
    for(int r=0; r<rot; r++){
        vector<L> w;
        for(VP v: nonrotate_rect[r]){
            int n = v.size();
            for(int i=0; i<n; i++){
                w.emplace_back(v[i], v[(i+1)%n]);
            }
        }
        auto &arc = nonrotate_da[r];
        auto &cand = cand_rot[r];
        int n = w.size();
        int m = arc.size();
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                if(strictItsSS(w[i], w[j])){
                    cand.push_back(crosspointLL(w[i], w[j]));
                }
            }
        }
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                insertvec(cand, crosspointSDA(w[i], arc[j]));
            }
        }
        for(int i=0; i<m; i++){
            for(int j=i+1; j<m; j++){
                insertvec(cand, crosspointDADA(arc[i], arc[j]));
            }
        }
        sort(cand.begin(), cand.end());
        cand.erase(unique(cand.begin(), cand.end()), cand.end());
    } 
}

void eliminate_nonrot_point(){
    vector<VP> res(rot);
    for(int r=0; r<rot; r++){
        auto &cand = cand_rot[r];
        for(P p: cand){
            bool enable = true;
            for(VP &rect: nonrotate_rect[r]){
                if(isInConvex(p, rect)){
                    enable = false;
                }
            }
            for(DA &da: nonrotate_da[r]){
                if((abs(p -da.c.p) +EPS < l) and (cross(p -da.c.p, da.v[0]) * cross(p -da.c.p, da.v[1]) < EPS)){
                    enable = false;
                }
            }
            if(enable){
                res[r].push_back(p);
            }
        }
    }
    cand_rot = res;
}

bool cansee(P s, P g, const vector<VP> &rects){
    P mid = (s + g) /2.0;
    for(VP rect: rects){
        if(isInConvex(mid, rect)) return false;
        for(int i=0; i<4; i++){
            if(strictItsSS(L(rect[i], rect[(i+1)%4]), L(s, g))){
                return false;
            }
        }
    }
    return true;
}

void make_visible_graph(){
    graph = vector<vector<vector<pair<int, int>>>>(rot);
    vector<VP> vlist(rot, VP{s,g});
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        for(VP rect: slide_rect[r]){
            insertvec(v, rect);
        }
        insertvec(v, cand_rot[r]);
        insertvec(v, cand_rot[(r-1+rot)%rot]);
    }
    for(int r=0; r<rot; r++){
        auto &v = vlist[r];
        graph[r].resize(v.size());
        for(size_t i=0; i<v.size(); i++){
            for(size_t j=i+1; j<v.size(); j++){
                if(cansee(v[i], v[j], slide_rect[r])){
                    graph[r][i].emplace_back(r, j);
                    graph[r][j].emplace_back(r, i);
                }
            }
        }
        for(size_t i=0; i<cand_rot[r].size(); i++){
            graph[r][i +4*n +2].emplace_back((r+1)%rot, i +4*n +2 +cand_rot[(r+1)%rot].size());
        }
    }
}

int shortest_path(){
    const int inf = 1e9;
    using pii = pair<int, int>;
    deque<pii> wait;
    vector<vector<int>> mincost(rot, vector<int>(10000, inf));
    mincost[0][0] = 0;
    wait.push_front(pii(0, 0));
    while(!wait.empty()){
        pii curr = wait.front();
        wait.pop_front();
        int cr=curr.first, ci=curr.second;
        if(ci == 1) return mincost[cr][ci];
        for(auto next: graph[cr][ci]){
            int nr=next.first, ni=next.second;
            int cost = (cr==nr)? 0: 1;
            if(mincost[cr][ci] + cost < mincost[nr][ni]){
                mincost[nr][ni] = mincost[cr][ci] + cost;
                if(cost == 0) wait.push_front(pii(nr, ni));
                else wait.push_back(pii(nr, ni));
            }
        }
    }
    return -1;
}

int main(){
    input();
    misc();
    make_slide_rect();
    make_nonrot_area();
    enum_rotate_candidate();
    eliminate_nonrot_point();
    make_visible_graph();
    cout << shortest_path() << endl;
    return 0;
}
accuracy: 1
time_ms: 2960
memory_kb: 6044
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public array<point, 2> {
	segment(const point &a, const point &b) {
		at(0) = a;
		at(1) = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1[1] - s1[0], s2[1] - s2[0]);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s[0] - p;
	auto b = s[1] - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) == -1 &&
		ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) == -1;
}
point projection(const segment &l, const point &p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + t*(l[0] - l[1]);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) + EPS <= 0 && EPS < imag(b))
			if (cross(a, b) < 0) in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) <= EPS) return 1;
	}
	return in ? 2 : 0;
}
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l[1] - l[0]) * sqrt(c.r * c.r - dist * dist) / abs(l[1] - l[0]);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now[0];
		point B = now[1];
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = seg_list[i][j];
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 5860
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment {
	point first, second;
	segment(const point &a, const point &b) {
		first = a;
		second = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1.SE - s1.FI, s2.SE - s2.FI);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a.SE - a.FI, b.SE - b.FI);
}

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s.FI - p;
	auto b = s.SE - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) <= 0 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) == -1 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) == -1;
}
point projection(const segment &l, const point &p) {
	double t = dot(p - l.FI, l.FI - l.SE) / norm(l.FI - l.SE);
	return l.FI + t*(l.FI - l.SE);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) + EPS <= 0 && EPS < imag(b))
			if (cross(a, b) < 0) in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) <= EPS) return 1;
	}
	return in ? 2 : 0;
}
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l.SE - l.FI, m.SE - m.FI);
	double B = cross(l.SE - l.FI, l.SE - m.FI);
	if (abs(A) < EPS && abs(B) < EPS) return m.FI; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m.FI + B / A * (m.SE - m.FI);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l.SE - l.FI) * sqrt(c.r * c.r - dist * dist) / abs(l.SE - l.FI);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now.FI;
		point B = now.SE;
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = (j == 0 ? seg_list[i].FI : seg_list[i].SE);
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 5844
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;
//--------geometry original ------------------
#define curr(PP, i) PP[i]
#define next(PP, i) PP[(i+1)%PP.size()]
#define diff(PP, i) (next(PP, i) - curr(PP, i))
#define eq(n,m) (abs((n)-(m)) < EPS)

typedef long long ll;
typedef pair<ll, ll> P;

const double EPS = 1e-8;
const double EPS_GIG = 1e-3;
const double PI = acos(-1.0);
typedef complex<double> point;
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}

	bool operator == (const point& a,const point& b) {
		return (abs(a.real() - b.real()) < EPS && abs(a.imag() - b.imag()) < EPS);
	}
}
struct circle {
	point p; double r;
	circle(){}
	circle(const point &p, double r) : p(p), r(r) { }
};

// 扇型、中心と半径、二つの端点
// 現在中心角が180未満の前提
struct sector {
	point o;
	point a, b;
	double r;
	sector(){}
	sector(point O, point A, point B, double _r) :o(O), a(A), b(B), r(_r) {}
};

struct segment : public pair<point, point> {
	segment(const point &a, const point &b) {
		first = a;
		second = b;
	}
};

double cross(const point& a, const point& b) {
	return imag(conj(a)*b);
}

double dot(const point& a, const point& b) {
	return real(conj(a)*b);
}

//なす角(vector)
double angle(const point &a,const point &b) {
	auto tmp = abs(arg(a) - arg(b));
	return min(tmp, 2 * PI - tmp);
}

double angle(const segment &s1,const segment &s2) {
	return angle(s1.SE - s1.FI, s2.SE - s2.FI);
}

//並行
bool isParallel(const point &a, const point &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const segment &a, const segment &b){
    return isParallel(a.SE - a.FI, b.SE - b.FI);
}

int ccw(point a, point b, point c) {
	b -= a; c -= a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) + EPS < 0)   return -1;       // clockwise
	if (dot(b, c) - EPS < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
bool intersectSP(const segment &s, const point &p) {
	auto a = s.FI - p;
	auto b = s.SE - p;
	return (abs(cross(a, b)) < EPS && dot(a, b) <= EPS); // triangle inequality
}
bool intersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) <= 0 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) <= 0;
}
//端点の交差hは考えない
bool strictIntersectSS(const segment &s, const segment &t) {
	return ccw(s.FI, s.SE, t.FI) * ccw(s.FI, s.SE, t.SE) == -1 &&
		ccw(t.FI, t.SE, s.FI) * ccw(t.FI, t.SE, s.SE) == -1;
}
point projection(const segment &l, const point &p) {
	double t = dot(p - l.FI, l.FI - l.SE) / norm(l.FI - l.SE);
	return l.FI + t*(l.FI - l.SE);
}
double distanceLP(const segment &l, const point &p) {
	return abs(p - projection(l, p));
}
int contains(const vector<point>& Poly, const point& p) {
	bool in = false;
	for (int i = 0; i < Poly.size(); ++i) {
		point a = curr(Poly, i) - p, b = next(Poly, i) - p;
		if (imag(a) > imag(b)) swap(a, b);
		if (imag(a) + EPS <= 0 && EPS < imag(b))
			if (cross(a, b) < 0) in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) <= EPS) return 1;
	}
	return in ? 2 : 0;
}
int contain_sector(const sector &sec, point &p){
	if(eq(abs(p - sec.o), sec.r))return 1;
	if(intersectSP(segment(sec.o, sec.a), p))return 1;
	if(intersectSP(segment(sec.o, sec.b), p))return 1;
	if(abs(p - sec.o) + EPS > sec.r)return 0;
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(angle(vec, vecA) + EPS < angle(vecA, vecB) && angle(vec, vecB) + EPS < angle(vecA, vecB))return 2;
	return 0;
}

//交点
point crosspointSS(const segment &l, const segment &m) {
	double A = cross(l.SE - l.FI, m.SE - m.FI);
	double B = cross(l.SE - l.FI, l.SE - m.FI);
	if (abs(A) < EPS && abs(B) < EPS) return m.FI; // same line
	if (abs(A) < EPS) return point(INF,INF); // !!!PRECONDITION NOT SATISFIED!!!
	return m.FI + B / A * (m.SE - m.FI);
}

vector<point> crosspointCL(const circle &c, const segment &l) {
	auto ret = vector<point>(2, point(INF, INF));
	auto pro_p = projection(l, c.p);
	auto dist = distanceLP(l, c.p);
	if(abs(dist - c.r) < EPS){
		ret[0] = pro_p;
		return ret;
	}
	if(c.r < dist){
		return ret;
	}
	point vec = (l.SE - l.FI) * sqrt(c.r * c.r - dist * dist) / abs(l.SE - l.FI);
	ret[0] = pro_p + vec;
	ret[1] = pro_p - vec;
	return ret;
}

vector<point> crosspointCC(const circle c1, const circle c2) {
	auto ret = vector<point>(2, point(INF, INF));
	auto dist = abs(c2.p - c1.p);
	if(eq(dist, c1.r + c2.r) || eq(dist, abs(c2.r - c1.r))){
		auto tmp = c2.p - c1.p;
		ret[0] = c1.p + tmp * (c1.r / dist);
		return ret;
	}
	if(c1.r + c2.r < dist || dist < abs(c1.r - c2.r)){
		return ret;
	}
	auto alpha = acos((c1.r * c1.r + dist * dist - c2.r * c2.r) / (2 * c1.r * dist));
	auto theta = atan2(c2.p.imag() - c1.p.imag(), c2.p.real() - c1.p.real());
	ret[0] = c1.p + point(cos(theta + alpha) * c1.r, sin(theta + alpha) * c1.r);
	ret[1] = c1.p + point(cos(theta - alpha) * c1.r, sin(theta - alpha) * c1.r);
	return ret;
}

bool isOnSector(const sector sec, const point p) {
	point vec = p - sec.o;
	point vecA = sec.a - sec.o;
	point vecB = sec.b - sec.o;
	if(eq(angle(vec, vecA) + angle(vec, vecB), angle(vecA, vecB)))return true;
	return false;
}

vector<point> crosspointSecS(const sector sec, const segment s) {
	circle c = circle(sec.o, sec.r);
	auto ret = crosspointCL(c, s);
	point inf = point(INF, INF);
	REP(i, 2){
		if(eq(ret[i], inf))continue;
		if(!isOnSector(sec, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!intersectSP(s, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
vector<point> crosspointSecSec(const sector sec1, const sector sec2) {
	circle c1 = circle(sec1.o, sec1.r);
	circle c2 = circle(sec2.o, sec2.r);
	auto ret = crosspointCC(c1, c2);
	point inf = point(INF, INF);
	REP(i, 2){
		if(!isOnSector(sec1, ret[i])){
			ret[i] = inf;
			continue;
		}
		if(!isOnSector(sec2, ret[i])){
			ret[i] = inf;
		}
	}
	return ret;
}
//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	for (int i = n-2, t = k+1;i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) == -1) --k;
	ch.resize(k - 1);
	return ch;
}

double L, sx, sy, gx, gy;
int point_size = 0, n, r;
vector<int> dist(10000);
vector<int> goal_list;
vector<segment> seg_list;
vector<vector<P>> v(10000);
// 各回転時点での点候補(点, id)
vector<vector<pair<point, int>>> r_point_list(20);
// 回転代表点でないものの点数
vector<int> r_def_point_size(20);
// 各回転時点での四角形
vector<vector<vector<point>>> r_square_list(20);
vector<vector<vector<point>>> r_square_beta_list(20);
// 各回転時点での線分
vector<vector<segment>> r_segment_list(20);
vector<vector<segment>> r_segment_beta_list(20);
// 各回転時点での扇
vector<vector<sector>> r_sector_list(20);

bool can_rotate(point p, int rad_num);
bool check_visible(point p_a, point p_b, int rad_num);

bool add_point_list(int rad_num, point p){
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	r_point_list[rad_num].EB(p, point_size);
	point_size++;
	return true;
}

void make_r_segment_list_square_list(int rad_num) {
	double rad = (double)rad_num * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(seg_num, n) {
		segment now = seg_list[seg_num];
		point A = now.FI;
		point B = now.SE;
		point now_v = A - B;
		vector<point> tmp;
		if (isParallel(now_v,vec)) {
			vec = point(cos(rad), sin(rad)) * L;
			point rotated_vec = point(-sin(rad), cos(rad)) * EPS_GIG;
			point C, D;
			if(abs(A - (B + vec)) > abs(A - (B - vec)))C = B + vec;
			else C = B - vec;
			if(abs(B - (A + vec)) > abs(B - (A - vec)))D = A + vec;
			else D = A - vec;

			tmp.PB(C + rotated_vec);
			tmp.PB(C - rotated_vec);
			tmp.PB(D + rotated_vec);
			tmp.PB(D - rotated_vec);
		}
		else {
			auto eps_vec = now_v * EPS_GIG / abs(now_v);
			tmp.PB(A + vec + eps_vec);
			tmp.PB(A - vec + eps_vec);
			tmp.PB(B + vec - eps_vec);
			tmp.PB(B - vec - eps_vec);
		}

		tmp = convex_hull(tmp);
		r_square_list[rad_num].EB(tmp);
		REP(i, 4) {
			r_segment_list[rad_num].EB(tmp[i], tmp[(i + 1) % 4]);
		}

		point rotated_vec = now_v * point(0, 1) * (L / abs(now_v));
		if(ccw(point(0, 0), vec, rotated_vec) * ccw(point(0, 0), next_vec, rotated_vec) == -1) {
			vector<point> beta;
			beta.PB(A + rotated_vec);
			beta.PB(A - rotated_vec);
			beta.PB(B + rotated_vec);
			beta.PB(B - rotated_vec);
			auto square_beta = convex_hull(beta);
			r_square_beta_list[rad_num].PB(square_beta);
			REP(i, 4){
				r_segment_beta_list[rad_num].EB(square_beta[i], square_beta[(i+1)%4]);
			}
		}
	}
}

void make_r_sector_list(int rad_num){
	double rad = (double)rad_num * PI / r;
	double next_rad = (double)(rad_num + 1) * PI / r;
	point vec = point(cos(rad), sin(rad)) * L;
	point next_vec = point(cos(next_rad), sin(next_rad)) * L;

	REP(i, seg_list.size()){
		REP(j, 2){
			auto p = (j == 0 ? seg_list[i].FI : seg_list[i].SE);
			auto sec = sector(p, p + vec, p + next_vec, L);
			r_sector_list[rad_num].EB(sec);
			sec = sector(p, p - vec, p - next_vec, L);
			r_sector_list[rad_num].EB(sec);
		}
	}
}

void make_r_point_list(int rad_num) {
	add_point_list(rad_num, point(sx, sy));
	if(add_point_list(rad_num, point(gx, gy))){
		goal_list.EB(point_size-1);
	}

	REP(i, r_segment_list[rad_num].size()){
		auto seg_a = r_segment_list[rad_num][i];
		REP(j, i){
			auto seg_b = r_segment_list[rad_num][j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p = crosspointSS(seg_a, seg_b);
			add_point_list(rad_num, p);
		}
	}
	REP(i, r_square_list[rad_num].size()){
		REP(j, 4){
			add_point_list(rad_num, r_square_list[rad_num][i][j]);
		}
	}
	r_def_point_size[rad_num] = r_point_list[rad_num].size();
}

void add_rotate_point(point p_a, int id_a, int rad_num){
	int next_rad = (rad_num + 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_b = r_point_list[rad_num][i].FI;
		auto id_b = r_point_list[rad_num][i].SE;
		if(check_visible(p_a, p_b, rad_num)){
			v[id_b].EB(id_a, 0);
			v[id_a].EB(id_b, 0);
		}
	}
	REP(i, r_def_point_size[next_rad]){
		auto p_b = r_point_list[next_rad][i].FI;
		auto id_b = r_point_list[next_rad][i].SE;
		if(check_visible(p_a, p_b, next_rad)){
			v[id_a].EB(id_b, 1);
		}
	}
}

void make_rotate_pointSS(vector<segment> &seg_list_a,
						 vector<segment> &seg_list_b,
						 int rad_num) {
	REP(i, seg_list_a.size()) {
		auto seg_a = seg_list_a[i];
		REP(j, seg_list_b.size()){
			auto seg_b = seg_list_b[j];
			if(!intersectSS(seg_a, seg_b))continue;
			auto p_a = crosspointSS(seg_a, seg_b);
			if(!can_rotate(p_a, rad_num))continue;
			auto id_a = point_size;
			add_point_list(rad_num, p_a);
			add_rotate_point(p_a, id_a, rad_num);
		}
	}
}

void make_rotate_pointSecS(vector<sector> &sec_list,
						   vector<segment> & seg_list,
					       int rad_num) {
    REP(i, sec_list.size()){
	    auto sc1 = sec_list[i];
	    point inf = point(INF, INF);
		REP(j, seg_list.size()){
			auto seg = seg_list[j];
			auto tmp = crosspointSecS(sc1, seg);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

void make_rotate_point(int rad_num) {
	int next_rad = (rad_num + 1) % r;
	int pre_rad = (rad_num + r - 1) % r;
	REP(i, r_def_point_size[rad_num]){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		if(can_rotate(p_a, rad_num)){
			REP(j, r_def_point_size[next_rad]){
				auto p_b = r_point_list[next_rad][j].FI;
				auto id_b = r_point_list[next_rad][j].SE;
				if(check_visible(p_a, p_b, next_rad)){
					v[id_a].EB(id_b, 1);
				}
			}
		}
		if(can_rotate(p_a, pre_rad)){
			REP(j, r_def_point_size[pre_rad]){
				auto p_b = r_point_list[pre_rad][j].FI;
				auto id_b = r_point_list[pre_rad][j].SE;
				if(check_visible(p_a, p_b, pre_rad)){
					v[id_b].EB(id_a, 1);
				}
			}
		}
	}
	make_rotate_pointSS(r_segment_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSS(r_segment_beta_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[rad_num], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_list[next_rad], rad_num);
	make_rotate_pointSecS(r_sector_list[rad_num], r_segment_beta_list[rad_num], rad_num);
	REP(i, r_sector_list[rad_num].size()){
		auto sc1 = r_sector_list[rad_num][i];
		point inf = point(INF, INF);
		REP(j, i){
			auto sc2 = r_sector_list[rad_num][j];
			auto tmp = crosspointSecSec(sc1, sc2);
			REP(ii, 2){
				if(eq(inf, tmp[ii]))continue;
				if(!can_rotate(tmp[ii], rad_num))continue;
				auto p_a = tmp[ii];
				auto id_a = point_size;
				add_point_list(rad_num, p_a);
				add_rotate_point(p_a, id_a, rad_num);
			}
		}
	}
}

bool check_visible(point p_a, point p_b, int rad_num) {
	segment seg = segment(p_a, p_b);
	point mid = (p_a + p_b) * 0.5;
	REP(i, r_square_list[rad_num].size()){
		int cou = 0;
		bool flag = false;
		auto sq = r_square_list[rad_num][i];
		if(contains(sq, mid) == 2)return false;
		REP(j, 4){
			segment tmp_seg = segment(sq[j], sq[(j+1)%4]);
			if(strictIntersectSS(seg, tmp_seg))return false;
		}
	}
	return true;
}

void make_visible_graph(int rad_num) {
	REP(i, r_point_list[rad_num].size()){
		auto p_a = r_point_list[rad_num][i].FI;
		auto id_a = r_point_list[rad_num][i].SE;
		REP(j, i){
			auto p_b = r_point_list[rad_num][j].FI;
			auto id_b = r_point_list[rad_num][j].SE;
			if(check_visible(p_a, p_b, rad_num)){
				v[id_a].EB(id_b, 0);
				v[id_b].EB(id_a, 0);
			}
		}
	}
}

bool can_rotate(point p, int rad_num) {
	int next_rad = (rad_num + 1) % r;
	REP(i, r_square_list[rad_num].size()){
		if(contains(r_square_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_beta_list[rad_num].size()){
		if(contains(r_square_beta_list[rad_num][i], p) == 2)return false;
	}
	REP(i, r_square_list[next_rad].size()){
		if(contains(r_square_list[next_rad][i], p) == 2)return false;
	}
	REP(i, r_sector_list[rad_num].size()){
		auto sec = r_sector_list[rad_num][i];
		if(contain_sector(sec, p) == 2)return false;
	}
	return true;
}

int Dijkstra() {
	priority_queue<P, vector<P>, greater<>> pq;
	pq.push(MP(0, 0));

	while(!pq.empty()){
		int d = pq.top().FI;
		int id = pq.top().SE;
		pq.pop();
		REP(i, v[id].size()){
			int aite = v[id][i].FI;
			int cost = v[id][i].SE;
			if(dist[aite] > d + cost){
				dist[aite] = d + cost;
				pq.push(MP(dist[aite], aite));
			}
		}
	}

	int ret = INF;
	REP(i, goal_list.size()){
		ret = min(ret, dist[goal_list[i]]);
	}
	return ret;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
	cin >> L >> r;L += EPS_GIG;
	cin >> sx >> sy;
	cin >> gx >> gy;

	cin >> n;
	REP(i, n){
		double x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;
		seg_list.EB(point(x1, y1), point(x2, y2));
	}

	REP(i, r){
		make_r_segment_list_square_list(i);
		make_r_sector_list(i);
	}
	REP(i, r){
		make_r_point_list(i);
	}
	REP(i, r){
		make_visible_graph(i);
	}
	REP(i, r){
		make_rotate_point(i);
	}

	REP(i, point_size)dist[i] = INF;
	dist[0] = 0;
	int ans = Dijkstra();

	if(ans == INF)cout << -1 << endl;
	else cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 5884
final_rank: 9