Documente Academic
Documente Profesional
Documente Cultură
de programare
DISCIPLINA : INFORMATICA
Prin unicitate se nelege c toate transformrile prin care trece informaia iniial
pentru a obine rezultatul rR sunt bine determinate de regulile algoritmului. Aceasta
nseamn c fiecare pas din execuia algoritmului d rezultate bine determinate i precizeaz n
mod unic pasul urmtor. Altfel spus, ori de cte ori am executa algoritmul, pornind de la
aceeai informaie admisibil xD, transformrile prin care se trece i rezultatele obinute sunt
aceleai.
n descrierea algoritmilor se folosesc mai multe limbaje de descriere, dintre care cele
mai des folosite sunt:
- limbajul schemelor logice;
- limbajul Pseudocod.
n continuare vom folosi pentru descrierea algoritmilor limbajul Pseudocod care va fi
definit n cele ce urmeaz. n ultima vreme schemele logice sunt tot mai puin folosite n
descrierea algoritmilor i nu sunt deloc potrivite n cazul problemelor complexe. Prezentm
ns i schemele logice, care se mai folosesc n manualele de liceu, ntruct cu ajutorul lor vom
preciza n continuare semantica propoziiilor Pseudocod.
METODA BACKTRACKING
La dispoziia celor care rezolv probleme cu ajutorul calculatorului exist mai multe
metode. Dintre acestea cel mai des utilizate sunt:
metoda Greedy;
metoda Divide et impera;
metoda Branch and Bound;
metoda Backtracking;
Metoda backtracking se aplic problemelor n care soluia poate fi reprezentat sub forma
unui vector x = (x1, x2, x3, xk, xn) S, unde S este mulimea soluiilor problemei i S = S1
x S2 x x Sn, i Si sunt mulimi finite avnd s elemente si xi si , ()i = 1..n.
Pentru fiecare problem se dau relaii ntre componentele vectorului x, care sunt numite
condiii interne; soluiile posibile care satisfac condiiile interne se numesc soluii rezultat. Metoda
de generare a tuturor soluiilor posibile si apoi de determinare a soluiilor rezultat prin verificarea
ndeplinirii condiiilor interne necesit foarte mult timp.
Metoda backtracking evit aceast generare i este mai eficient. Elementele vectorului
x, primesc pe rnd valori n ordinea cresctoare a indicilor, x[k] va primi o valoare numai daca au
fost atribuite valori elementelor x1.. x[k-1]. La atribuirea valorii lui x[k] se verifica ndeplinirea
unor condiii de continuare referitoare la x1x[k-1]. Daca aceste condiii nu sunt ndeplinite, la
pasul k, acest lucru nseamn ca orice valori i-am atribui lui x[k+1], x[k+1], .. x[n] nu se va ajunge
la o soluie rezultat.
Metoda backtracking construiete un vector soluie n mod progresiv ncepnd cu prima
component a vectorului i mergnd spre ultima cu eventuale reveniri asupra atribuirilor
anterioare.
Metoda se aplica astfel :
1) se alege prima valoare sin S1 si I se atribuie lui x1 ;
2) se presupun generate elementele x1x[k-1], cu valori din S1..S[k-1]; pentru generarea lui
x[k] se alege primul element din S[k] disponibil si pentru valoarea aleasa se testeaz
ndeplinirea condiiilor de continuare.
Pot aprea urmtoarele situaii :
1
1
2
1
1
2
1
2
2
1
3
2
1
3
1
1
3
1
2
3
1
3
3
1
1
2
1
1
2
2
1
2
3
1
2
3
2
1
3
2
2
2
n mod practic la scoaterea unei variabile din stiv, scade cu 1 valoarea variabilei ce indic
vrful stivei, iar atunci cnd scriem ceva n stiv, o eventual valoare rezidual se pierde:
Pe un anumit nivel se retine, de regul, o singur informaie (liter sau cifr), ns este
posibil; aa cum va rezulta din exemplele, prezentate n lucrare, s avem mai multe informaii, caz
n care avem de a face cu stive duble, triple, etc.
ntreaga teorie a recursivitii se bazeaz pe structura de tip stiv.
Prezentarea tehnicii Backtracking
Aceast tehnic se folosete n rezolvarea problemelor care ndeplinesc simultan
urmtoarele condiii:
soluia lor poate fi pus sub forma unui vector S=x1,x2, ...,xn, cu x1 A1, x2 A2 ,
xn An
mulimile A1, A2 , ., An sunt mulimi finite, iar elementele lor se consider c se
afl ntr-o relaie de ordine bine stabilit;
nu se dispune de o alt metod de rezolvare, mai rapid
x1 x2 , xn pot fi la rndul lor vectori;
A1, A2 , An pot coincide.
La ntlnirea unei astfel de probleme, dac nu cunoatem aceast tehnic, suntem tentai s
generm toate elementele produsului cartezian A1,A2 ,An si fiecare element s fie testat dac
este soluie. Rezolvnd problema n acest mod, timpul de execuie este att de mare, nct poate fi
considerat infinit, algoritmul neavnd nici o valoare practic.
De exemplu, dac dorim s generm toate permutrile unei mulimi finite A, nu are rost s
generm produsul cartezian AxAx.....xA, pentru ca apoi, s testm, pentru fiecare element al
acestuia, dac este sau nu permutare (nu are rost s generm 1.1,1.......1, pentru ca apoi s
constatm c nu am obinut o permutare, cnd de la a doua cifr 1 ne puteam da seama c cifrele
nu sunt distincte).
Tehnica Backtracking are la baz un principiu extrem de simplu:
se construiete soluia pas cu pas: x1, x2 ,xn
dac se constat c, pentru o valoare aleas, nu avem cum s ajungem la soluie, se
renun la acea valoare i se reia cutarea din punctul n care am rmas.
Concret:
se alege primul element x, ce aparine lui A;
presupunnd generate elementele x1,x2 ,xk , aparinnd mulimilor A1, A2 ,Ak,
se alege (dac exist) xk+1, primul element disponibil din mulimea Ak+1, apar dou
posibiliti:
1) Nu s-a gsit un astfel de element, caz n care caz n care se reia cutarea
considernd generate elementele x1,x2 ,xk+1 , iar aceasta se reia de la urmtorul
element al mulimii Ak rmas netestat;
2) A fost gsit, caz n care se testeaz dac acesta ndeplinete anumite condiii de
continuare aprnd astfel dou posibiliti:
ndeplinete, caz n care se testeaz dac s-a ajuns la soluie si apar din nou dou
posibiliti:
- s-a ajuns la soluie, se tiprete soluia si se reia algoritmul considernd
generate elementele x1,x2 ,xk, (se caut n continuare, un alt element al
mulimii Ak, rmas netestat);
- nu s-a ajuns la soluie, caz n care se reia algoritmul considernd generate
elementele x1,x2 ,xk , si se caut un prim element xk+2 Ak.
nu le ndeplinete caz n care se reia algoritmul considernd generate elementele
x1,x2 , xk , iar elementul xk-1 se caut ntre elementele mulimii A, rmase
netestate.
Algoritmii se termin atunci cnd nu exist nici un element x1 A1 netestat.
Observaie: tehnica Backtracking are ca rezultat obinerea tuturor soluiilor problemei. n cazul
n care se cere o sigur soluie se poate fora oprirea, atunci cnd a fost gsit.
Am artat c orice soluie se genereaz sub form de vector. Vom considera c generarea
soluiilor se face intr-o stiv. Astfel, x1 A1, se va gsi pe primul nivel al stivei, x2 A2 se va gsi
pe al doilea nivel al stivei,... xk Ak se va gsi pe nivelul k al stivei. n acest fel, stiva (notat ST)
va arta astfel:
Nivelul k+1 al stivei trebuie iniializat (pentru a alege, n ordine, elementele mulimii
k+1 ). Iniializarea trebuie fcut cu o valoare aflat (n relaia de ordine considerat, pentru
mulimea Ak+1 ) naintea tuturor valorilor posibile din mulime. De exemplu, pentru
xk generarea permutrilor mulimii {1,2.....n}, orice nivel al stivei va lua valori de la 1 la n.
Iniializarea unui nivel (oarecare) se face cu valoarea 0. Procedura de iniializare o vom
numi INIT i va avea doi parametri: k (nivelul care trebuie iniializat si ST (stiva)).
...
Observaie: Problemele rezolvate prin aceast metod necesit un timp ndelungat. Din acest
motiv, este bine s utilizm metoda numai atunci cnd nu avem la dispoziie un alt algoritm mai
eficient. Cu toate c exist probleme pentru care nu se pot elabora ali algoritmi mai eficieni,
tehnica backtracking trebuie aplicat numai n ultim instan.
Fiind dat o tabl de ah, de dimensiune n, xn, se cer toate soluiile de aranjare a n dame,
astfel nct s nu se afle dou dame pe aceeai linie, coloan sau diagonal (dame s nu se atace
reciproc).
Exemplu: Presupunnd c dispunem de o tabl de dimensiune 4x4, o soluie ar fi urmtoarea:
D
D
D
D
Observm c o dam trebuie s fie plasat singur pe linie. Plasm prima dam pe linia 1, coloana
1.
D
Observm c a treia dam nu poate fi plasat n linia 3. ncercm atunci plasarea celei de-a doua
dame n coloana 4.
D
D
Acum este posibil s plasm a patra dam n coloana 3 si astfel am obinut o soluie a
problemei.
D
D
D
D
Algoritmul continu n acest mod pn cnd trebuie scoas de pe tabl prima dam.
Pentru reprezentarea unei soluii putem folosi un vector cu n componente (avnd n vedere
c pe fiecare linie se gsete o singur dam).
Exemplu pentru soluia gsit avem vectorul ST ce poate fi asimilat unei stive.
Dou dame se gsesc pe aceeai diagonal dac si numai dac este ndeplinit condiia:
|st(i)-st(j)|=|i-j| ( diferena, n modul, ntre linii si coloane este aceeai).
n general ST(i)=k semnific faptul c pe linia i dama ocup poziia k.
3
ST(4)
ST(3)
ST(2)
ST(1)
st(1)= 1 i = 1
st(3)= 3 j = 3
|st(1) - st(3)| = |1 3| = 2
|i j| = |1 3| = 2
D
D
D
sau situaia
D
D
D
D
st(1) = 3 i = 1
st(3) = 1 j = 3
|st(i) - st(j)| = |3 1| = 2
|i j| = |1 3| = 2
ntruct doua dame nu se pot gsi n aceeai coloan, rezult c o soluie este sub form de
permutare. O prim idee ne conduce la generarea tuturor permutrilor si la extragerea soluiilor
pentru problema ca dou dame s nu fie plasate n aceeai diagonal. A proceda astfel, nseamn
c lucrm conform strategiei backtracking. Aceasta presupune ca imediat ce am gsit dou dame
care se atac, s relum cutarea.
Iat algoritmul, conform strategiei generate de backtracking:
n prima poziie a stivei se ncarc valoarea 1, cu semnificaia c n linia unu se
aeaz prima dam n coloan.
Linia 2 se ncearc aezarea damei n coloana 1, acest lucru nefiind posibil ntruct
avem doua dame pe aceeai coloan.
n linia 2 se ncearc aezarea damei n coloana 2 , ns acest lucru nu este posibil,
pentru c damele se gsesc pe aceiai diagonal (|st(1)-st(2)|=|1-2|);
Aezarea damei 2 n coloana 3 este posibil.
Nu se poate plasa dama 3 n coloana 1, ntruct n liniile 1-3 damele ocupa acelai
coloan.
i aceast ncercare eueaz ntruct damele de pe 2 i 3 sunt pe aceeai diagonal.
Damele de pe 2-3 se gsesc pe aceeai coloan.
Damele de pe 2-3 se gsesc pe aceeai diagonal.
Am cobort n stiv mutnd dama de pe linia 2 i coloana 3 n coloana 4.
Algoritmul se ncheie atunci cnd stiva este vid. Semnificaia procedurilor utilizate este
urmtoarea:
INIT - nivelul k al stivei este iniializat cu 0;
SUCCESOR - mrete cu 1 valoarea aflat pe nivelul k al stivei n situaia n care
aceasta este mai mic dect n i atribuie variabilei EV valoarea TRUE, n caz
contrar, atribuie variabilei EV valoarea FALSE;
VALID - valideaz valoarea pus pe nivelul k al stivei, verificnd dac nu avem
dou dame pe aceeai linie (st(k)=st(i)), sau dac nu avem dou dame pe aceeai
diagonal (st(k)-st(i)=|k-i|)caz n care variabilei EV i se atribuie FALSE; n caz
contrar, variabilei EV i se atribuie TRUE;
SOLUTIE - verific dac stiva a fost completat pn la nivelul n inclusiv;
TIPAR - tiprete o soluie.
Subprogramele prezentate in limbajul Visual Basic sunt descrise mai jos:
Global n As Integer, am_suc As Boolean, ev As Boolean
Type stiva
ss(100) As Integer
End Type
Global st As stiva
Else
k = k - 1
End If
Wend
End Sub
Sub Button2_Click()
n = InputBox("n=", ib_title)
back
End Sub
Aceste subprobleme sunt independente, deoarece tijele initial (pe care sunt dispuse
discurile), tijele finale si tijele intermediare sunt diferite. Notam H(n,A,B,C)=sirul mutarilor a n
discuri de pe A pe B, folosind C.
PENTRU
n=1 AB
n>1 H(n,A,B,C)= H(n-1,A,C,B),AB, H(n-1,C,B,A)
Sortare rapida (quicksort)
Un tablou V se completeaza cu n elemente numere reale .Sa se ordoneze crescator folosind
metoda de sortare rapida .
Solutia problemei se bazeaza pe urmatoarele etape implementate in programul principal:
se apeleaza procedura quick cu limita inferioara li=1 si limita superioara ls=n;
functiapoz realizeaza mutarea elementului v[i] exact pe pozitia ce o va ocupa
acesta in vectorul final ordonat ; functiapoz intoarce (in k ) pozitia ocupata de
acest element;
in acest fel , vectorul V se imparte in doua parti: li k-1 si k+1ls;
pentru fiecare din aceste parti se reapeleaza procedura quick, cu limitele
modificate corespunzator;
in acest fel, primul element din fiecare parte va fi pozitionat exact pe pozitia
finala ce o va ocupa in vectorul final ordonat (functiapoz);
fiecare din cele doua parti va fi, astfel, inpartita in alte doua parti; procesul
continua pana cand limitele partilor ajung sa se suprapuna ,ceea ce indica ca toate
elementele vectorului au fost mutate exact pe pozitiile ce le vor ocupa in vectorul
final ;deci vectorul este ordonat ;
in acest moment se produc intoarcerile din apelurile recursive si programul isi
termina executia.
Observaii:
daca elementul se afla in stanga, atunci se compara cu elementele din dreapta lui
si se sar (j:=j-1) elementele mai mari decat el;
daca elementul se afla in dreapta, atunci se compara cu elemente din stanga lui
si se sar (i:=i+1) elementele mai mici decat el.
Sortare prin interclasare(mergesort)
Tabloul unidimensional V se completeaza cu n numere reale. Sa se ordoneze crescator
folosind sortare prin interclasare.
Sortarea prin interclasare se bazeaza pe urmatoarea logica:
vectorul V se imparte, prin injumatatiri succesive,in vectori din ce in ce mai mici;
cand se ating vectorii de maxim doua elemente, fiecare dintre acestia se
ordoneaza printr-o simpla comparare a elementelor;
cate doi astfel de mini-vectori ordonati se interclaseaza succesiv pana se ajunge
iar la vectorul V.
Observaii:
mecanismul general de tip Divide et Impera se gaseste implementat in procedura
divi;
astfel de abordare a problemei sortarii unii vector conduce la economie de timp
de calcul, deoarece operatia de interclasare a doi vectori deja ordonati este foarte
rapida, iar ordonarea independenta celor doua jumatati (mini-vectori) consuma in
total aproximativ a doua parte din timpul care ar fi necesar ordonarii vectorului luat
ca intreg .
Metoda Greedy
Algoritmii greedy (greedy = lacom) sunt in general simpli si sunt folositi la probleme de
optimizare, cum ar fi: sa se gaseasca cea mai buna ordine de executare a unor lucrari pe calculator,
sa se gaseasca cel mai scurt drum intr-un graf etc. In cele mai multe situatii de acest fel avem:
multime de candidati (lucrari de executat, varfuri ale grafului etc)
o functie care verifica daca o anumita multime de candidati constituie o solutie
posibila
o functie care verifica daca o multime de candidati este fezabila, adica daca este
posibil sa completam aceasta multime astfel incat sa obtinem o solutie posibila, nu
neaparat optima, a problemei
o functie de selectie care indica la orice moment care este cel mai promitator
dintre candidatii inca nefolositi
o functie obiectiv care da valoarea unei solutii (timpul necesar executarii tuturor
lucrarilor intr-o anumita ordine, lungimea drumului pe care l-am gasit etc); aceasta
este functia pe care urmarim sa o optimizam (minimizam/maximizam)
Pentru a rezolva problema noastra de optimizare, cautam o solutie posibila care sa
optimizeze valoarea functiei obiectiv. Un algoritm greedy construieste solutia pas cu pas. Initial,
multimea candidatilor selectati este vida. La fiecare pas, incercam sa adaugam acestei multimi cel
mai promitator candidat, conform functiei de selectie. Daca, dupa o astfel de adaugare, multimea
de candidati selectati nu mai este fezabila, eliminam ultimul candidat adaugat; acesta nu va mai fi
niciodata considerat. Daca, dupa adaugare, multimea de candidati selectati este fezabila, ultimul
candidat adaugat va ramane de acum incolo in ea. De fiecare data cand largim multimea
candidatilor selectati, verificam daca aceasta multime nu constituie o solutie posibila a problemei
noastre. Daca algoritmul greedy functioneaza corect, prima solutie gasita va fi totodata o solutie
optima a problemei. Solutia optima nu este in mod necesar unica: se poate ca functia obiectiv sa
aiba aceeasi valoare optima pentru mai multe solutii posibile. Descrierea formala a unui algoritm
greedy general este:
function greedy(C)
{C este multimea candidatilor}
S
{S este multimea in care construim solutia}
while not solutie(S) and C do
x un element din C care maximizeaza/minimizeaza select(x)
C C \ {x}
if fezabil(S {x}) then S S {x}
if solutie(S)
then return S
else return nu exist soluie
Este de inteles acum de ce un astfel de algoritm se numeste lacom (am putea sa-i spunem
si nechibzuit). La fiecare pas, procedura alege cel mai bun candidat la momentul respectiv, fara
sa-i pese de viitor si fara sa se razgandeasca. Daca un candidat este inclus in solutie, el ramane
acolo; daca un candidat este exclus din solutie, el nu va mai fi niciodata reconsiderat. Asemenea
unui intreprinzator rudimentar care urmareste castigul imediat in dauna celui de perspectiva, un
algoritm greedy actioneaza simplist. Totusi, ca si in afaceri, o astfel de metoda poate da rezultate
foarte bune tocmai datorita simplitatii ei.
Functia select este de obicei derivata din functia obiectiv; uneori aceste doua functii sunt
chiar identice.
Un exemplu simplu de algoritm greedy este algoritmul folosit pentru rezolvarea urmatoarei
probleme. Sa presupunem ca dorim sa dam restul unui client, folosind un numar cat mai mic de
monezi. In acest caz, elementele problemei sunt:
candidatii: multimea initiala de monezi de 1, 5, si 25 unitati, in care
presupunem ca din fiecare tip de moneda avem o cantitate nelimitata
Presupunem acum ca I este astfel incat putem gasi doi intregi a < b cu
Interschimbam pe ia cu ib in I; cu alte cuvinte, clientul care a fost servit al b-lea va fi servit
acum al a-lea si invers. Obtinem o noua ordine de servire J, care este de preferat deoarece
unde ai este adancimea varfului i. Se observa ca numarul total de deplasari de elemente pentru
strategia corespunzatoare lui A este chiar L(A). Solutia optima a problemei noastre este atunci
arborele (strategia) pentru care lungimea externa ponderata este minima.
Proprietate :Prin metoda greedy se obtine intotdeauna interclasarea optima a n siruri ordonate,
deci strategia cu arborele de lungime externa ponderata minima.
drumurilor directe de la un element i la un nod j. Vom construi matricea A (nxn) care va contine n
final toate drumurile minime ntre 2 noduri i si j. Initial, A(i,j) = C(i,j). pentru fiecare k, k=1,n, se
verifica daca A(i,j) > A(i,k) + A(k,j), pentru orice i si j. n caz afirmativ, se inlocuieste valoarea lui
A(i,j) cu valoarea A(i,k) + A(k,j). n final, vom avea n matricea A lungimea drumurilor minime.