#include #include #include using std::queue; using std::min; #define MAX 1234 const int dx[4] = { -1, 0, +1, 0 }; const int dy[4] = { 0, -1, 0, +1 }; typedef struct { int x, y, d; } Vertex; char buffer[MAX]; // Mapa bludiska bool Map[MAX][MAX]; // Navstivene vrcholy v prehladavani bool Vis[MAX][MAX]; // najkratsia vzdialenost do vrchola int Dist[MAX][MAX][4]; // uroven pri hladani dvoj-suvislych komponentov int Level[MAX][MAX]; // najnizsia uroven na ktoru sa da z vrcholu dostat // pri hladani dvoj-suvislych komponentov int MinLevel[MAX][MAX]; // cislo komponenty dvoj-suvislosti do ktorej // patri hrana z daneho vrchola iduca v smere d int Comp[MAX][MAX][4]; // farba vrcholu pri prehladavani do hlbky // 0 - nenavstiveny vrchol // 1 - vrchol na zasobniku // 2 - opusteny vrchol int Color[MAX][MAX]; // pocitadlo komponentov dcoj-suvislosti int Counter; // fronta pri prehladavani do sirky queue Q; // spocita najnizsiu uroven na ktoru sa da z vrchola // dostat pri hladani dvoj-suvislych komponentov int GetLevel(int x, int y, int level) { if (!Map[y][x]) return level; if (Level[y][x]) return Level[y][x]; MinLevel[y][x] = Level[y][x] = level; for (int i = 0; i < 4; i++) { int child = GetLevel(x+dx[i],y+dy[i], Level[y][x]+1); MinLevel[y][x] = min(MinLevel[y][x],child); } return MinLevel[y][x]; } // na zaklade najnizsej urovne na ktoru sa vie vrchol dostat // nastavi hranam cisla dvoj-suvislosti void SetLabels(int x, int y, int label) { Color[y][x] = 1; for (int i = 0; i < 4; i++) { int px = x+dx[i], py = y+dy[i]; if (Map[py][px] && Color[py][px] < 2) { Comp[y][x][i] = label; if (MinLevel[py][px] >= Level[y][x]) Comp[y][x][i] = ++Counter; Comp[y+dy[i]][x+dx[i]][(i+2)&3] = Comp[y][x][i]; if (Color[py][px] == 0) SetLabels(px,py, Comp[y][x][i]); } } Color[y][x] = 2; } // prehladavanie do hlbky (zistime dosiahnutelnost vrcholov) void DFS(int x, int y) { if (!Map[y][x] || Vis[y][x]) return; Vis[y][x] = true; for (int i = 0; i < 4; i++) DFS(x+dx[i],y+dy[i]); } // vlozi do fronty novy vrchol pri prehladavani do sirky void Insert(int x, int y, int d, int dist) { if (Map[y][x] && Dist[y][x][d] == -1) { Dist[y][x][d] = dist; Vertex v = { x,y,d }; Q.push(v); } } int main() { int X, Y, sx, sy, tx, ty, kx, ky; scanf("%d %d\n", &Y, &X); // inicializovat premenne Counter = 0; for (int y = 0; y <= Y+1; y++) { for (int x = 0; x <= X+1; x++) { Map[y][x] = Vis[y][x] = false; Level[y][x] = MinLevel[y][x] = Color[y][x] = 0; for (int i = 0; i < 4; i++) { Comp[y][x][i] = 0; Dist[y][x][i] = -1; } } } // nacitat vstup for (int y = 1; y <= Y; y++) { scanf("%s", buffer); for (int x = 1; x <= X; x++) { Map[y][x] = true; switch(buffer[x-1]) { case '#': Map[y][x] = false; break; case 'H': kx = x, ky = y; break; case 'O': sx = x, sy = y; break; case 'P': tx = x, ty = y; break; } } getchar(); } // oznackovat hrany cislom prislusnej // dvoj-suvislej komponenty GetLevel(kx,ky,1); SetLabels(kx,ky,1); // zistit kam sa moze hrac dostat na zaciatku Map[sy][sx] = false; DFS(kx,ky); Map[sy][sx] = true; // oznacit stavy okolo objektu za pociatocne for (int i = 0; i < 4; i++) if (Vis[sy+dy[i]][sx+dx[i]]) Insert(sx,sy,i,0); bool Found = false; while (!Q.empty()) { // vybrat vrchol z fronty Vertex v = Q.front(); Q.pop(); int dist = Dist[v.y][v.x][v.d]; if (v.x == tx && v.y == ty) { printf("%d\n", dist); Found = true; break; } // zistit na ktore pozicie okolo bedne sa da // dostat a skusit posunut bednu tym smerom for (int i = 0; i < 4; i++) if (Comp[v.y][v.x][v.d] == Comp[v.y][v.x][i]) Insert(v.x-dx[i],v.y-dy[i], i,dist+1); } if (!Found) printf("-1\n"); return 0; }