Salutare si bine v-am regasit, astazi vom raspunde unei propuneri primita pe YouTube.
Enuntul problemei:
Se dă un labirint reprezentat sub forma unei matrici cu n linii şi m coloane, conţinând doar valori 0 şi 1. O succesiune de 1 reprezintă un drum iar o (zero) reprezintă un zid. Dintr-un punct iniţial, a cărui coordonate se citesc, porneşte o persoană. Să se afişeze toate posibilităţile ca acea persoană să ajunga in pozitia finala, ştiind că deplasarea se poate face doar prin valori 1 ale matricei, iar salturile se pot face în stânga, dreapta, jos şi sus.
Ca sa facem un rezumat al problemei, avem:
- Un fisier de intrare, sa-i zicem “labirint.in” in care scriem urmatoarele valori:
5 8 1 1 3 6 0 1 0 0 0 0 1 0 0 1 1 1 1 1 1 0 0 1 0 0 0 0 1 0 1 1 1 1 1 1 1 0 0 0 0 0 1 0 0 0
Cu urmatoarea semnificatie:
- 5 8 – dimensiunile matricei (incepem numaratoarea de la 0, dupa cum v-am obisnuit)
- 1 1 – coordonatele de pornire in matrice
- 3 6 – coordonatele de sosire in matrice
- o succesiune de 1, reprezinta o cale libera
De asemenea, in problema mai mentioneaza si faptul ca deplasarea se face doar in 4 directii:
- Nord: (-1, 0)
- Est: (0, +1)
- Sud: (+1, 0)
- Vest: (0, -1)
Sa trecem la rezolvarea problemei, o sa explic fiecare functie in parte mai jos, si de asemenea o sa fac si o mica animatie, dupa cum v-am obisnuit.
revenim cu edit
Rezolvare problema labirintului:
#include <iostream> #include <fstream> using namespace std; ifstream fin("labirint.in"); const int N_MAX = 2005; const int M_MAX = 2005; int N, M; unsigned int poz_init_X, poz_init_Y; unsigned int poz_finala_X, poz_finala_Y; unsigned int matrice[N_MAX][M_MAX]; const int directii = 4; const int di[directii] = {-1, 0, 1, 0}; const int dj[directii] = {0, 1, 0, -1}; void Citire() { fin >> N >> M; fin >> poz_init_X >> poz_init_Y; fin >> poz_finala_X >> poz_finala_Y; for(int i = 0; i < N; i++) for(int j = 0; j < M; j++) fin >> matrice[i][j]; } bool isOK(int i, int j) { if(i > N || i < 1) return false; if(j > M || j < 1) return false; if(matrice[i][j] == 1 || (i == poz_finala_X && j == poz_finala_Y)) return true; if(matrice[i][j] == 0 || matrice[i][j]) return false; return true; } void afisare() { for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) cout << matrice[i][j] << " "; cout << "\n"; } cout << "\n\n"; } void Rezolvare(int i, int j, int pas) { if(i == poz_finala_X && j == poz_finala_Y) afisare(); else { for(int k = 0; k < directii; k++) { int i_vecin = i + di[k]; int j_vecin = j + dj[k]; if(isOK(i_vecin, j_vecin)) { matrice[i_vecin][j_vecin] = pas; Rezolvare(i_vecin, j_vecin, pas + 1); matrice[i_vecin][j_vecin] = 0; } } } } int main() { Citire(); Rezolvare(poz_init_X, poz_init_Y, 2); return 0; }
Functia bool isOK(int i, int j)
- Primeste ca si parametrii doua numere intregi i si j (sunt numere intregi deoarece pot sa primeasca si -1, altfel le-am fi declarat “unsigned int”)
- Functia noastra verifica prima oara daca noile coordonate sunt in-afara matricei
- Mai apoi, accepta toate casutele ce sunt marcate cu 1 (drum disponibil, inca nevizitat) si de-asemenea casuta de final (casuta de final va avea o valoare diferita de 1, in cazul in care se parcurge a doua oara – a trebuit tratat separat acest caz)
- La final respingem toate casutele de 0 sau casutele diferite de 1 (casute disponibile, dar vizitate)
Functia void Rezolvare(int i, int j, int pas)
- Este o functie recursiva ce parcurge pe rand vecinii, iar mai apoi se intoarce de unde a plecat – similar algoritmului lui Lee
- Aceasta functie verifica pe rand toti cei 4 vecini. In cazul in care casuta poate fi vizitata, aceasta functie o viziteaza, iar cand se intoarce din recursivitate marcheaza casuta cu “0” (drum indisponibil)