#include #include // 25-4-2 // Na prvním řádku dostaneme čísla M a N. // Na následujících M řádcích pak máme mapu: // S značí start // C je cíl // . odpovídá volnému políčku // # je překážka /* Příklad vstupu: 5 4 ...S .#.. ...# .#.. .C.. */ // typ datové struktury pro vkládání do fronty typedef struct t_vrchol { int i, j; } t_vrchol; int M, N; // rozměry vstupu int start_i, start_j; // startovní souřadnice int **mapa; // vstupní mapa // vzdálenosti od překážek int **vzdalenost_levo; // Udává o kolik políček můžeme jít doleva. int **vzdalenost_pravo; int **vzdalenost_nahore; int **vzdalenost_dole; t_vrchol *fronta; int delka_fronty; int prvni_prvek; // Pro každý vrchol (políčko u překážky) si pamatujeme int **pocet_zatacek; int **pocet_policek; int **odkud_jsme_prisli_i; int **odkud_jsme_prisli_j; int **odkud_jsme_prisli_smer; // Jakým smérem jsme se vydali na předchozí zatáčce. int** vytvor_pole() { int i; int **p; p = calloc(M, sizeof(int*)); for (i = 0; i < M; i++) p[i] = calloc(N, sizeof(int)); return p; } // Pro prohlížení obsahu polí se hodí tato funkce. void vypis_mapu(int **p) { int i, j; for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { printf("%2i ", p[i][j]); } printf("\n"); } printf("\n"); } void nacti_mapu() { int i, j; for (i = 0; i < M; i++) { scanf("\n"); for (j = 0; j < N; j++) { char val; scanf("%c", &val); if (val == '#') // překážka mapa[i][j] = -1; else if (val == '.') // volné políčko mapa[i][j] = 0; else if (val == 'C') // cíl mapa[i][j] = 2; else if (val == 'S') { // start mapa[i][j] = 1; start_i = i; start_j = j; } } } } void spocitej_vzdalenosti() { int i, j; // levá překážka for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { if (j != 0) // pokud nejsme na kraji mapy vzdalenost_levo[i][j] = vzdalenost_levo[i][j-1] + 1; if (mapa[i][j] == -1) // překážka vzdalenost_levo[i][j] = -1; if (mapa[i][j] == 2) // cíl vzdalenost_levo[i][j] = 0; } } // pravá překážka for (i = 0; i < M; i++) { for (j = N-1; j >= 0; j--) { if (j != N-1) vzdalenost_pravo[i][j] = vzdalenost_pravo[i][j+1] + 1; if (mapa[i][j] == -1) vzdalenost_pravo[i][j] = -1; if (mapa[i][j] == 2) vzdalenost_pravo[i][j] = 0; } } // horní překážka for (i = 0; i < M; i++) { for (j = 0; j < N; j++) { if (i != 0) vzdalenost_nahore[i][j] = vzdalenost_nahore[i-1][j] + 1; if (mapa[i][j] == -1) vzdalenost_nahore[i][j] = -1; if (mapa[i][j] == 2) vzdalenost_nahore[i][j] = 0; } } // dolní překážka for (i = M-1; i >= 0; i--) { for (j = 0; j < N; j++) { if (i != M-1) vzdalenost_dole[i][j] = vzdalenost_dole[i+1][j] + 1; if (mapa[i][j] == -1) vzdalenost_dole[i][j] = -1; if (mapa[i][j] == 2) vzdalenost_dole[i][j] = 0; } } } void vloz_do_fronty(int i, int j) { fronta[prvni_prvek + delka_fronty].i = i; fronta[prvni_prvek + delka_fronty].j = j; delka_fronty++; } void vloz_pokud_muzes(int i, int j, int zatacky, int policka, int odkud_i, int odkud_j, char smer) { // vložení políčka, na kterém zatáčíme do fronty, pokud jsme jej ještě do fronty nevložili if (pocet_zatacek[i][j] == 0) { pocet_zatacek[i][j] = zatacky; pocet_policek[i][j] = policka; odkud_jsme_prisli_i[i][j] = odkud_i; odkud_jsme_prisli_j[i][j] = odkud_j; odkud_jsme_prisli_smer[i][j] = smer; vloz_do_fronty(i, j); } // výběr nejkratší trasy při stejném počtu zatáček, do fronty již nevkládáme if ((pocet_zatacek[i][j] == zatacky) && (pocet_policek[i][j] > policka)) { pocet_zatacek[i][j] = zatacky; pocet_policek[i][j] = policka; odkud_jsme_prisli_i[i][j] = odkud_i; odkud_jsme_prisli_j[i][j] = odkud_j; odkud_jsme_prisli_smer[i][j] = smer; } } void vypis_trasu(int i, int j) { if (mapa[i][j] != 1) { vypis_trasu(odkud_jsme_prisli_i[i][j], odkud_jsme_prisli_j[i][j]); printf("%c", odkud_jsme_prisli_smer[i][j]); } } int main() { scanf("%d %d", &M, &N); // příprava paměti mapa = vytvor_pole(); vzdalenost_levo = vytvor_pole(); vzdalenost_pravo = vytvor_pole(); vzdalenost_nahore = vytvor_pole(); vzdalenost_dole = vytvor_pole(); pocet_zatacek = vytvor_pole(); pocet_policek = vytvor_pole(); odkud_jsme_prisli_i = vytvor_pole(); // Abychom mohli cestu nakonec vypsat odkud_jsme_prisli_j = vytvor_pole(); odkud_jsme_prisli_smer = vytvor_pole(); nacti_mapu(); spocitej_vzdalenosti(); // Příprava fronty fronta = calloc(M*N, sizeof(t_vrchol)); // máme zaručeno, že do fronty nikdy nepřidáme víc, než M*N vrcholů delka_fronty = 0; prvni_prvek = 0; // Startovní políčko vložíme do fronty pocet_zatacek[start_i][start_j] = 1; vloz_do_fronty(start_i, start_j); while (delka_fronty) { int i = fronta[prvni_prvek].i; int j = fronta[prvni_prvek].j; prvni_prvek++; delka_fronty--; if (mapa[i][j] == 2) // Cíl break; vloz_pokud_muzes(i, j - vzdalenost_levo[i][j], pocet_zatacek[i][j] + 1, pocet_policek[i][j] + vzdalenost_levo[i][j], i, j, 'L'); vloz_pokud_muzes(i, j + vzdalenost_pravo[i][j], pocet_zatacek[i][j] + 1, pocet_policek[i][j] + vzdalenost_pravo[i][j], i, j, 'P'); vloz_pokud_muzes(i - vzdalenost_nahore[i][j], j, pocet_zatacek[i][j] + 1, pocet_policek[i][j] + vzdalenost_nahore[i][j], i, j, 'N'); vloz_pokud_muzes(i + vzdalenost_dole[i][j], j, pocet_zatacek[i][j] + 1, pocet_policek[i][j] + vzdalenost_dole[i][j], i, j, 'D'); } //výpis cesty prvni_prvek--; if (mapa[fronta[prvni_prvek].i][fronta[prvni_prvek].j] == 2) { vypis_trasu(fronta[prvni_prvek].i, fronta[prvni_prvek].j); printf("\n"); } else printf("Cesta neexistuje\n"); return 0; }