Documente Academic
Documente Profesional
Documente Cultură
Problemă: Se dă o matrice binară, reprezentând harta unui teren (labirint, clădire, tablă de
joc, etc.), în care valorile 0 reprezintă zone libere, iar cele egale cu 1 reprezintă obstacole.
Într-o zonă aflată la coordonate cunoscute se află un mobil, care se poate deplasa prin
matrice, trecând din zona curenta în una din cele patru zone vecine de pe aceeași linie sau
aceeași coloană, dacă este liberă. Să se identifice zonele în care poate să ajungă mobilul.
Problema enunțată mai sus face parte din categoria Algoritmilor de umplere sau FILL, iar
prezentul articol este consacrat acestor algoritmi!
Identificarea vecinilor
Înainte de a descrie efectiv modul în care se realizează umplerea, să analizăm conceptul de
vecin al unui element din matrice. Deși nu este nou, este bine să sistematizăm lucrurile,
pentru a obține algoritmi cât mai clari și mai ușor de depanat!
În probleme este precizat care sunt vecinii unui element al matricei. De regulă, sunt
elementele învecinate pe linie și pe coloană, dar pot fi și pe diagonală, sau în formă de L,
așa cum se deplasează calul de șah.
1|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
Pentru a evita repetarea unor instrucțiuni aproape identice – singura diferență fiind
coordonatele vecinului curent, putem construi două tablouri unidimensionale di[], dj[] –
numiți și vectori de deplasare:
2|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
Bordarea matricei
Un alt aspect care trebuie avut în vedere constă evitarea ieșirii din matrice – analiza unor
elemente care nu fac parte din matrice, ceea ce are de regulă consecințe impredictibile. În
cazul vecinilor pe linie și coloană, majoritatea elementelor au patru vecini, dar există și
elemente cu trei vecini – chenarul matricei, precum și elemente cu doi vecini – colțurile:
3|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
Pentru a evita cazurile particulare putem borda matricea cu obstacole sau putem pentru fiecare
element vecin, determinat cu ajutorul vectorilor de deplasare, să verificăm dacă aparține
matricei, înainte de a-l analiza/prelucra:
2.FILL RECURSIV:
Operația de umplere poate fi sistematizată astfel:
Ultima etapă – continuarea în mod similar cu vecinii elementului curent, ne duce cu gândul
la recursivitate. Următorul program realizează umplerea pornind dintr-o poziție dată:
#include <iostream>
4|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
{
// i,j - elementul curent, v - valoarea cu care facem Fill
if(i >= 1 && i <= n && j >= 1 && j <= m && A[i][j] == 0)
{ // in matrice, element liber si nemarcat
A[i][j] = v;
for(int k = 0 ; k < 4 ; k ++)
Fill(i + di[k] , j + dj[k], v);
}
}
int main()
{
cin >> n >> m;
for(int i = 1 ; i <= n ;i ++)
for(int j = 1 ; j <= m ; j ++)
cin >> A[i][j];
cin >> istart >> jstart;
return 0;
}
3.FILL CU COADA:
Algoritmul de umplere (FILL) pe matrice funcționează pe ideea: marcăm elementul curent și
analizăm vecinii liberi și nemarcați ai acestuia. Pentru a gestiona ordinea în care se face
acest lucru putem folosi recursivitatea sau putem folosi o structură de date de tip coadă
– queue. Această metodă are o serie de avantaje, fiind de regulă mai rapidă.
5|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
Reamintim, coada este o structură de date de tip FIFO – first in, first out. Elementele se
elimină strict în ordinea în care au fost adăugate.
Vom folosi o coadă în care elementele sunt perechi de indici ai tabloului. Algoritmul de
umplere este următorul:
Algoritmul este eficient, fiecare element accesibil în matrice pornind de la poziția inițială (de
fapt coordonatele lui) este adăugat și eliminat din coadă exact o dată. Astfel numărul de
elemente cozii este cel mult n*m (unde n și m sunt dimensiunile matricei).
Modalități de implementare
Pentru implementarea cozii se pot folosi mai multe metode:
dimensiunea acestui tablou trebuie să fie suficient de mare pentru a memora toate
elementele parcurse – în caz extrem toate elementele matricei. Dimensiunea trebuie
deci să fie n*m.
elementele tabloului sunt perechi de indici (linie-coloană). Pentru aceasta vom
declara o structură cu două câmpuri: linie, coloana.
gestionarea cozii se face folosind doi indici, st și dr:
o dr reprezintă finalul cozii – poziția ultimului element adăugat;
o st reprezintă începutul cozii – poziția elementul care urmează a fi eliminat.
La eliminare, elementul nu se șterge propriu-zis din vector (operația este prea
6|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
struct Coordonate
{
int linie, coloana;
};
7|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
// il adaugam in coada
dr ++;
Q[dr].linie = iv , Q[dr].coloana = jv;
}
}
st ++; // eliminam din coada
}
}
Următoarea funcție C++ realizează umplerea pornind dintr-o poziție dată – programul
complet este atașat articolului:
8|Page
INFO CLASA A X-A : RECURSIVITATE -> ALGORITMI DE UMPLERE
9|Page