diff --git a/graph/grid_graph_template.hpp b/graph/grid_graph_template.hpp index 300e7053..66e5f103 100644 --- a/graph/grid_graph_template.hpp +++ b/graph/grid_graph_template.hpp @@ -5,32 +5,34 @@ #include #include #include +#include // CUT begin -template struct GridGraph { +template struct GridGraph { const int H, W; const std::vector dx{1, -1, 0, 0}; const std::vector dy{0, 0, 1, -1}; + // T_E (*edge_cost)(int, int, int, int); + std::function edge_cost; GridGraph() = default; - GridGraph(int h, int w) : H(h), W(w) {} + GridGraph(int h, int w, std::function _edge_cost) + : H(h), W(w), edge_cost(move(_edge_cost)) {} // Dijkstra's algorithm // Complexity: O(HWlog(HW)) std::vector> dist; // Distance from (x_s, y_s) std::vector>> prv; // Previous node for Dijkstra optimal path - void dijkstra(int x_s, int y_s) { + void dijkstra(int x_s, int y_s) { dijkstra({x_s, y_s}); } + void dijkstra(std::vector> xy_s) { dist.assign(H, std::vector(W, INF)); prv.assign(H, std::vector>(W, std::make_pair(-1, -1))); using P = std::tuple; std::priority_queue, std::greater

> pq; - dist[x_s][y_s] = 0; - pq.emplace(0, x_s, y_s); + for (auto [x_s, y_s] : xy_s) dist[x_s][y_s] = 0, pq.emplace(0, x_s, y_s); while (!pq.empty()) { - T_E dnow; - int x, y; - std::tie(dnow, x, y) = pq.top(); + auto [dnow, x, y] = pq.top(); pq.pop(); if (dist[x][y] < dnow) continue; for (unsigned d = 0; d < dx.size(); d++) { @@ -46,28 +48,29 @@ template struct Gr } } - void bfs_01(int x_s, int y_s) { + void bfs_01(int x_s, int y_s) { bfs_01({x_s, y_s}); } + void bfs_01(std::vector> xy_s) { + std::deque> deq; dist.assign(H, std::vector(W, INF)); prv.assign(H, std::vector>(W, std::make_pair(-1, -1))); - std::deque> deq; - dist[x_s][y_s] = 0; - deq.emplace_back(x_s, y_s); + for (auto [x_s, y_s] : xy_s) dist[x_s][y_s] = 0, deq.emplace_back(x_s, y_s); while (!deq.empty()) { - int x, y; - std::tie(x, y) = deq.front(); - const auto dnow = dist[x][y]; + auto [x, y] = deq.front(); deq.pop_front(); + const auto dnow = dist[x][y]; for (unsigned d = 0; d < dx.size(); d++) { int xn = x + dx[d], yn = y + dy[d]; if (xn < 0 or yn < 0 or xn >= H or yn >= W) continue; - auto dnxt = dnow + edge_cost(x, y, xn, yn); + auto cost = edge_cost(x, y, xn, yn); + auto dnxt = dnow + cost; if (dnxt < dist[xn][yn]) { dist[xn][yn] = dnxt; prv[xn][yn] = std::make_pair(x, y); - if (dnxt) + if (cost > 0) { deq.emplace_back(xn, yn); - else + } else { deq.emplace_front(xn, yn); + } } } }