#include #define MAX_R 1000 #define MAX_S 1000 #define MAX_PRVKU MAX_R*MAX_S*4+1 /** * Formát vstupu: * Dvě celá čísla R, S udávající počet řádků a sloupců v mřížce * R x 2*S celých čísel, vždy koeficient přehlédnutelnosti při průchodu rovně * a při odbočení na daném políčku * Dvě celá čísla Sr, Ss udávající řádek a sloupeček startu * Dvě celá čísla Cr, Cs udávající řádek a sloupeček cíle * (Indexování od nuly) * * Formát výstupu: * Celé číslo P udávající minimální přehlédnutelnost na cestě * X dvojic [Ri, Si] udávající řádek a sloupeček políčka v příslušném kroku * (Indexování od nuly) **/ enum ctvrtiny { Leva, Horni, Prava, Dolni }; struct souradnice { int r; int s; int c; }; int vzdalenosti[MAX_R][MAX_S][4]; struct souradnice predchudci[MAX_R][MAX_S][4]; int koef_rovne[MAX_R][MAX_S]; int koef_odboc[MAX_R][MAX_S]; struct souradnice halda[MAX_R*MAX_S*4]; int halda_pocet = 0; int halda_umisteni[MAX_R][MAX_S][4]; struct souradnice cesta[MAX_PRVKU], predchozi; void prohod(int index1, int index2) { struct souradnice s1 = halda[index1]; struct souradnice s2 = halda[index2]; halda[index1] = s2; halda[index2] = s1; halda_umisteni[s1.r][s1.s][s1.c] = index2; halda_umisteni[s2.r][s2.s][s2.c] = index1; } void bublej_nahoru(int index) { if (index == 1) return; struct souradnice s_prvek = halda[index]; struct souradnice s_rodic = halda[index / 2]; if (vzdalenosti[s_prvek.r][s_prvek.s][s_prvek.c] < vzdalenosti[s_rodic.r][s_rodic.s][s_rodic.c]) { prohod(index, index/2); bublej_nahoru(index/2); } } void bublej_dolu(int index) { if ((index > MAX_PRVKU/2) || (2*index > halda_pocet)) return; struct souradnice s_prvek = halda[index]; struct souradnice s_syn1 = halda[2*index]; struct souradnice s_syn2 = halda[2*index+1]; int min_vzdalenost, min_index; if ((2*index+1 > halda_pocet) || vzdalenosti[s_syn1.r][s_syn1.s][s_syn1.c] < vzdalenosti[s_syn2.r][s_syn2.s][s_syn2.c]) { min_vzdalenost = vzdalenosti[s_syn1.r][s_syn1.s][s_syn1.c]; min_index = 2*index; } else { min_vzdalenost = vzdalenosti[s_syn2.r][s_syn2.s][s_syn2.c]; min_index = 2*index + 1; } if (min_vzdalenost < vzdalenosti[s_prvek.r][s_prvek.s][s_prvek.c]) { prohod(index, min_index); bublej_dolu(min_index); } } // Funkce zpropaguje zadané souřadnice na správné místo v haldě // Jde-li o nové souřadnice, přidají se; jinak se jen aktualizují (probublají nahoru) // Při změně hodnoty je nutné měnit ji na nižší, jinak bude halda nekorektní void pridej_nebo_sniz(int radek, int sloupec, int c) { if (halda_umisteni[radek][sloupec][c] == 0) { halda_umisteni[radek][sloupec][c] = ++halda_pocet; struct souradnice s_prvek; s_prvek.r = radek; s_prvek.s = sloupec; s_prvek.c = c; halda[halda_pocet] = s_prvek; } bublej_nahoru(halda_umisteni[radek][sloupec][c]); } struct souradnice halda_min() { struct souradnice min = halda[1]; halda[1] = halda[halda_pocet--]; bublej_dolu(1); return min; } void zpracuj(struct souradnice odkud, int kam_r, int kam_s, int kam_c) { int koef = (odkud.c == kam_c ? koef_rovne[odkud.r][odkud.s] : koef_odboc[odkud.r][odkud.s]); if (vzdalenosti[kam_r][kam_s][kam_c] == -1 || (vzdalenosti[odkud.r][odkud.s][odkud.c] + koef < vzdalenosti[kam_r][kam_s][kam_c])) { vzdalenosti[kam_r][kam_s][kam_c] = vzdalenosti[odkud.r][odkud.s][odkud.c] + koef; predchudci[kam_r][kam_s][kam_c] = odkud; pridej_nebo_sniz(kam_r, kam_s, kam_c); } } int main(void) { int r, s; scanf("%d %d", &r, &s); for (int i=0; i 0) { vzdalenosti[start_r][start_s-1][Prava] = 0; predchudci[start_r][start_s-1][Prava] = start; pridej_nebo_sniz(start_r, start_s-1, Prava); } if (start_s < s-1) { vzdalenosti[start_r][start_s+1][Leva] = 0; predchudci[start_r][start_s+1][Leva] = start; pridej_nebo_sniz(start_r, start_s+1, Leva); } if (start_r > 0) { vzdalenosti[start_r-1][start_s][Dolni] = 0; predchudci[start_r-1][start_s][Dolni] = start; pridej_nebo_sniz(start_r-1, start_s, Dolni); } if (start_r < r-1) { vzdalenosti[start_r+1][start_s][Horni] = 0; predchudci[start_r+1][start_s][Horni] = start; pridej_nebo_sniz(start_r+1, start_s, Horni); } while (1) { struct souradnice aktualni = halda_min(); if (aktualni.r == cil_r && aktualni.s == cil_s) { cil_c = aktualni.c; break; } if (aktualni.r > 0) { zpracuj(aktualni, aktualni.r-1, aktualni.s, Dolni); } if (aktualni.r < r-1) { zpracuj(aktualni, aktualni.r+1, aktualni.s, Horni); } if (aktualni.s > 0) { zpracuj(aktualni, aktualni.r, aktualni.s-1, Prava); } if (aktualni.s < s-1) { zpracuj(aktualni, aktualni.r, aktualni.s+1, Leva); } } printf("%d\n", vzdalenosti[cil_r][cil_s][cil_c]); int i = 0; predchozi.r = cil_r; predchozi.s = cil_s; predchozi.c = cil_c; for (; (predchozi.r != start_r || predchozi.s != start_s); i++) { cesta[i] = predchozi; predchozi = predchudci[predchozi.r][predchozi.s][predchozi.c]; } cesta[i] = predchozi; for (; i >= 0; i--) { printf("[%d; %d]\n", cesta[i].r, cesta[i].s); } return 0; }