// #pragma GCC optimize("O3,unroll-loops") #include // #include using namespace std; #if __cplusplus >= 202002L using namespace numbers; #endif template struct dijkstra_dense{ int n; T base_dist; vector dist; vector pv; vector order; vector pos; vector root_of; vector root; vector depth; vector was; dijkstra_dense(T base_dist = T{0}): base_dist(base_dist){ } void init(int n){ this->n = n; dist.assign(n, base_dist); pv.assign(n, -1); order.clear(); pos.assign(n, -1); root_of.assign(n, -1); root.clear(); depth.assign(n, -1); was.assign(n, -2); done.assign(n, false); attempt = -1; } int attempt; vector done; // act_greater(v, u): dist[v] has been updated to larger value by u // act_equal(v, u): dist[v] equals the length of shortest path to v through u // O(n^2) template void _run(const vector> &edge_length, const vector &src, auto act_greater, auto act_equal){ int n = (int)edge_length.size(); for(auto u: src){ if(was[u] == attempt) continue; was[u] = attempt; done[u] = false; dist[u] = base_dist; depth[u] = 0; root_of[u] = u; root.push_back(u); pv[u] = -1; } while(true){ int u = -1; for(auto v = 0; v < n; ++ v) if(was[v] == attempt && !done[v] && (!~u || dist[u] > dist[v])) u = v; if(!~u) break; done[u] = true; pos[u] = (int)order.size(); order.push_back(u); for(auto v = 0; v < n; ++ v) if(~edge_length[u][v]){ if(was[v] != attempt || !done[v] && dist[u] + edge_length[u][v] < dist[v]){ dist[v] = dist[u] + edge_length[u][v]; was[v] = attempt; done[v] = false; depth[v] = depth[u] + 1; pv[v] = u; root_of[v] = root_of[u]; act_greater(v, u); } else if(!done[v] && dist[u] + edge_length[u][v] == dist[v]) act_equal(v, u); } } } // Requires graph template void run(const Graph &g, const vector &src, auto act_greater, auto act_equal){ assert(g.n <= n); if(g.n == 0) return; for(auto u: src) assert(0 <= u && u < g.n); root.clear(), order.clear(); ++ attempt; vector edge_length(g.n, vector(g.n, -1)); for(auto u = 0; u < g.n; ++ u) for(auto id: g.adj[u]){ if(g.ignore && g.ignore(id)) continue; assert(0 <= g.edge[id].cost); int v = g(u, id); edge_length[u][v] = ~edge_length[u][v] ? min(edge_length[u][v], g.edge[id].cost) : g.edge[id].cost; } _run(edge_length, src, act_greater, act_equal); } // Requires graph template void run(const Graph &g, const vector &src){ run(g, src, [&](int, int){ }, [&](int, int){ }); } // edge_length = -1 implies no edge template void run(const vector> &edge_length, const vector &src, auto act_greater, auto act_equal){ int n = (int)edge_length.size(); assert(n <= this->n); for(const auto &row: edge_length) for(auto w: row) assert(-1 <= w); for(auto u: src) assert(0 <= u && u < n); root.clear(), order.clear(); ++ attempt; _run(edge_length, src, act_greater, act_equal); } // edge_length = -1 implies no edge template void run(const vector> &edge_length, const vector &src){ run(edge_length, src, [&](int, int){ }, [&](int, int){ }); } // Check if u is visited during the last dijkstra-like call. bool visited(int u) const{ return was[u] == attempt; } }; int main(){ cin.tie(0)->sync_with_stdio(0); cin.exceptions(ios::badbit | ios::failbit); int nr, nc, n; cin >> nr >> nc >> n; vector> a(n + 2); a[1] = {nr - 1, nc - 1, nr - 1, nc - 1}; for(auto &[p, q, r, s]: a | ranges::views::drop(2)){ cin >> p >> q >> r >> s, -- p, -- q, -- r, -- s; } vector> adjm(n + 2, vector(n + 2, -1)); for(auto u = 0; u <= n + 1; ++ u){ for(auto v = 0; v <= n + 1; ++ v){ if(u != v){ adjm[u][v] = abs(a[u][2] - a[v][0]) + abs(a[u][3] - a[v][1]) + 1; } } } dijkstra_dense D; D.init(n + 2); D.run(adjm, {0}); cout << D.dist[1] - 1 << "\n"; return 0; } /* */