Sunteți pe pagina 1din 19

Colegiul National Carol I, Craiova

Atestat informatica
Algoritmul lui Lee

Profesor coordonator, Lic Ovidiu


Absolvent, Cimpoiau Mihai-Octavian, clasa XII-C

Cuprins
1. Consideraii teoretice
1.1 Motivarea alegerii temei 1.2 Conceptul algoritmului 1.3 Prezentarea algoritmului
1.3.1 Prezentarea algoritmului in pseudocod 1.3.2 Prezentarea algoritmului general in limbaj C++

2. Aplicaii practice
2.1 Problema Insule 2.2 Problema Alee

3. Bibliografie

1. Consideraii teoretice
1.1 Motivarea alegerii temei
Consider ca atat matricele cat si arborii sunt notiuni esentiale in informatica studiata in liceu. Astfel parcurgerea acestora determinand drumurile minime dintre doua puncte sau de iesire dintr-un tablou reprezinta probleme de natura importanta usor solutionate cu ajutorul algoritmului ales pentru studiu si anume algoritmul lui Lee. Matricele dupa cum bine stim sunt in informatica tablouri bidimensionale de variabile. Algoritmul lui Lee isi propune rezolvarea problemelor de orientare intr-un labirint aceasta fiind matricea. In esenta algoritmul poate fi aplicat pentru rezolvarea mai multor tipuri de probleme: - descoperirea drumului minim dintr-o matrice de la un punct dat a(u,v) la alt punct b(g,c), unde u, v, g si c sunt coordonatele punctelor din matrice introduse de la tastatura. - descoperirea posibilitatii de iesire dintr-o matrice labirint. Fiind pozitionat pe un punct din matrice de coordinate (i,j) algoritmul va determina daca este posibil sau nu parasirea matricei, deplasarea facandu-se pe punctele din matrice de valori diferite de 0. - descoperirea drumului de cost minim dintr-un arbore

1.2 Conceptul algoritmului


Etapele pe care le urmeaza algoritmul sunt urmatoarele:

Etapa 1 - Initializarea Se selecteaza punctual de start marcat cu 0 i=0

Etapa 2 - Expansiunea Se repeta marcarea tuturor vecinilor neetichetati ai punctelor marcate cu i cu i+1 pana cand este atinsa tinta sau niciun punct nu poate fii marcat.

Etapa 3 - Refacerea drumului Ne pozitionam pe punctual tinta. Se repeta: - pozitionarea pe urmatorul nod ce are un marcaj mai mic decat nodul pe care suntem pozitionati - adaugarea acestuia la drum pana cand nodul de origine este atins.

Etapa 4 - Curatarea Blocam drumul pentru viitoare conexiuni. Se sterg toate marcajele

1.3 Prezentarea algoritmului


