#include #include #include #include #include #include #include #include #include #include #include #define MONS 65535 #define UNIN 65534 #define uin uint8_t void getNums(const std::string in, int **values, uint vcount) { int ccount = 0; std::istringstream iss(in); std::string s; while (getline(iss, s, ' ') && vcount != ccount) { *values[ccount] = std::stoi(s); ccount++; } } struct ivec2 { uin x, y = 0; ivec2(int x, int y) : x(x), y(y) {} ivec2() {} ivec2 operator+(const ivec2 &other) const { return ivec2(x + other.x, y + other.y); } ivec2 operator*(const int &value) const { return ivec2(x * value, y * value); } ivec2 operator/(const int &value) const { return ivec2(x / value, y / value); } friend std::ostream &operator<<(std::ostream &os, const ivec2 &v) { return os << "(" << v.x << ", " << v.y << ")"; } bool operator<(const ivec2 &other) const { return (x < other.x) || (x == other.x && y < other.y); } bool operator>(const ivec2 &other) const { return (x > other.x) || (x == other.x && y > other.y); } bool operator<=(const ivec2 &other) const { return *this < other || *this == other; } bool operator>=(const ivec2 &other) const { return *this > other || *this == other; } bool operator==(const ivec2 &other) const { return (x == other.x && y == other.y) ? true : false; } }; struct Grid { std::unordered_map> xopt, yopt; uint8_t w, h; inline uint16_t getIndex(uint16_t x, uint16_t y) { return y * w + x; } inline ivec2 getCoords(uint16_t index) { return ivec2(index % w, index / w); } int solveslow(uin sx, uin sy, uin dx, uin dy) { std::unordered_set vx, vy; /// this isn't going to be any faster than the prev one, is it? std::vector nindices; // step and pos std::vector cindices; nindices.push_back(getIndex(dx, dy)); int step = 1; while (!nindices.empty()) { cindices = std::move(nindices); for (auto po : cindices) { int found = -1; ivec2 p = getCoords(po); for (auto xpos : xopt[p.y]) { if (vx.count(xpos)) continue; if (true) { if (yopt[xpos].count(sy)) return step + 2; if (step == -1) { for (auto yposs : yopt[xpos]) { if (xopt[yposs].count(sx)) found = step + 3; } } } nindices.push_back(getIndex(xpos, p.y)); } // xopt.erase(p.y); for (auto ypos : yopt[p.x]) { if (vy.count(ypos)) continue; if (true) { if (xopt[ypos].count(sx)) return step + 2; if (step == -1) { for (auto xposs : xopt[ypos]) { if (yopt[xposs].count(sy)) { found = step + 3; } } } } nindices.push_back(getIndex(p.x, ypos)); } if (found != -1) return found; // yopt.erase(p.x); vx.insert(p.x); vy.insert(p.y); } cindices.clear(); step++; } return -1; } int solve(uin sx, uin sy, uin dx, uin dy) { // idk why i'm doing it like this smh. pwease work if (dx == sx && dy == sy) return 0; else if (dx == sx || dy == sy) return 1; if (xopt[sy].size() == 1 && yopt[sx].size() == 1) return -1; if (yopt[dx].size() == 1 && xopt[dy].size() == 1) return -1; if (xopt[sy].count(dx)) return 2; if (yopt[sx].count(dy)) return 2; for (auto xpos : xopt[sy]) { if (yopt[xpos].count(dy)) { return 3; } } for (auto ypos : yopt[sx]) { if (xopt[ypos].count(dx)) return 3; } return solveslow(sx, sy, dx, dy); } }; int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int w, h, c, z; int **vals; vals = new int *[4]; vals[0] = &h; vals[1] = &w; vals[2] = &c; vals[3] = &z; uint qcount = c; std::string line; std::getline(std::cin, line); getNums(line, vals, 3); Grid grid; grid.w = w; grid.h = h; for (int i = 0; i < h && std::getline(std::cin, line); i++) { if (line.size() == 0) continue; for (int x = 0; x < w; x++) { if (line[x] == 46) { grid.yopt[x].insert(i); grid.xopt[i].insert(x); } } } for (int i = 0; std::getline(std::cin, line); i++) { getNums(line, vals, 4); std::cout << grid.solve(w - 1, h - 1, z - 1, c - 1) << "\n"; } // grid.print(); }