1.3.1 Prezentarea algoritmului in pseudocod utilizand structura de tip coada la determinarea drumului minim intr-un arbore
Parcurgerea in latime este cunoscuta si ca algoritmul lui Lee in lumea algoritmicii romanesti, avand la baza un algoritm clasic utilizat in teoria grafurilor, pentru a afla drumul de lungime minima intre doua noduri. Algoritmul are la baza o metoda iterativa. Fiecare nod adiacent cu nodul curent va fi bagat in coada, iar la extragerea unui nod vom insera in coada toate nodurile adiacente nevizitate ale nodului curent (avand grija sa eliminam nodul curent). Algoritmul se repeta pana cand coada devine vida sau gasim solutia asteptata. intreg m[100][100]; coada c; functie bfs(nod p) { adaug_in_coada(p); m[k.x][k.y]=1; //vizitez nodul pentru(i=0;i< =n+1;i++) m[i][0]=m[i][m+1]=1; //bordam coloanele marginale pentru(i=0;i<=m+1;i++) m[0][i]=m[n+1][i]=1; //bordam liniile marginale cat_timp(c <> NULL) { k = scot_din_coada(c); pentru_fiecare_nod(vecin din k){ daca(m[vecin.x][vecin.y]==0){
5

//daca vecinul e nevizitat m[vecin.x][vecin.y]=1; //il vizitez adaug_in_coada(vecin); } } sterg_din_coada(k); } }

1.3.2 Prezentarea algoritmului in limbaj C++ pentru determinarea unui drum minim intr-o matrice
enun: Se consider o matrice ptratic de ordinul N n care avem o singura valoare nul la o poziie cunoscut, mai multe valori -1 cu rol de valoare inaccesibil i o valoare foarte mare n restul locaiilor. Se cere s se gseasc cel mai mic drum de la valoarea 0 ctre o alt locaie de asemenea cunoscut, diferit de locaiile inaccesibile. rezolvare: Algoritmul lui Lee marcheaz n matrice pasul 1 peste tot n jurul valorii 0 daca rmnem n matrice i dac nu se ntlnesc puncte inaccesibile. Se marcheaz cu pasul 2 n jurul tuturor valorilor 1 in aceleai condiii ca n pasul anterior. Altfel spus, aflndu-ne la un pas oarecare k analizm toi cei 4 vecini ai unei locaii curente si marcm cu pasul k+1, daca valoarea existent ntrun anumit vecin este diferit de -1, rmne n matrice, memoreaz o valoare mai mare decat k+1, adic se optimizeaz traseul de la locaia cu 0 ctre resspectivul(vecin).

#include<fstream> #include<iostream> #include<iomanip> #define N 100 using namespace std; void Lee(int a[][N],int m, int n, int l, int c, int pas){ if (l>1 && a[l-1][c]>pas+1) { a[l-1][c]=pas+1; Lee(a, m, n, l-1, c, pas+1); } if (c<n && a[l][c+1]>pas+1) { a[l][c+1]=pas+1; Lee(a,m,n,l,c+1,pas+1); } if (l<m && a[l+1][c]>pas+1){ a[l+1][c]=pas+1; Lee(a, m, n, l+1, c, pas+1); } if (c>0 && a[l][c-1]>pas+1){ a[l][c-1]=pas+1; Lee(a, m, n, l, c-1, pas+1); } } void tipar (int a[][N], int m, int n) { int i,j; for (i=1; i<=m; i++){ for (j=1; j<=n; j++) cout<<setw(5)<<a[i][j]; cout<<endl; } }

int main () { int a[N][N],l,c,lf,cf,m,n,i,j; fstream f("Lee.txt",ios::in); f>>m>>n; for (i=1; i<=m; i++) for (j=1; j<=n; j++) { f>>a[i][j]; if (a[i][j]==0){ l=i; c=j; } } cout<<"Dati lf si cf ";cin>>lf>>cf; if(a[lf][cf]==-1) return 0; Lee(a,m,n,l,c,0); if (a[lf][cf]==100) cout<<"Locatie inaccesibila"; else tipar(a,m,n); } Observaie: Algoritmul recursivitatea. prezentat folosete ca metod principal

2. Aplicaii practice

2.1 Problema Insule - OJI 2009, clasa a 10-a


enun original: Arhipelagul RGB este format din insule care aparin rilor R, G i B. Putem reprezenta harta arhipelagului ca o matrice cu N linii i M coloane cu elemente din mulimea {0, 1, 2, 3} astfel: - un element egal cu 0 reprezint o zon acoperit de ap - un element egal cu 1 reprezint o zon de pmnt aparinnd unei insule din ara R - un element egal cu 2 reprezint o zon de pmnt aparinnd unei insule din ara G - un element egal cu 3 reprezint o zon de pmnt aparinnd unei insule din ara B Se consider c dou elemente ale matricei sunt vecine dac ele au aceeai valoare i fie sunt consecutive pe linie, fie sunt consecutive pe coloan. Dou elemente aparin aceleiai insule dac ele sunt vecine sau dac se poate ajunge de la un element la cellalt pe un drum de-a lungul cruia oricare dou elemente consecutive sunt vecine. Pentru a ncuraja relaiile de colaborare dintre rile R i G, se dorete construirea unui pod care s uneasc o insul aparinnd rii R de o insul aparinnd rii G. Podul trebuie s respecte urmtoarele condiii: - s nceap pe o zon cu ap consecutiv pe linie sau coloan cu o zon aparinnd rii R; - s se termine pe o zon cu ap consecutiv pe linie sau coloan cu o zon aparinnd rii G; - s traverseze numai zone acoperite cu ap; - oricare dou elemente consecutive ale podului trebuie s fie vecine; - lungimea podului s fie minim (lungimea podului este egal cu numrul de elemente traversate de pod).

cerin: Dat fiind harta arhipelagului s se determine cte insule aparin fiecrei ri, precum i lungimea minim a unui pod care s satisfac condiiile din enunt. date de intrare: Fiierul de intrare insule.in conine pe prima linie numerele naturale N i M, separate prin spaiu. Pe urmtoarele n linii este descris harta arhipelagului. Pe fiecare dintre aceste n linii sunt scrise cte m valori din mulimea {0, 1,2, 3}; valorile nu sunt separate prin spaii. date de ieire: Fiierul de ieire insule.out va conine o singur linie pe care vor fi scrise patru numere naturale separate prin spaii NR NG NB Lg, unde NR reprezint numrul de insule aparinnd rii R, NG numrul de insule aparinnd rii G,NB numrul de insule aparinnd rii B, iar Lg lungimea minim a podului. restricii i precizri: 1 N,M 100 Se garanteaz c pe hart exist cel puin un element 1, un element 2 i un element 0. Se acord 40% din punctaj pentru determinarea corect a numrului de insule din fiecare ar; se acord punctaj integral pentru rezolvarea corect a tuturor cerinelor. nceputul i sfritul podului pot s coincid. Pentru datele de test exist ntotdeauna soluie.

10

codul surs al rezolvrii: #include<fstream> using namespace std; ifstream f("insule.in"); ofstream g("insule.out"); char c; int k, ok, o, mini, nr, x, y, n1, n2, n3, i, j, n, m, v[102][102], v1[102][102]; void fill(int x, int y, int k) { if(v1[x][y]==k) { v1[x][y]=4; fill(x-1,y,k); fill(x,y-1,k); fill(x+1,y,k); fill(x,y+1,k); } }

int main() { f>>n>>m; for(i=1; i<=n; i++) { f.get(c); for(j=1; j<=m; j++) { f.get(c); v1[i][j]=c-48; v[i][j]=v1[i][j]; if(v[i][j]==2) v[i][j]=-2; else if(v[i][j]==3) v[i][j]=-3; }
11

} n1=0; n2=0; n3=0; for(i=0; i<=n+1; i++) { v1[i][0]=4; v1[i][m+1]=4; v[i][0]=-4; v[i][m+1]=-44; } for(i=1; i<=m; i++) { v[0][i]=-4; v[n+1][i]=-4; v1[0][i]=4; v1[n+1][i]=4; } for(i=1; i<=n; i++) for(j=1; j<=m; j++) if(v1[i][j]==1) { n1++; fill(i,j,1); } else if(v1[i][j]==3) { n3++; fill(i,j,3); } else if(v1[i][j]==2) { n2++; fill(i,j,2); } g<<n1<<" "<<n2<<" "<<n3<<" "; mini=9999; k=1; ok=1; while(ok==1) {
12

ok=0; for(i=1; i<=n; i++) for(j=1; j<=m; j++) if(v[i][j]==k) { if(v[i][j+1]==0) { v[i][j+1]=k+1; ok=1; } if(v[i][j-1]==0) { v[i][j-1]=k+1; ok=1; } if(v[i+1][j]==0) { v[i+1][j]=k+1; ok=1; } if(v[i-1][j]==0) { v[i-1][j]=k+1; ok=1; } } k++; } mini=9999; for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(v[i][j]==-2) { if(v[i][j+1]>1) if(v[i][j+1]<mini&&v[i][j+1]>1) mini=v[i][j+1]; if(v[i][j-1]>1) if(v[i][j-1]<mini&&v[i][j-1]>1) mini=v[i][j-1]; if(v[i+1][j]>1) if(v[i+1][j]<mini&&v[i+1][j]>1) mini=v[i+1][j]; if(v[i-1][j]>1) if(v[i-1][j]<mini&&v[i-1][j]>1) mini=v[i-1][j];
13

} g<<mini-1<<'\n'; f.close(); g.close(); return 0; }

14

2.1 Problema Alee - OJI 2007, clasa a 10-a


enun original: Parcul orasului a fost neglijat mult timp, astfel ca acum toate aleile sunt distruse. Prin urmare, anul acesta Primaria si-a propus sa faca reamenajari. Parcul are forma unui patrat cu latura de N metri si este inconjurat de un gard care are exact doua porti. Proiectantii de la Primarie au realizat o harta a parcului si au trasat pe harta un caroiaj care imparte parcul in N*N zone patrate cu latura de 1 metru. Astfel harta parcului are aspectul unei matrice patratice cu N linii si N coloane. Liniile si, respectiv, coloanele sunt numerotate de la 1 la N. Elementele matricei corespund zonelor patrate de latura 1 metru. O astfel de zona poate sa contina un copac sau este libera. Edilii orasului doresc sa paveze cu un numar minim de dale patrate cu latura de 1 metru zonele libere (fara copaci) ale parcului, astfel incat sa se obtina o alee continua de la o poarta la alta. cerin: Scrieti un program care sa determine numarul minim de dale necesare pentru construirea unei alei continue de la o poarta la cealalta. date de intrare: Fisierul de intrare alee.in contine pe prima linie doua valori naturale N si M separate printr-un spatiu, reprezentand dimensiunea parcului, respectiv numarul de copaci care se gasesc in parc. Fiecare dintre urmatoarele M linii contine cate doua numere naturale X si Y separate printr-un spatiu, reprezentand pozitiile copacilor in parc (X reprezinta linia, iar Y reprezinta coloana zonei in care se afla copacul). Ultima linie a fisierului contine patru numere naturale X1, Y1, X2, Y2, separate prin cate un spatiu, reprezentand pozitiile celor doua porti ( X1, Y1 reprezinta linia si respectiv coloana zonei ce contine prima poarta, iar X2, Y2 reprezinta linia si respectiv coloana zonei ce contine cea de a doua poarta). date de ieire: Fisierul de iesire alee.out va contine o singura linie pe care va fi scris un numar natural care reprezinta numarul minim de dale necesare pentru construirea aleii.

15

restricii i precizri: 1 N 175 1 M N*N Aleea este continua daca oricare doua placi consecutive au o latura comuna. Aleea incepe cu zona unde se gaseste prima poarta si se termina cu zona unde se gaseste cea de a doua poarta. Pozitiile portilor sunt distincte si corespund unor zone libere. Pentru datele de test exista intotdeauna solutie. codul surs al rezolvrii: #include<fstream.h> #define N 300 ifstream f("alee.in"); ofstream g("alee.out"); struct punct { int x; int y; } cd[N]; int a[177][177],p,nrelem; int dx[] = { -1, 0, 0, 1 }; int dy[] = { 0, -1, 1, 0 }; void init() { p=nrelem=0; } int vplin() { if(nrelem==N) return 1; return 0; }

16

int vgol() { if(nrelem==0) return 1; return 0; } int add(punct el) { if(vplin()==1) return 0; cd[(p+nrelem)%N]=el; nrelem++; return 1; } int extract(punct &el) { if(vgol()==1) return 0; el=cd[p]; p=(p+1)%N; nrelem--; return 1; } int main() { int i,n,m; punct c2,c1,a1,b1; f>>n>>m; for(i=0; i<=n+1; i++) a[0][i]=-1, a[n+1][i]=-1, a[i][0]=-1, a[i][n+1]=-1; for(; m; --m) { f>>a1.x>>a1.y; a[a1.x][a1.y]=-1; } f>>a1.x>>a1.y>>b1.x>>b1.y; a[a1.x][a1.y]=1;

17

init(); add(a1); while(vgol()==0) { extract(c1); for(i=0; i<4; i++) { c2.x=c1.x+dx[i]; c2.y=c1.y+dy[i]; if(a[c2.x][c2.y]==0) { a[c2.x][c2.y]=a[c1.x][c1.y]+1; add(c2); } } } g<<a[b1.x][b1.y]; f.close(); g.close(); return 0; }

18

III. Bibliografie
1. Boian F. M. De la arithmetic la calculatoare, Ed. Presa, Universitatea Clujean, Cluj-Napoca, 1996 2. Burdescu D. D. Tehnici de programare n Turbo C, Craiova 1995 3. Oltean M. Proiectarea i implementarea algoritmilor, Ed. Agora, Cluj-Napoca, 1999 4. Rancea D. Limbajul C++ - Algoritmi fundamentali, manual pentru clasa a XI-a, Ed. Agora, Cluj Napoca, 1999

19