Documente Academic
Documente Profesional
Documente Cultură
Prof.Bogdan Constantin
1
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3. Algoritmi
3.1 Noţiunea de algoritm şi caracteristici
ALGORITMI. DESCRIEREA ALGORITMILOR
Algoritmi
Orice activitate umană se desfăşoară, în general, pa baza unor principii logice sau, altfel spus,
a unui algoritm bine definit. Deşi nu se conştientizează acest lucru, omul acţionează conform unor
algoritmi, care reprezintă expresia regulilor impuse de parcurgerea logică a etapelor necesare pentru a
ajunge de la o situaţie iniţială la un anumit rezultat.
Funcţionarea calculatoarelor se aseamănă în mare măsură cu activitatea umană. În cazul
acestora, este obligatorie conştientizarea faptului că întreaga activitate a echipamentului de calcul se
bazează pe respectarea unor algoritmi, algoritmi ce sunt elaboraţi de factorul uman dotat cu raţiune şi
capacitate de analiză. Calculatorul nu dispune de calităţile omului, ca atare, în procesul de rezolvare a
unei probleme cu ajutorul echipamentului electronic de calcul este obligatorie parcurgerea unei etape
importante, şi anume elaborarea algoritmului de calcul. Succesul rezolvării problemei depinde de
2
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
calitatea algoritmului întocmit de către utilizator şi aplicat de echipamentul de calcul prin intermediul unui
program.
Calculatoarele numerice prelucrează informaţiile prin executarea unor operaţii simple. Deşi operaţiile
sunt elementare, prin înlănţuirea unei mulţimi de operaţii se poate ajunge la prelucrări deosebit de
complexe. Combinarea operaţiilor nu se face la întâmplare, ea supunându-se unor reguli bine
precizate. Studiul acestor reguli are la bază noţiunea de algoritm. Noţiunea de algoritm este strâns
legată de noţiunea de calcul.
Intuitiv un algoritm de calcul este o mulţime finită de operaţiuni cunoscute care executate într-o
ordine bine stabilită, pornind de la un set de valori, numite date de intrare, conduc într-un timp finit la un
set de valori, numite date de ieşire.
Algoritmul reprezintă o mulţime de asemenea calcule. Altfel spus, prin algoritm se înţelege
metoda de rezolvare a unei probleme într-un număr finit de paşi. Metoda de rezolvare este în esenţă un
şir de operaţii precise, care dacă sunt îndeplinite conduc la rezultatul dorit într-un număr finit de paşi.
Se poate spune că un algoritm constituie un sistem de reguli care, aplicat la o clasă de
probleme de acelaşi tip, conduce de la o situaţie iniţială la un rezultat final prin intermediul unor operaţii
succesiv ordonate, unic determinate.
O informaţie iniţială pentru care un algoritm de calcul este aplicabil, se numeşte informaţie admisibilă.
Totalitatea informaţiilor de acest gen constituie domeniul algoritmului.
Cunoscând faptul că orice algoritm conţine un anumit număr de etape numite şi paşii
algoritmului, se poate afirma că regulile algoritmului f aplicate asupra informaţiei iniţiale, care aparţine
domeniului D, determină întotdeauna obţinerea informaţiei finale corespunzătoare. Ca urmare, un
algoritm poate fi definit ca o funcţie:
f = D F unde: D= domeniul algoritmului (informaţiile iniţiale);
F= soluţia finală (informaţiile finale).
În general, un algoritm se caracterizează prin:
unicitatea. regulile algoritmului determinând unicitatea ordinii în care au loc toate
transformările intermediare, dar şi obţinerea informaţiei finale, după care activitatea
algoritmului se opreşte.
finalitate. Orice pas al algoritmului trebuie să se termine după un număr finit de paşi, şi
anume atunci când este obţinut rezultatul final, nu cel intermediar. Această proprietate se
mai numeşte şi realizabilitate potenţială.
claritate (să fie definit). Fiecare pas al algoritmului trebuie să fie precis definit. Operaţiile
ce trebuie efectuate în cadrul fiecărui pas trebuie să fie specificate în mod riguros, precis,
astfel încât să nu apară ambiguităţi în interpretare lui de către cel care îl execută.
Totodată, trebuie riguros precizate toate etapele de calcul ce trebuie urmate pentru a
obţine soluţia finală;
eficacitate. Orice algoritm trebuie să fie eficace. Aceasta înseamnă că toate operaţiile
algoritmului să poată fi efectuate de un individ cu creion şi hârtie într-un interval de timp
finit.
generalitate (universal) - adică să permită rezolvarea oricărei probleme dintr-o
anumită clasă de probleme pentru care a fost stabilit.
Ca exemple de algoritmi cunoscuţi din matematică amintim: algoritmul lui Newton pentru aflarea
rădăcinii pătrate aritmetice a unui număr, algoritmul lui Euclid pentru aflarea celui mai mare divizor
comun a două numere etc .
Descrierea algoritmilor.
Transcrierea algoritmului într-un limbaj de programare, în vederea rezolvării lui cu ajutorul
calculatorului numeric poartă numele de program. Programele transmise calculatorului, ca o
reprezentare fidelă a algoritmului de calcul sunt transcrise într-un limbaj “înţeles” de calculator, nu
conţine ambiguităţi şi specifică precis şi clar doar operaţiile pe care calculatorul le poate executa.
Scrierea unui algoritm poate fi făcută rareori direct într-un limbaj de programare. Ca atare
realizarea unui program comportă, uzual nişte etape intermediare.
În vederea întocmirii unui algoritm de calcul şi utilizării acestuia la calculator, este necesară
realizarea următoarelor activităţi:
definirea problemei;
formularea modelului matematic al problemei;
stabilirea algoritmului de rezolvare a problemei;
reprezentarea algoritmului;
3
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemple
4
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
6. Testarea programului.
Testarea se face pe mai multe seturi de date care să acopere cazurile posibile ce pot
apărea.
3.2 Structuri fundamentale( secvenţa, decizia, repetiţia)
5
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
6
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
CITESTE
i
EITES
SUBRUTINA X
TE
PRINT i
STOP
V=Vi
A
A
C
NU V=V+r
C
DA
A V>Vr
Exemplu:
Se cere algoritmul şi schema logică pentru calculul lui n!
Paşii algoritmului de calcul sunt :
1. citeşte valoarea lui n;
7
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
Citeşte
n
p: = 1
i: = 1
p: = p * i
i: = i + 1
Diagrama arborescentă
Diagrama arborescentă constituie o altă modalitate de reprezentare grafică a algoritmilor. Ca şi
în cazul schemelor logice, există mai multe convenţii de reprezentare a operaţiilor în cadrul algoritmilor.
IN PSEUDOCOD AVEM:
a) Secvenţa – este o structură realizată prin scrierea succesivă (în secvenţă) a comenzilor
componente.
Exemplu: citeşte A,B
atribuie C A + B
scrie A , B , C
stop
Efectul execuţiei unei comenzi depinde de poziţia comenzii în cadrul secvenţei .
b) Decizia – este o structură care asigură alegerea pentru execuţie a unei secvenţe din două
alternative posibile.
Structura comenzii: dacă condiţie atunci
secvenţa1
altfel
secvenţa 2
[]
Începutul comenzii de decizie este marcat de cuvântul cheie “dacă” iar sfârşitul său de semnul []
Execuţia acestei comenzi comportă următoarele etape:
se evaluează “ condiţia”;
dacă rezultatul evaluării este adevărat (condiţie îndeplinită) se execută secvenţa 1;
în caz contrar se execută secvenţa 2.
După executarea secvenţei 1 sau a secvenţei 2 se trece la următoarea comandă (cea după
semnul [] )
Observaţie: În cazul în care secvenţa care urmează după cuvântul cheie “altfel” lipseşte, se utilizează
forma simplificată a deciziei:
8
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemplul:
dacă A > B atunci
scrie A
altfel
scrie B
[]
Efectul execuţiei exemplului de mai sus este următorul:dacă valoarea variabilei A este mai
mare decât a variabilei B se scrie valoarea lui A în caz contrar se scrie valoarea variabilei B şi nu
valoarea variabilei A.
Exemplul: Decsrierea în Pseudocod a algoritmului de aflare a celui mai mare element
din 3 valori reale desemnate prin variabilele a,b,c.Variabila “x” va conţine cel mai mare element din cele
3 valori.Algoritmul de rezolvare a unei probleme nu este unic.Ca atare se dau două descrieri
Pseudocod pentru rezolvarea acestei probleme.
a) varianta 1
citeşte a,b,c
dacă a>b atunci
atribuie x a
altfel
atribuie x b
[]
dacă c > x atunci
atribuie x c
[]
scrie x
stop
b) varianta 2
citeşte a,b,c
atribuie x a
dacă x < b atunci
atribuie x b
[]
dacă x < c atunci
atribuie x c
[]
scrie x
stop
O variantă simplificată : citeşte a,b,c,
atribuie x a
dacă x < b atunci atribuie x b
9
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c2 : secvenţa 2
.
.
cn : secvenţa n
rest : secvenţa n+1
[]
Unde c1 , c2 , ... cn sunt etichete şi se folosesc pentru identificarea secvenţelor.Sfârşitul comenzii este
marcat de _[] iar liniile textului selecţiei sunt marcate prin etichetele c.
Modul de execuţie al comenzii de selecţie este următorul:
se evaluează expresia
se identifică eticheta ci ce are aceeaşi valoare cu expresia ( în urma evaluării expresiei)şi
este selectată secvenţa corespunzătoare.Dacă nici o etichetă nu are valoarea expresiei
atunci este selectată secvenţa n+1, corespunzătoare etichetei rest.
se execută secvenţa selecctată şi se sare la sfârşitul comenzii de selecţie adică după
semnul [].
Exemplu: Să se adune valoarea întreagă v la una din variabilele s 0,s1,s2 ,s3, după cum
restul împărţirii valorii v la 4 este 0,1,2 sau 3 .Descrierea în Pseudocod arată astfel:
citeşte v,s0,s1,s2,s3
alege v – int ( v/4)*4 dintre
0: atribuie s0 s0 + v
1: atribuie s1 s1 + v
2: atribuie s2 s2 + v
3: atribuie s3 s3 + v
[]
scrie s0,s1,s2,s3
stop
STRUCTURI REPETITIVE IN PSEUDOCOD
În acest caz , eticheta “rest” şisecvenţa respectivă lipseşte ,deoarece domeniul de valori ale expresiei
este mulţimea (0,1,2,3).
a) Ciclul cu test final – În rezolvarea unei probleme , nu de puţine ori apare situaţia executării
repetate a unei secvenţe de operaţii.O astfel de combinaţie , în care execuţia unui grup de
operaţii se repetă se numeşte ciclu sau iteraţie.Pentru reprezentarea ei se utilizează o comandă
de ciclare care specifică atâtoperaţiile care se repetă cât şi condiţia de repetare.
Forma generală a comenzii de ciclare cu test final este următoarea:
repetă
secvenţa
până condiţia
10
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
[]
Modul de execuţie al comenzii de ciclare este următorul:
1-se execută secvenţa
2-se evaluează condiţia şi dacă rezultatul este fals(condiţie neîndeplinită)se continuă cu etapa 1 , altfel
execuţia comenzii se termină şi se trece la comanda următoare.
Exemplu: Se dă algoritmul lui Euclid pentru afişarea celui mai mare divizor comun a
două numere întregi m,n(m>=n>0).
1. citeşte valorile lui m şi n
2. atribuie lui c valoarea lui n ( în variabila c se reţine cel mai mare divizor
comun )
3. atribuie lui r restul împărţirii întregi a lui m la n
4. dacă r diferit de 0 atunci treci la 7
5. scrie valoarea lui c
6. stop
7. atribuie lui m valoarea lui n
8. atribuie lui n valoarea lui r
9. treci la pasul 2
Se observă că operaţiile care se realizează calculul restului şiactualizarea valorilor c, m şi n se
repetă.
Folosind Descrierea în Pseudocod a algoritmului şi ciclul cu test final vom avea:
citeşte m,n
repetă
atribuie c n , r m-int(m/n)*n
atribuie mn , n r
până r=0
_[]
scrie c
stop
Condiţia de terminare a ciclului poate fi orice expresie logică.Secvenţa de operaţii din ciclu
alcătuieşte corpul ciclului .Ea poate conţine oriceoperaţii, inclusiv iteraţii.
b) Ciclul cu test iniţial – În cazul ciclurilor sau iteraţiilor condiţia de
ciclare poate apare şi la începutul secvenţei de ciclare
Forma generală este :
cât timp condiţia execută
secvenţa
[]
Condiţia poate fi orice expresie logică , iar secvenţa poate conţine orice comenzi , inclusiv
comenzi de ciclare.
Modul de execuţie al ciclului cu test iniţial :
1-se evaluează condiţia;dacă rezultatul este fals(condiţie neîndeplinită) execuţia se termină,iar dacă
rezultatul este adevărat se continuă secvenţa(etapa 2)
2-se execută secvenţa,după care se continuă cu 1.
În cazul în care rezultatul evaluării condiţiei este fals încă de la început,secvenţa nu se
execută niciodată spre deosebire de ciclul cu test final,când secvenţa se executa cel puţin o dată.
Scrierea algoritmului lui Euclid în Pseudocod folosind ciclul cu test iniţial ne conduce la:
citeşte m,n
atribuie c n , r m-int(m/n)*n
cât timp r <> 0 execută
atribuie m n , n r, c n
atribuie r m-int(m/n)*n
[]
11
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
scrie c
stop
c) Ciclul de contor, cu forma generală:
pentru contor = val iniţială, val.finală,pas execută
secvenţa
[]
unde prin contor se înţelege o variabilă cu valori întregi:”valoarea iniţială, finală şi pas” pot fi expresii
aritmetice cu valori întregi.
Execuţia ciclului cu contor se explicitează astfel:
1) variabilei contor i se atribuie valoarea iniţială;
2) se verifică condiţia contor > val. Finală; dacă rezultatul este fals se continuă cu, astfel
execuţia ciclului se termină;
3) se execută secvenţa
4) se modifică valoarea contorului cu pasul p şi se continuă cu pasul 2)
Exemplu: aflarea lui n!
Observaţii: 1. Dacă pasul de ciclare este 1, se poate omite
2. Algoritmul a fost completat şi pentru cazul în care n = 0
citeşte n
atribuie p = 1
dacă n>0 atunci
pentru i=1,n execută
atribuie p=p*i
[]
[]
scrie p
stop
12
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Scheme logice
Schemele logice reprezintă scrierea algoritmilor de calcul cu ajutorul unor simboluri (forme)
geometrice, care evidenţiază diferite tipuri de acţiuni.
Realizarea schemei logice corespunzătoare unui algoritm este utilă fie la depanarea
programelor, fie la lucrul în echipă, fie la schimbul de informaţii dintre diverse grupuri de
programatori,întrucât ea specifică precis şi clar ordinea de parcurgere a blocurilor (simbolurilor
geometrice).
Simbolurile uzuale utilizate în realizarea schemelor sunt cuprinse în tabelul de mai jos:
13
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
START
CITESTE
i
EITES
SUBRUTINA X
TE
PRINT i
STOP
STA STA
RT RT I
I
CITESTE CITESTE
I
i DA i DA I
A2
EITES EITES I
TE TE
A1 A3
PRINT i PRINT i
STOP STOP ii
CASE - OF I
IF - THEEN
- STRUCTURA REPETITIVĂ (CICLICĂ) se bazează pe repetarea unei secvenţe din
algoritm, care poate să cuprindă una sau mai multe operaţii. Există următoarele tipuri de
operaţii repetitive:
- WHILE – DO presupune executarea unei anumite secvenţe din algoritm atâta timp cât
este îndeplinită condiţia C. Deoarece structura este condiţionată anterior, există
posibilitatea ca secvenţa respectivă să nu se execute niciodată.
- DO – UNTIL , condiţionare posterioară, secvenţa din program se execută cel puţin o dată,
întrucât decizia de reluare a secvenţei se ia după executarea acesteia.
- DO – FOR se execută atunci când se cunoaşte de câte ori trebuie repetată o anumită
secvenţă. Ea se caracterizează prin apariţia unei variabile numită contor, care evidenţiază
numărul de repetări a secvenţei.
14
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
V=Vi
A
A
C
NU V=V+r
C
DA
A V>Vr
WHILE - DO
DO - UNTIL DO - FOR
Exemplu:
Se cere algoritmul şi schema logică pentru calculul lui n!
Paşii algoritmului de calcul sunt :
9. citeşte valoarea lui n;
10. atribuie lui P valoarea 1;
11. atribuie lui I valoarea 1;
12. atribuie lui P valoarea expresiei P * I;
13. atribuie lui I valoarea expresiei I + 1;
14. dacă I<N atunci treci la pasul 4;
15. scrie valoare lui P;
16. stop.
Schema logică corespunzătoare algoritmului:
START
Citeşte
n
p: = 1
i: = 1
p: = p * i
i: = i + 1
Diagrama arborescentă
Diagrama arborescentă constituie o altă modalitate de reprezentare grafică a algoritmilor. Ca şi
în cazul schemelor logice, există mai multe convenţii de reprezentare a operaţiilor în cadrul algoritmilor.
Limbajul Pseudocod
15
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
16
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
h) Secvenţa – este o structură realizată prin scrierea succesivă (în secvenţă) a comenzilor
componente.
Exemplu: citeşte A,B
atribuie C A + B
scrie A , B , C
stop
Efectul execuţiei unei comenzi depinde de poziţia comenzii în cadrul secvenţei .
i) Decizia – este o structură care asigură alegerea pentru execuţie a unei secvenţe din două
alternative posibile.
Structura comenzii: dacă condiţie atunci
secvenţa1
altfel
secvenţa 2
[]
Începutul comenzii de decizie este marcat de cuvântul cheie “dacă” iar sfârşitul său de semnul []
Execuţia acestei comenzi comportă următoarele etape:
se evaluează “ condiţia”;
dacă rezultatul evaluării este adevărat (condiţie îndeplinită) se execută secvenţa 1;
în caz contrar se execută secvenţa 2.
După executarea secvenţei 1 sau a secvenţei 2 se trece la următoarea comandă (cea după
semnul [] )
Observaţie: În cazul în care secvenţa care urmează după cuvântul cheie “altfel” lipseşte, se utilizează
forma simplificată a deciziei:
dacă condiţie atunci
secvenţa1
[]
În cazul în care condiţia nu este îndeplinită se trece direct la comanda ce urmează deciziei
Exemplul:
dacă A > B atunci
scrie A
altfel
scrie B
[]
Efectul execuţiei exemplului de mai sus este următorul:dacă valoarea variabilei A este mai
mare decât a variabilei B se scrie valoarea lui A în caz contrar se scrie valoarea variabilei B şi nu
valoarea variabilei A.
Exemplul: Descrierea în Pseudocod a algoritmului de aflare a celui mai mare element
din 3 valori reale desemnate prin variabilele a,b,c.Variabila “x” va conţine cel mai mare element din cele
3 valori.Algoritmul de rezolvare a unei probleme nu este unic.Ca atare se dau două descrieri
Pseudocod pentru rezolvarea acestei probleme.
a) varianta 1
citeşte a,b,c
dacă a>b atunci
atribuie x a
altfel
atribuie x b
[]
dacă c > x atunci
17
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
atribuie x c
[]
scrie x
stop
b) varianta 2
citeşte a,b,c
atribuie x a
dacă x < b atunci
atribuie x b
[]
dacă x < c atunci
atribuie x c
[]
scrie x
stop
O variantă simplificată : citeşte a,b,c,
atribuie x a
dacă x < b atunci atribuie x b
dacă x < c atunci atribuie x c
scrie x
stop
Observaţie: Ultima variantă a algoritmului are avantajul că poate fi uşor generalizată pentru aflarea
maximului unui şir.
j) Selecţia reprezintă o extindere a operaţiei de decizie, ea permitând alegerea unei alternative din
mai multe posibile.Forma generală a comenzii de selecţie este următoarea :
alege expresia dintre
c1 : secvenţa 1
c2 : secvenţa 2
.
.
cn : secvenţa n
rest : secvenţa n+1
[]
Unde c1 , c2 , ... cn sunt etichete şi se folosesc pentru identificarea secvenţelor.Sfârşitul comenzii este
marcat de _[] iar liniile textului selecţiei sunt marcate prin etichetele c.
Modul de execuţie al comenzii de selecţie este următorul:
se evaluează expresia
se identifică eticheta ci ce are aceeaşi valoare cu expresia ( în urma evaluării expresiei)şi
este selectată secvenţa corespunzătoare.Dacă nici o etichetă nu are valoarea expresiei
atunci este selectată secvenţa n+1, corespunzătoare etichetei rest.
se execută secvenţa selecctată şi se sare la sfârşitul comenzii de selecţie adică după
semnul [].
Exemplu: Să se adune valoarea întreagă v la una din variabilele s 0,s1,s2 ,s3, după cum
restul împărţirii valorii v la 4 este 0,1,2 sau 3 .Descrierea în Pseudocod arată astfel:
citeşte v,s0,s1,s2,s3
alege v – int ( v/4)*4 dintre
0: atribuie s0 s0 + v
18
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1: atribuie s1 s1 + v
2: atribuie s2 s2 + v
3: atribuie s3 s3 + v
[]
scrie s0,s1,s2,s3
stop
În acest caz , eticheta “rest” şisecvenţa respectivă lipseşte ,deoarece domeniul de valori ale
expresiei este mulţimea (0,1,2,3).
k) Ciclul cu test final – În rezolvarea unei probleme , nu de puţine ori apare situaţia executării
repetate a unei secvenţe de operaţii.O astfel de combinaţie , în care execuţia unui grup de
operaţii se repetă se numeşte ciclu sau iteraţie.Pentru reprezentarea ei se utilizează o comandă
de ciclare care specifică atâtoperaţiile care se repetă cât şi condiţia de repetare.
Forma generală a comenzii de ciclare cu test final este următoarea:
repetă
secvenţa
până condiţia
[]
Modul de execuţie al comenzii de ciclare este următorul:
1-se execută secvenţa
2-se evaluează condiţia şi dacă rezultatul este fals(condiţie neîndeplinită)se continuă cu etapa 1 , altfel
execuţia comenzii se termină şi se trece la comanda următoare.
Exemplu: Se dă algoritmul lui Euclid pentru afişarea celui mai mare divizor comun a
două numere întregi m,n(m>=n>0).
10. citeşte valorile lui m şi n
11. atribuie lui c valoarea lui n ( în variabila c se reţine cel mai mare divizor
comun )
12. atribuie lui r restul împărţirii întregi a lui m la n
13. dacă r diferit de 0 atunci treci la 7
14. scrie valoarea lui c
15. stop
16. atribuie lui m valoarea lui n
17. atribuie lui n valoarea lui r
18. treci la pasul 2
Se observă că operaţiile care se realizează calculul restului şiactualizarea valorilor c, m şi n se
repetă.
Folosind Descrierea în Pseudocod a algoritmului şi ciclul cu test final vom avea:
citeşte m,n
repetă
atribuie c n , r m-int(m/n)*n
atribuie mn , n r
până r=0
_[]
scrie c
stop
Condiţia de terminare a ciclului poate fi orice expresie logică.Secvenţa de operaţii din ciclu
alcătuieşte corpul ciclului .Ea poate conţine oriceoperaţii, inclusiv iteraţii.
l) Ciclul cu test iniţial – În cazul ciclurilor sau iteraţiilor condiţia de ciclare poate apare şi la
începutul secvenţei de ciclare
Forma generală este :
cât timp condiţia execută
19
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
secvenţa
[]
Condiţia poate fi orice expresie logică , iar secvenţa poate conţine orice comenzi , inclusiv
comenzi de ciclare.
Modul de execuţie al ciclului cu test iniţial :
1-se evaluează condiţia;dacă rezultatul este fals(condiţie neîndeplinită) execuţia se termină,iar dacă
rezultatul este adevărat se continuă secvenţa(etapa 2)
2-se execută secvenţa,după care se continuă cu 1.
În cazul în care rezultatul evaluării condiţiei este fals încă de la început,secvenţa nu se
execută niciodată spre deosebire de ciclul cu test final,când secvenţa se executa cel puţin o dată.
Scrierea algoritmului lui Euclid în Pseudocod folosindciclul cu test iniţial ne conduce la:
citeşte m,n
atribuie c n , r m-int(m/n)*n
cât timp r <> 0 execută
atribuie m n , n r, c n
atribuie r m-int(m/n)*n
[]
scrie c
stop
m) Ciclul de contor, cu forma generală:
pentru contor = val iniţială, val.finală,pas execută
secvenţa
[]
unde prin contor se înţelege o variabilă cu valori întregi:”valoarea iniţială, finală şi pas” pot fi expresii
aritmetice cu valori întregi.
Execuţia ciclului cu contor se explicitează astfel:
5) variabilei contor i se atribuie valoarea iniţială;
6) se verifică condiţia contor > val. Finală; dacă rezultatul este fals se continuă cu, astfel
execuţia ciclului se termină;
7) se execută secvenţa
8) se modifică valoarea contorului cu pasul p şi se continuă cu pasul 2)
Exemplu: aflarea lui n!
Observaţii: 1. Dacă pasul de ciclare este 1, se poate omite
2. Algoritmul a fost completat şi pentru cazul în care n = 0
citeşte n
atribuie p = 1
dacă n>0 atunci
pentru i=1,n execută
atribuie p=p*i
[]
[]
scrie p
stop
n) Proceduri şi funcţii
În rezolvarea unor probleme apar frecvent situaţii când un număr decomenzi se repetă
schimbându-se numai variabilele ce compun aceste comenzi,structura comenzilor rămânând aceeaşi.
Pentru a nu repeta acel număr de comenzi în mai multe locuri în cadrul descrierii algoritmului de
rezolvare a problemei se folosesc procedurile şi funcţiile.
Procedura – descrie în termeni generali un algoritm cu posibilitatea de a aplica acel algoritm în
diverse cazuri particulare concrete.
20
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
S=
Descrierea în Pseudocod a procedurii este :
Procedura norma (a, n; s) este :
atribuie s 0
pentru i=1,n,1 execută
atribuie s s + |ai|
[]
sfârşit norma
Numele procedurii este “norma”.Parametrii de intrare necesari pentru a se realiza calculele din
procedură sunt vectorul a şi numărul de elemente ale vectorului n, iar parametrul de ieşire este S,prin
el se obţine rezultatul calculelor- norma . Separarea parametrilor de ieşire de cel de intrare se face prin
punct şi virgulă . Parametrii de intrare şi cei de ieşire specificaţi la definirea procedurii se numesc
parametrii formali.
Exemplu: Să se folosească procedura definită pentru a determina dacă norma vectorului x de l
componente este mai mare decât norma vectorului w de m componente.
Descrierea în Pseudocod a algoritmului de aflare a celei mai mari dintre normele vectorilor x şi
w este următoarea :
citeşte l ,(xi , i = 1, 1)
citeşte m,(xi , i = 1,m)
execută norma (x ,l ; s1)
execută norma (w,m; s2)
dacă s1>s2 atunci
scrie ‘norma vectorului x este mai mare’
altfel
scrie ‘norma vectorului w este mai mare’
[]
stop
În apelulprocedurii norma , parametrii x,l,s1,respectiv w,m,s2 sunt parametrii actuali.
Comanda “execută” urmată de numele procedurii are ca efect execuţia operaţiilor care
constituie procedura cu numele specificat , în care valorile parametrilor formali sunt înlocuite cu
valorile parametrilor efectivi corespunzători,adică parametrii a,n,s din procedura sunt înlocuiţi cu x,l,s1
respectiv w,m,s2 din apelul procedurii.
21
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
= =
22
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
T - T atribuie S0,T+1
pentru i=1,n,1 execută i:=1
atribuie S S + T*(1 / (2*i-1) )
T -T
NU DA
[] i<=n
atribuie PI 4 * S S := S + T*(1 / (2*i-1) )
scrie PI T := - T
stop i:=i+1
Variabila T asigură însumarea corectă
a termenilor cu semne contrare. T:=-T
d)Programul Pascal
Program calcul_pi; Scrie PI
var
i,n:integer; STOP
s,pi,t:real;
BEGIN{main}
writeln(‘introduceti valoarea lui
n:intreg’);
readln(n);
s:=0;t:=1;
for i:=1 to n do
begin
s:=s + t / (2 * i - 1);
t:= - t ;
end;
pi := 4 * s ;
writeln(‘valoarea lui PI=’,PI:10,8);
END.
23
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Să se calculeze pentru un n dat , toţi termenii şirului lui Fibonacci, cunoscând relaţia de
recurenţă f k = f k-1+ f k-2 , pentru orice k >= 2 şi f0 =0, f1 = 1
a) Descrierea algoritmului în limbaj natural
Relaţia de recurenţă necesită două valori iniţiale f 0 şi f . Această relaţie va fi aplicată de n-2 ori ,
actualizând de fiecare dată pe f k-2 şi f k-1.Deci pentru calculul termenului curent f k sunt suficienţi 2
termeni consecutivi din şir. Vom nota cu “a” termenul f k-2 ,cu “b” f k-1 şi cu “c” termenul f k calculat.
b.) Descrierea algoritmului în pseudocod:
citeşte n
scrie n
{iniţializează primi 2 termeni ai şirului}
atribuie a 0, b 1
scrie a,b {primi doi termeni}
pentru k=3, n, 1 execută
atribuie c a+b {calculează termenul curent}
24
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
25
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
26
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
var n,nr:word;
begin
write('n='); readln(n);
nr:=0;
while (n<>0) do begin
nr:=nr+1;
n:=n div 10;
end;
write(nr);
end.
3) Pentru a, b numere naturale date, 0<=a<b, sa se afiseze toate numerele
deosebite din intervalul [a,b].Pentru fiecare numar deosebit se va afisa o
singura descompunere.Sa se precizeze numarul lor.Un numar natural m este
deosebit daca exista un numar natural n astfel incat m=n +s(n), unde s(n)
este suma cifrelor lui n.
Exemplu:
In intervalul [30,100] sunt 64 numere deosebite.}
var a,b,m,n,n1,s,nr:word;
begin
write('a='); readln(a);
write('b='); readln(b);
if b<=a then begin
writeln('Data incorecta!'); readln; exit; end;
nr:=0;
for m:=a to b do
for n:=0 to m do begin
n1:=n; s:=0;
while n1>0 do begin
inc(s,n1 mod 10);
n1:=n1 div 10; end;
if m=n+s then begin
inc(nr);
write(m,'este un numar deosebit.');
writeln(' ',m,'=',n,'+',s);
if (m-a+1) mod 20=0 then
readln;
break
end
end;
writeln('in intervalul[',a,',',B,'] SUNT',NR,'NUMERE DEOSEBITE');
readln;
end.
4) Se citeste un numar natural mai mare strict decat 9 avand numar impar de
cifre (validare).Sa se afiseze numarul obtinut prin eliminarea cifrei din
27
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
28
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
29
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Ne dam seama de acest lucru comparand ultimele doua cifre ale lui n.Dar daca
aceste sunt egale?Pentru a rezolva aceasta problema am facut un 'while' ce
elimina ultimele cifre din n. Apoi am facut o conventie: daca n are cifrele
in ordine descrescatoare , t=0, iar daca le are in ordine crescatoare t=1.}
var n,c,t,r:word;
ok:boolean;
begin
ok:=true;
write('n='); readln(n);
c:=n mod 10; n:=n div 10;
while c= n mod 10 do
n:=n div 10;
if c<n mod 10 then t:=0
else t:=1;
r:=n mod 10; n:=n div 10;
while n<>0 do begin
c:=r;
if (c> n mod 10) and (t=0) then ok:=false;
if (c< n mod 10) and (t=1) then ok:=false;
r:=n mod 10; n:=n div 10;
end;
if ok then writeln('bine ordonat')
else writeln('nu e bine ordonat');
end.
10) Se dau doua numar natural x si y cu cel mult zece cifre.Se cere sa se
afiseze suma dintre produsul cifrelor lui x si produsul cifrelor lui y.}
var
x, y, px, py:longint;
begin
write ('x='); readln(x);
write ('y='); readln(y);
px:=1;
while x<>0 do begin
px:=px*(x mod 10);
x:=x div 10;
end;
py:=1;
while y<>0 do begin
py:=py *(y mod 10);
y:=y div 10;
end;
writeln (px+py);
readln;
end.
11) Sa se determine cel mai mare numar care se poate forma cu
cifrele unui numar natural citit de la tastatura.}
var
x,i,c ,nr , ap:longint;
begin
writeln('dati numarul ');readln(nr);
for c:=9 downto 0 do begin
x:=nr;
ap:=0;
repeat
if x mod 10=c then inc(ap);
x:=x div 10;
until x=0;
for i:=1 to ap do write (c);
end;
readln;
30
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end.
12) Sa se determine cel mai mic nr. nat. care se poate
forma cu cifrele unui nr nat. citit de la tastatura.}
var x,i,c,nr,ap,ap0,w:longint;
begin
writeln('nr=');
readln(nr);
w:=0;
for c:=0 to 9 do begin
x:=nr;
ap:=0;
ap0:=0;
repeat
if x mod 10=c then inc(ap);
if x mod 10=0 then inc(ap0);
x:=x div 10;
until x=0;
if(c<>0)and (ap>0)then begin
if w=0 then begin
write(c);
for i:=1 to ap0 do write(0);
dec(ap); inc(w); end;
for i:=1 to ap do
write(c);
end;
end;
end.
3.5.2 Divizibilitate
1)Determinaţi toate numerele care sunt multipli de k, care depăşesc valoarea n.
program multipli2;
var k,i,n:longint;
begin
write('k=');readln(k);
write('n=');readln(n);
i:=k;
while i<=n do
begin
write(i,' ');
inc(i,k);
end;
end.
2) Se citesc n numere naturale.Sa se numere cate din ele sunt pare.
var n,i,x,nr_pare:integer;
begin
Write('n='); readln(n);
nr_pare:=0;
for i:=1 to n do begin
read(x);
if x mod 2 =0 then
nr_pare:=nr_pare+1;
end;
write(nr_pare);
end.
31
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
var n,nr_div,i:integer;
begin
Write('n='); readln(n);
nr_div:=0;
for i:=1 to n do
if n mod i=0 then
nr_div:=nr_div+1;
write(nr_div);
end.
4) Sa se genereze toate numerele naturale de patru cifre de forma 1bcd care
indeplinesc simultan conditiile:d<c, b-c=1, iar b si d sunt divizibile cu 3 .
Sa se precizeze numarul lor.
Exemplu:
Sunt 6 numere:1320, 1650, 1653, 1980, 1983, 1986}
var b,c,d,n:0..9;
nr:word;
begin
n:=0;
for b:=3 to 9 do
for d:=0 to 6 do begin
c:=b-1;
if (d<c) and (b mod 3=0) and (d mod 3=0) then begin
nr:=1000+100*b+10*c+d;
write(nr:5); inc(n);
end;
end;
writeln;
writeln('sunt',n,'numere');
end.
5) Sa se verifice daca numarul natural n este perfect sau nu.( n este perfect
daca este egal cu suma divizorilor sai mai mici ca el).
Exemplu:
n=6 este perfect deoarece 6=1+2+3.}
var n,i,s:word;
begin
write('n='); readln(n);
s:=0;
for i:=1 to n div 2 do
if n mod i=0 then s:=s+i;
if n=s then
writeln('numar perfect')
else
writeln('numarul nu este perfect');
end.
6) Sa se determine cel mai mic numar natural nenul care are exact n divizori
(inclusiv divizorii banali), d>=2 dat.Sa se afiseze acest numar impreuna cu
divizorii sai.
Exemplu:
d=10 : n=48
Divizori: 1,2,3,4,6,8,12,16,24,48}
var d,nr:byte;
n,i:word;
begin
repeat
write('d='); readln(d)
until d>=2;
32
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
n:=2;
repeat
nr:=0;
for i:=1 to n do
if n mod i=0 then inc(nr);
if nr=d then begin
writeln('Cel mai mic numar natural cu exact',d,'divizori este',n);
write('Divizorii lui', n,' sunt:');
for i:=1 to n do
if n mod i=0 then write(i:5);
writeln;
break end
else inc(n)
until false;
readln
end.
7) SA se determine descompunerea in factori primi a unui numar natural n,
citit de pe mediul standard de intrare.Afisarea se va efectua ca in exemplul
urmator.
Exemplu:
pentru n=12 avem:
12|2
6|2
3|3
1|-}
var n,p:word;
begin
write('n='); read(n); p:=2;
while n>1 do
begin
while n mod p=0 do
begin
writeln(n,'|',p);
n:=n div p;
end;
p:=p+1;
end;
writeln(1,'|-');
end.
8) SA se determine suma numerelor naturale mai mici ca n, divizibile cu 5.}
var i,n,s:word;
begin
write('n='); readln(n);
s:=0;
for i:=5 to n do
if i mod 5=0 then s:=s+i;
writeln('s=',s);
end.
9) Sa se determine cifrele x si y astfel incat numarul 1x2y sa fie divizibil
cu 3.
Solutie:
Daca x si y sunt cifre atunci x,y apartin multimii{0,1,..,9) cu x<>0.Vom
verifica daca suma 1+x+2+y=3+x+y este divizibila cu 3}
var x,y:byte;
begin
for x:=1 to 9 do
for y:=0 to 9 do
if (x+y+3) mod 3=0 then
writeln(1,x,2,y);
end.
33
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
34
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
readln;
end.
3.5.2 Numere prime
var n,i:integer;
prim:boolean;
begin
write('n='); readln(n);
prim:=true;
for i:=2 to trunc(sqrt(n)) do
if n mod i =0 then
prim:=false;
if prim then
write('Numarul este prim')
else
write('Numarul nu este prim');
end.
2) Se citeste un numar natural n.Sa se afiseze divizorii sai primi.
ex:n=9
=>3}
var n,i,j:integer;
prim:boolean;
begin
write('n='); read(n);
for i:=2 to n-1 do
if n mod i=0 then begin
prim:=true;
for j:=2 to trunc(sqrt(i)) do
if i mod j =0 then
prim:=false;
if prim then write(i);
end;
end.
3) Sa se afiseze toate numerele prime mai mici sau egale decat n, n>1 dat.
ex:n=10
=>2 3 5 7}
var n,i,j:byte;
prim:boolean;
begin
write('n='); readln(n);
for i:=2 to n do begin
prim:=true;
for j:=2 to trunc(sqrt(i)) do
if i mod j=0 then begin
prim:=false; break; end;
if prim then write(i:5);
end;
writeln;
end.
4) Sa se afiseze toate numerele naturale x mai mici decat n,natural, cu
proprietatea ca x-1 si x+1 sunt numere prime.
Exemplu:
pentru n=15 se vor afisa: 4,6,12.}
var x,y,n,i,k:integer;
t:boolean;
begin
35
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
write('n='); readln(n);
for x:=2 to n-2 do
begin
k:=0;
t:=true;
for i:=2 to trunc(sqrt(x)) do
if x mod i=0 then t:=false;
if t then k:=k+1;
y:=x+2; t:=true;
for i:=2 to trunc(sqrt(y)) do
if y mod i=0 then t:=false;
if t then k:=k+1;
if k=2 then write (x+1,' ');
end;
end.
5) Se citeste un numar natural de cel mult 8 cifre. Sa se afiseze cel
mai apropiat numar prim fata de acesta.}
VAR x,i,k,n1,n2: longint;
ok: boolean;
begin
writeln('dati numarul ');
readln (x); n1:=x;
repeat
inc(n1);
ok:=true;
for i:=2 to trunc(sqrt(n1)) do
if n1 mod i =0 then ok:=false;
until ok;
n2:=x+1;
repeat
dec(n2); ok:=true;
for i:=2 to trunc (sqrt(n2)) do
if n2 mod i=0 then ok:=false;
until ok;
if k-n2<n1-x then writeln (n2)
else writeln(n1);
readln;
end.
6) Se da un numar natural n (0<n<1000000).Se cere sa se afiseze toate
perechile de numere gemene (a,b), a,b<=n. Perechea (a,b) este o
pereche de numere gemene daca a si b sunt prime si valoarea absoluta a
diferenteia-b este 2.}
var
i,j,n,l:integer;
bec: boolean;
begin
write ('n='); readln(n);
for i:=2 to n-2 do begin bec:=true;
for j:=2 to trunc(sqrt(i)) do
if i mod j=0 then bec:= false;
if bec then begin
l:=trunc (sqrt(i+2));
for j:=2 to l do
if (i+2) mod j=0 then
bec:=false;
if bec then write ('(',i,',',i+2,') ');end;
end;
readln;
end.
36
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
7) Dându-se un număr întreg N, să se afişeze toţi factorii primi ai acestuia precum şi ordinele lor de
multiplicitate.
a) Descrierea algoritmului în limbaj natural:
O soluţie posibilă ar fi aceea de a alege dintre numerele 2,3,4,5...d...[n/2] pe acelea care sunt
numere prime urmând a fi “extrase” din numărul n.Ordinul de multiplicare al fiecărui factor prim d va fi
egal cu numărul de împărţiri cu rest nul care se pot face succesiv cu el.Pentru a verifica că d este
număr prim trebuie cercetată divizibilitatea sa cu 2,3,4,...[sqrt(d)],ceea ce presupune un număr mare de
împărţiri.O serie de observaţii ce se vor face va conduce la reducerea numărului de calcule.Dintre toate
numerele pare, singurul număr prim este 2.Deci este suficient să căutăm factorii primi numai printre 2 şi
numerele impare ce satisfac condiţia 2k+1<=[n/2] (partea întreagă din n/2).
Dacă se scot din “n” divizorii săi în ordine crescătoare, un număr neprim nu va fi găsit divizor al
lui n, deoarece proprii săi factori primi au fost eliminaţi din n. De exemplu un număr nu se mai divide cu
25 după ce toţi divizorii 5 au fost eliminaţi. Deci nu este necesar să se verifice dacă un număr este prim.
Algoritmul ne asigură că dacă un număr este divizor al lui n atunci acesta este un divizor prim.
Căutarea divizorilor este o operaţie care se repetă ciclic necunoscându-se aprioric numărul de
repatări. Operaţia continuă până numărul mai admite divizori (n>1). Dacă n=1, el nu admite divizori, deci
ciclul nu se va efectua niciodată (se va folosi ciclu cu test iniţial).
Întrucât valoarea lui n se modifică prin extragerea divizorilor,este necesară afişarea sa înaintea
începerii procesului de căutare a acestora.
b) Descrierea şi semnificaţia structurilor de date folosite
n : numărul ce se descompune
d : divizorul (potenţial )
m : ordinul de multiplicare
c) Descrierea algoritmului în Pseudocod
O primă formă arată astfel:
citeşte n
scrie n
atribuie d 2
cât timp *n mai admite divizori execută
* determină multiplicitatea eventualului divizor şi extrage d din n
dacă *d a fost divizor atunci
afişează d şi ordinul de multiplicare
[]
trecere la următorul d
[]
stop
Acţiunea “*determină multiplicitatea eventualului divizor d şi îl extrage pe d din n” are un
caracter ciclic, necunoscându-se numărul de repetări ale ciclului.Această acţiune se poate realiza în
Pseudocod astfel:
atribuie m 0 {ordinul de multiplicitate}
cât timp *n estedivizibil cu d execută
*extrage d din n
atribuie m m+1
[]
Deoarece divizorii se caută printre numerele 2,3,5,7.... acţiunea”*trecere la următorul d” se
realizează în Pseudocod astfel :
dacă d=2 atunci
atribuie d 3
altfel
atribuie d d + 2
[]
Acţiunea “* îl extrage pe d in n” se cere realizează astfel:
37
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
atribuie n n div d
Pentru valaorea maximă a lui d nu trebuiesc impuse condiţii , d va căpăta noi valori atât timp
cât n mai admite divizori.El nu va putea avea o valoare mai mare decât [ n / 2 ].
Având în vedere faptul că un număr n este prim dacă nu se divide cu 2,3,4,...[sqrt(n)]
algoritmul poate fi inductabil. Deci, trebuie căutaţi divizori ai lui n până la [sqrt(n)] şi nu până la [n/2]. În
final n va conţine iltimul divizor prim (cel mai mare) dacă acesta are multiplicitatea 1. În caz contrar, n va
fi 1. Algoritmul trebuie să facă distincţie între cele 2 situaţii.
Deoarece funcţia sqrt(n) oferă un rezultat de tip real, care poate fi afectat de erorile interne
operării cu numere reale, de exemplu sqrt(16) are valoarea 3,99999E+00, iar trunc(sqrt(16))=3, va
trebui introdusă corecţia sqrt(n+0.5), pentru ca algoritmul să lucreze corect.
citeşte n STAR
atribuie d 2 T
cât timp d<=(sqrt(n+0.5)) execută Citeste
atribuie m0 n
cât timp n mod d =0 execută
d := 2
atribuie n n div d
mm+1 DA
d<=(sqrt(n+0.5))
[]
dacă m>0 atunci m:=0
scrie d , m
[] n mod d :=0
dacă d = 2 atunci
atribuie d 3 n :=n divd
altfel m := m + 1
atribuie d d + 2 NU
NU DA
[] m>0
[]
Scrie d,m
dacă n > 1 atunci
scrie n
NU DA
[] d: = 2
n>1
stop
d := 3 d:= d + 2
Scrie n
STOP
d)Programul Pascal
Program divizorii ;{descompunere în factori primi}
var n,d,m:integer;
BEGIN{main}
write (‘introduceti n:integer’);
readln(n);
writeln(n:4,’are urmatorii factori primi’);
writeln(‘factor’,’‘:5,’multiplicitate’);
d:=2;{cel mai mic numar prim}
while d<= trunc(sqrt(n+0.5)) do
begin
38
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
m:=0;
while(n mod d)= 0 do
begin
n:=n div d;
m:=m+1;
end;
if m>0 then
writeln(d:5,’ ‘:9,m:2);
if d = 2 then d:=3
else d:=d+2;
end;
if n>1 then writeln(n:5,’ ‘:10,’1’);
END.
3.5.3 Algoritmul lui Euclid
1)Să se calculeze c.m.m.d.c. şi c.m.m.m.c a două numere întregi aplicând algoritmul lui
Euclid.
a.) Descrierea algoritmului în limbaj natural:
Se ştie că c.m.m.m.c a două numere A şi B este egal cu raportul dintre produsul celor două numere
şi c.m.m.d.c. al celor două numere. Ca atare în variabila p se va reţine produsul celor două numere.
Variabila CMMMC va reţine c.m.m.m.c, iar variabila CMMDC va reţine c.m.m.d.c. Conform
algoritmului lui Euclid de aflare a c.m.m.d.c se împarte cel mai mare număr (A) la cel mai mic (B) şi se
calculează restul împărţirii întregi (R). Dacă restul împărţiirii este 0 atunci c.m.m.d.c. este B. În caz
contrar se fac atribuirile: lui A i se atribuie B iar lui B i se atribuie R şi procesul se continuă până R=0.
Dacă la introducerea datelor B>A, se schimbă între ele cele două valori.
Dacă cel mai mic număr este 0 se va tipări mesajul ‘unul dintre numere este 0’ şi nu se va calcula
c.m.m.m.c.
Pentru calculul restului împărţirii se va folosi operatorul PASCAL ,,mod”.
b.) Descrierea şi semnificaţia structurilor de date folosite:
A,B : cele două numere întregi
CMMDC, CMMMC : variabile întregi pentru calculul c.m.m.d.c. şi c.m.m.m.c.
c)Descrierea şi semnificaţia structurilor de date folosite
a,b : cele două numere întregi
cmmdc,cmmmc : variabile xîntregi pt.calculul cmmdc şi cmmmc
p : produsul celor două numere ( pentru calculul cmmmc)
x : variabilă auxiliară
d)Descrierea algoritmului în Pseudocod
citeşte a,b
atribuie p a * b { reţine produsul numerelor }
dacă a<b atunci
atribuie x a {schimbă cele două valori între ele}
ab
bx
[]
dacă b<>0 atunci
atribuie r a mod b {restul împărţirii întregi }
cât timp r<>0 execută
atribuie a b {pregăteşte o nouă reluare
39
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
a algoritmului }
br
r a mod b
[]
atribuie cmmdc b
cmmmc p / b
scrie cmmmc,cmmdc
altfel
scrie ‘ unul din termeni este zero’
[]
stop
c)Programul Pascal
Program Euclid;
var a,b,x,p,r,cmmdc,cmmmc:integer;
BEGIN{main}
write(‘introduceţi a si b : integer’);
readln(a,b);
p:=a*b;
if a<b then
begin
x:=a;
a:=b;
b:=x;
end;
if b<>0 then
begin
r:=a mod b;
while r<>0 do
begin
a:=b
b:=r;
r:=a mod b;
end;
cmmdc:=b;
cmmmc:=p div b;
writeln(‘cmmdc=’,cmmdc:8,
’cmmmc=’,cmmmc:9);
end
else writeln(‘unul din termeni este
zero’);
END.
2
40
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
citeşte n
scrie n
{iniţializează primi 2 termeni ai şirului}
atribuie a 0, b 1
scrie a,b {primi doi termeni}
pentru k=3, n, 1 execută
atribuie c a+b {calculează termenul curent}
a b {actualizarea ultimilor doi}
b c {termeni din şir}
scrie c
stop
d.) Programul PASCAL:
program fibonacii;
var
a,b,c,k,n:integer;
BEGIN{main}
write('Introduceti nr. de
termeni:');
readln(n);
a:=0; b:=1;
write(a:3);
for k:=3 to n do
begin
c:=a+b;
a:=b; b:=c;
write(c:3)
end;
END.
2) ) Calculul termenului de rang n din sirul Fibonacci, n>0 dat.Sirul lui
Fibonacci este definit astfel: f(1)=0, f(2)=1, f(n)=f(n-1)+f(n-2).
Exemplu:
n=7 : 1, 1, 2, 3, 5, 8,13.}
var n,a,b,c,i,fibo:word;
begin
write('n='); readln(n);
if n=0 then fibo:=0
else if n=1 then fibo:=1
else begin
a:=0; b:=1;
for i:=2 to n do begin
c:=a+b; a:=b; b:=c; end;
fibo:=b; end;
writeln('Termenul de rangul',n,'din sirul lui Fibonacci:',fibo);
end.
3) Se citeste de la tastatura o valoare n intreaga,
pozitiva. Sa se verifice
daca acest numar este un termen in sirul lui Fibonacci. In caz contrar, sa
se descompuna intr-o suma de termeni Fibonacci.
41
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
ex:5=2+3}
Program Fibo;
var n,x,y,z,nr,k:longint;
BEGIN
write('Dati valoarea lui n ');
readln(n);
nr:=n;
k:=1;
repeat
x:=0;
y:=1;
z:=x+y;
while z<n do begin
x:=y;
y:=z;
z:=x+y;
end;
if z=n then begin
if k=1 then writeln(n,' este termen Fibonacci')
else writeln(z, '=',nr,'scris ca suma de termeni Fibonacci');
n:=0;
end
else begin
k:=2;
write(y,'+');
n:=n-y;
end;
until n=0;
readln;
END.
4) Sa se determine, fara a calcula efectiv termenii sirului Fibonacci, daca
2 nr m si n sunt termeni consecutivi ai sirului.Se va afisa pe ecran mesa-
jul DA daca raspunsul este afirmativ, respectiv mesajul NU daca raspunsul
este negativ.}
program ddd;
var a,b,c:integer;
begin
write('a='); readln(a);
write('b='); readln(b);
if a>b then
begin
c:=a; a:=b; b:=c;
end;
while b-a>1 do
begin
c:=b-a; b:=a; a:=c;
end;
if (a=2) and (b=3) or (a=1) and (b=1) or (a=0) and (b=1) then
writeln('Da')
else
writeln('Nu')
end.
42
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
clrscr;
writeln('Introduceti n:');readln(n);
s:=0;
for i:=1 to n do
begin
s:=s+i;
writeln('Suma primelor',i,'numere este',s);
end;
writeln('Suma totala este:',s);
readln;
end.
Varianta 2: Determinarea sumei a n numere folosind clauza downto .
program suma2;
var n,i,s:integer;
begin
writeln('Introduceti n:');readln(n);
s:=0;
for i:=n downto 1 do
begin
s:=s+i;
writeln('Suma ultimelor ',n-i+1,' numere este ',s);
end;
writeln(' Suma totala: ',s);
readln;
end.
2) Sa se calculeze suma S=1+1*2+1*2*3+...+1*2*....*n, unde n este un numar
natural citit.
ex:n=2
=>3
}
var p,n,s,i:integer;
begin
Write('n='); readln(n);
p:=1; s:=0;
for i:=1 to n do begin
p:=p*i;
s:=s+p;
end;
write(s);
end.
3) Pentru n>0 dat, sa se evalueze expresia:
E=1+1*3+1*3*5+...+1*3*..*(2*n+1)
Exemple:
a)n=2 : E=19
b)n=3 : E=124
c)n=4 : E=1069
d)n=5 : E=11464}
var n,i:byte;
e,p:word;
begin
write('n='); readln(n);
e:=1; p:=1;
for i:=1 to n do begin
p:=p*(2*i+1);
inc(e,p);
end;
write('E=',e);
end.
43
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Vom dezvolta in acest capitol aparatul matematic necesar pentru analiza eficientei algoritmilor,
incercand ca aceasta incursiune matematica sa nu fie excesiv de formala. Apoi, vom arata, pe baza unor
exemple, cum poate fi analizat un algoritm. O atentie speciala o vom acorda tehnicilor de analiza a
algoritmilor recursivi.
Notatia asimptotica
In Capitolul 1 am dat un inteles intuitiv situatiei cand un algoritm necesita un timp in ordinul unei
anumite functii. Revenim acum cu o definitie riguroasa.
Fie N multimea numerelor naturale (pozitive sau zero) si R multimea numerelor reale. Notam prin N+
si R+ multimea numerelor naturale, respectiv reale, strict pozitive, si prin R multimea numerelor reale
nenegative. Multimea {true, false} de constante booleene o notam cu B. Fie f : N R o functie
arbitrara. Definim multimea
Cu alte cuvinte, O( f ) (se citeste “ordinul lui f ”) este multimea tuturor functiilor t marginite superior de
un multiplu real pozitiv al lui f, pentru valori suficient de mari ale argumentului. Vom conveni sa
spunem ca t este in ordinul lui f (sau, echivalent, t este in O( f ), sau t O( f )) chiar si atunci cand
valoarea f (n) este negativa sau nedefinita pentru anumite valori n < n0. In mod similar, vom vorbi
despre ordinul lui f chiar si atunci cand valoarea t(n) este negativa sau nedefinita pentru un numar finit
de valori ale lui n; in acest caz, vom alege n0 suficient de mare, astfel incat, pentru n n0, acest lucru
sa nu mai apara. De exemplu, vom vorbi despre ordinul lui n/log n, chiar daca pentru n = 0 si n = 1
functia nu este definita. In loc de t O( f ), uneori este mai convenabil sa folosim notatia
t(n) O( f (n)), subintelegand aici ca t(n) si f (n) sunt functii.
Fie un algoritm dat si fie o functie t : N R astfel incat o anumita implementare a algoritmului sa
necesite cel mult t(n) unitati de timp pentru a rezolva un caz de marime n, n N. Principiul invariantei
(mentionat in Capitolul 1) ne asigura ca orice implementare a algoritmului necesita un timp in ordinul
lui t. Mai mult, acest algoritm necesita un timp in ordinul lui f pentru orice functie f : N R pentru
care t O( f ). In particular, t O(t). Vom cauta in general sa gasim cea mai simpla functie f, astfel
incat t O( f ).
Proprietatile de baza ale lui O( f ) sunt date ca exercitii (Exercitiile 5.1-5.7) si este recomandabil sa le
studiati inainte de a trece mai departe.
Notatia asimptotica defineste o relatie de ordine partiala intre functii si deci, intre eficienta relativa a
diferitilor algoritmi care rezolva o anumita problema. Vom da in continuare o interpretare algebrica a
notatiei asimptotice. Pentru oricare doua functii f , g : N R, definim urmatoarea relatie binara: f g
daca O( f ) O(g). Relatia “” este o relatie de ordine partiala in multimea functiilor definite pe N si
cu valori in R (Exercitiul 5.6). Definim si o relatie de echivalenta: f g daca O( f ) = O(g).
44
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Aceasta ierarhie corespunde unei clasificari a algoritmilor dupa un criteriu al performantei. Pentru o
problema data, dorim mereu sa obtinem un algoritm corespunzator unui ordin cat mai “la stanga”.
Astfel, este o mare realizare daca in locul unui algoritm exponential gasim un algoritm polinomial.
In Exercitiul 5.7 este data o metoda de simplificare a calculelor, in care apare notatia asimptotica. De
exemplu,
n33n2n8 O(n3(3n2n8)) = O(max(n3, 3n2n8)) = O(n3)
Ultima egalitate este adevarata, chiar daca max(n3, 3n2n8) n3 pentru 0 n 3, deoarece notatia
asimptotica se aplica doar pentru n suficient de mare. De asemenea,
chiar daca pentru 0 n 6 polinomul este negativ. Exercitiul 5.8 trateaza cazul unui polinom
oarecare.
Notatia O( f ) este folosita pentru a limita superior timpul necesar unui algoritm, masurand eficienta
algoritmului respectiv. Uneori este util sa estimam si o limita inferioara a acestui timp. In acest scop,
definim multimea
Exista o anumita dualitate intre notatiile O( f ) si ( f ). Si anume, pentru doua functii oarecare
f, g : N R, avem: f O(g), daca si numai daca g ( f ).
O situatie fericita este atunci cand timpul de executie al unui algoritm este limitat, atat inferior cat si
superior, de cate un multiplu real pozitiv al aceleiasi functii. Introducem notatia
( f ) = O( f ) ( f )
numita ordinul exact al lui f. Pentru a compara ordinele a doua functii, notatia nu este insa mai
puternica decat notatia O, in sensul ca relatia O( f ) = O(g) este echivalenta cu ( f ) = (g).
Se poate intampla ca timpul de executie al unui algoritm sa depinda simultan de mai multi parametri.
Aceasta situatie este tipica pentru anumiti algoritmi care opereaza cu grafuri si in care timpul depinde
atat de numarul de varfuri, cat si de numarul de muchii. Notatia asimptotica se generalizeaza in mod
natural si pentru functii cu mai multe variabile. Astfel, pentru o functie arbitrara f : N N R
definim
Multi algoritmi sunt mai usor de analizat daca consideram initial cazuri a caror marime satisface
anumite conditii, de exemplu sa fie puteri ale lui 2. In astfel de situatii, folosim notatia asimptotica
conditionata. Fie f : N R o functie arbitrara si fie P : N B un predicat.
45
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Notatia O( f ) este echivalenta cu O( f | P), unde P este predicatul a carui valoare este mereu true.
Similar, se obtin notatiile ( f | P) si ( f | P).
O functie f : N R este eventual nedescrescatoare, daca exista un n0, astfel incat pentru orice n n0
avem f (n) f (n1), ceea ce implica prin inductie ca, pentru orice n n0 si orice m n, avem
f (n) f (m). Fie b 2 un intreg oarecare. O functie eventual nedescrescatoare este b-neteda daca
f (bn) O( f (n)). Orice functie care este b-neteda pentru un anumit b 2 este, de asemenea, b-neteda
pentru orice b 2 (demonstrati acest lucru!); din aceasta cauza, vom spune pur si simplu ca aceste
functii sunt netede. Urmatoarea proprietate asambleaza aceste definitii, demonstrarea ei fiind lasata ca
exercitiu.
Proprietatea 5.1 Fie b 2 un intreg oarecare, f : N R o functie neteda si t : N R o functie
eventual nedescrescatoare, astfel incat
unde X poate fi O, , sau . Atunci, t X( f ). Mai mult, daca t ( f ), atunci si functia t este neteda.
unde a, b R+ sunt constante arbitrare. Este dificil sa analizam direct aceasta ecuatie. Daca
consideram doar cazurile cand n este o putere a lui 2, ecuatia devine
Prin tehnicile pe care le vom invata la sfarsitul acestui capitol, ajungem la relatia
Pentru a arata acum ca t (n log n), mai trebuie doar sa verificam daca t este eventual
nedescrescatoare si daca n log n este neteda.
t(1) = a 2(ab) = t(2)
t(n/2) t((n1)/2)
t(n/2) t((n1)/2)
Atunci,
t(n) = t(n/2)t(n/2)bn t((n1)/2)t((n1)/2)b(n1) = t(n1)
In fine, mai ramane sa aratam ca n log n este neteda. Functia n log n este eventual nedescrescatoare si
46
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
2n log(2n) = 2n(log 2 log n) = (2 log 2)n 2n log n
O(n n log n) = O(max(n, n log n)) = O(n log n)
De multe ori, timpul de executie al unui algoritm se exprima sub forma unor inegalitati de forma
si, simultan
pentru anumite constante c, d R+, n0 N si pentru doua functii t1, t2 : N R+. Notatia asimptotica ne
permite sa scriem cele doua inegalitati astfel:
t(n) t(n/2) t(n/2) O(n)
respectiv
t(n) t(n/2) t(n/2) (n)
t(n) t(n/2) t(n/2) (n)
Definim functia
Am vazut ca f (n log n). Ne intoarcem acum la functia t care satisface inegalitatile precedente. Prin
inductie, se demonstreaza ca exista constantele v d, u c, astfel incat
v t(n)/f (n) u
t ( f ) = (n log n)
Aceasta tehnica de rezolvare a inegalitatilor initiale are doua avantaje. In primul rand, nu trebuie sa
demonstram independent ca t O(n log n) si t (n log n). Apoi, mai important, ne permite sa
restrangem analiza la situatia cand n este o putere a lui 2, aplicand apoi Proprietatea 5.1. Deoarece nu
stim daca t este eventual nedescrescatoare, nu putem aplica Proprietatea 5.1 direct asupra inegalitatilor
initiale.
Nu exista o formula generala pentru analiza eficientei unui algoritm. Este mai curand o chestiune de
rationament, intuitie si experienta. Vom arata, pe baza exemplelor, cum se poate efectua o astfel de
analiza.
47
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Consideram algoritmul select din Sectiunea 1.3. Timpul pentru o singura executie a buclei interioare
poate fi marginit superior de o constanta a. In total, pentru un i dat, bucla interioara necesita un timp de
cel mult ba(ni) unitati, unde b este o constanta reprezentand timpul necesar pentru initializarea
buclei. O singura executie a buclei exterioare are loc in cel mult cba(ni) unitati de timp, unde c
este o alta constanta. Algoritmul dureaza in total cel mult
unitati de timp, d fiind din nou o constanta. Simplificam aceasta expresie si obtinem
(a/2)n2 (bca/2)n (dcb)
de unde deducem ca algoritmul necesita un timp in O(n2). O analiza similara asupra limitei inferioare
arata ca timpul este de fapt in (n2). Nu este necesar sa consideram cazul cel mai nefavorabil sau cazul
mediu, deoarece timpul de executie este independent de ordonarea prealabila a elementelor de sortat.
In acest prim exemplu am dat toate detaliile. De obicei, detalii ca initializarea buclei nu se vor
considera explicit. Pentru cele mai multe situatii, este suficient sa alegem ca barometru o anumita
instructiune din algoritm si sa numaram de cate ori se executa aceasta instructiune. In cazul nostru,
putem alege ca barometru testul din bucla interioara, acest test executandu-se de n(n1)/2 ori.
Exercitiul 5.23 ne sugereaza ca astfel de simplificari trebuie facute cu discernamant.
Timpul pentru algoritmul insert (Sectiunea1.3) este dependent de ordonarea prealabila a elementelor de
sortat. Vom folosi comparatia “x < T[ j]” ca barometru.
Sa presupunem ca i este fixat si fie x = T[i], ca in algoritm. Cel mai nefavorabil caz apare atunci cand
x < T[ j] pentru fiecare j intre 1 si i1, algoritmul facand in aceasta situatie i1 comparatii. Acest lucru
se intampla pentru fiecare valoare a lui i de la 2 la n, atunci cand tabloul T este initial ordonat
descrescator. Numarul total de comparatii pentru cazul cel mai nefavorabil este
(n2)
Vom estima acum timpul mediu necesar pentru un caz oarecare. Presupunem ca elementele tabloului T
sunt distincte si ca orice permutare a lor are aceeasi probabilitate de aparitie. Atunci, daca 1 k i,
probabilitatea ca T[i] sa fie cel de-al k-lea cel mai mare element dintre elementele T[1], T[2], …, T[i]
este 1/i. Pentru un i fixat, conditia T[i] < T[i1] este falsa cu probabilitatea 1/i, deci probabilitatea ca sa
se execute comparatia “x < T[ j]”, o singura data inainte de iesirea din bucla while, este 1/i. Comparatia
“x < T[ j]” se executa de exact doua ori tot cu probabilitatea 1/i etc. Probabilitatea ca sa se execute
comparatia de exact i1 ori este 2/i, deoarece aceasta se intampla atat cand x < T[1], cat si cand
T[1] x < T[2]. Pentru un i fixat, numarul mediu de comparatii este
ci = 1×1/i 2×1/i (i2)1/i (i1)2/i = (i1)/2 1/i
(n23n)/4 Hn (n2)
48
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
unde prin Hn= (log n) am notat al n-lea element al seriei armonice (Exercitiul 5.17).
Se observa ca algoritmul insert efectueaza pentru cazul mediu de doua ori mai putine comparatii decat
pentru cazul cel mai nefavorabil. Totusi, in ambele situatii, numarul comparatiilor este in (n2).
Algoritmul necesita un timp in (n2), atat pentru cazul mediu, cat si pentru cel mai nefavorabil. Cu
toate acestea, pentru cazul cel mai favorabil, cand initial tabloul este ordonat crescator, timpul este in
O(n). De fapt, in acest caz, timpul este si in (n), deci este in (n).
5.2.3 Heapsort
Vom analiza, pentru inceput, algoritmul make-heap din Sectiunea3.4. Definim ca barometru
instructiunile din bucla repeat a algoritmului sift-down. Fie m numarul maxim de repetari al acestei
bucle, cauzat de apelul lui sift-down(T, i), unde i este fixat. Notam cu jt valoarea lui j dupa ce se
executa atribuirea “j k” la a t-a repetare a buclei. Evident, j1 = i. Daca 1 < t m, la sfarsitul celei de-
a (t1)-a repetari a buclei, avem j k si k 2j. In general, jt 2jt-1 pentru 1 < t m. Atunci,
n jm 2jm-1 4jm-2 … 2m-1i
Numarul total de executari ale buclei repeat la formarea unui heap este marginit superior de
Demonstratia ultimei inegalitati rezulta din Exercitiul 5.26. Dar d = lg(n/2) implica d1 lg n si
d1 lg(n/8). Deci,
Din () deducem ca n/23n repetari ale buclei repeat sunt suficiente pentru a construi un heap,
deci make-heap necesita un timp t O(n). Pe de alta parte, deoarece orice algoritm pentru formarea
unui heap trebuie sa utilizeze fiecare element din tablou cel putin o data, t (n). Deci, t (n).
Puteti compara acest timp cu timpul necesar algoritmului slow-make-heap (Exercitiul 5.28).
Pentru cel mai nefavorabil caz, sift-down(T[1 .. i1], 1) necesita un timp in O(log n) (Exercitiul 5.27).
Tinand cont si de faptul ca algoritmul make-heap este liniar, rezulta ca timpul pentru algoritmul
heapsort pentru cazul cel mai nefavorabil este in O(n log n). Mai mult, timpul de executie pentru
heapsort este de fapt in (n log n), atat pentru cazul cel mai nefavorabil, cat si pentru cazul mediu.
49
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Algoritmii de sortare prezentati pana acum au o caracteristica comuna: se bazeaza numai pe comparatii
intre elementele tabloului T. Din aceasta cauza, ii vom numi algoritmi de sortare prin comparatie. Vom
cunoaste si alti algoritmi de acest tip: bubblesort, quicksort, mergesort. Sa observam ca, pentru cel mai
nefavorabil caz, orice algoritm de sortare prin comparatie necesita un timp in (n log n) (Exercitiul
5.30). Pentru cel mai nefavorabil caz, algoritmul heapsort este deci optim (in limitele unei constante
multiplicative). Acelasi lucru se intampla si cu mergesort.
Matematicianul francez Éduard Lucas a propus in 1883 o problema care a devenit apoi celebra, mai
ales datorita faptului ca a prezentat-o sub forma unei legende. Se spune ca Brahma a fixat pe Pamant
trei tije de diamant si pe una din ele a pus in ordine crescatoare 64 de discuri de aur de dimensiuni
diferite, astfel incat discul cel mai mare era jos. Brahma a creat si o manastire, iar sarcina calugarilor
era sa mute toate discurile pe o alta tija. Singura operatiune permisa era mutarea a cate unui singur disc
de pe o tija pe alta, astfel incat niciodata sa nu se puna un disc mai mare peste unul mai mic. Legenda
spune ca sfarsitul lumii va fi atunci cand calugarii vor savarsi lucrarea. Aceasta se dovedeste a fi o
previziune extrem de optimista asupra sfarsitului lumii. Presupunand ca in fiecare secunda se muta un
disc si lucrand fara intrerupere, cele 64 de discuri nu pot fi mutate nici in 500 de miliarde de ani de la
inceputul actiunii!
Observam ca pentru a muta cele mai mici n discuri de pe tija i pe tija j (unde 1 i 3, 1 j 3,
i j, n 1), transferam cele mai mici n1 discuri de pe tija i pe tija 6ij, apoi transferam discul n
de pe tija i pe tija j, iar apoi retransferam cele n1 discuri de pe tija 6ij pe tija j. Cu alte cuvinte,
reducem problema mutarii a n discuri la problema mutarii a n1 discuri. Urmatoarea procedura descrie
acest algoritm recursiv.
procedure Hanoi(n, i, j)
{muta cele mai mici n discuri de pe tija i pe tija j}
if n > 0 then Hanoi(n1, i, 6ij)
write i ““ j
Hanoi(n1, 6ij, j)
Consideram instructiunea write ca barometru. Timpul necesar algoritmului este exprimat prin
urmatoarea recurenta:
Acest algoritm este optim, in sensul ca este imposibil sa mutam n discuri de pe o tija pe alta cu mai
putin de 2n1 operatii. Implementarea in oricare limbaj de programare care admite exprimarea
recursiva se poate face aproape in mod direct.
Am vazut in exemplul precedent cat de puternica si, in acelasi timp, cat de eleganta este recursivitatea
in elaborarea unui algoritm. Nu vom face o introducere in recursivitate si nici o prezentare a metodelor
de eliminare a ei. Cel mai important castig al exprimarii recursive este faptul ca ea este naturala si
compacta, fara sa ascunda esenta algoritmului prin detaliile de implementare. Pe de alta parte, apelurile
recursive trebuie folosite cu discernamant, deoarece solicita si ele resursele calculatorului (timp si
50
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
memorie). Analiza unui algoritm recursiv implica rezolvarea unui sistem de recurente. Vom vedea in
continuare cum pot fi rezolvate astfel de recurente. Incepem cu tehnica cea mai banala.
5.3.1 Metoda iteratiei
Cu putina experienta si intuitie, putem rezolva de multe ori astfel de recurente prin metoda iteratiei: se
executa primii pasi, se intuieste forma generala, iar apoi se demonstreaza prin inductie matematica ca
forma este corecta. Sa consideram de exemplu recurenta problemei turnurilor din Hanoi. Pentru un
anumit n > 1 obtinem succesiv
t(n) = 2t(n1) 1 = 22t(n2) 2 1 = …
= 2n-1t(1)
t
Rezulta t(n) = 2n1. Prin inductie matematica se demonstreaza acum cu usurinta ca aceasta forma
generala este corecta.
5.3.2 Inductia constructiva
Inductia matematica este folosita de obicei ca tehnica de demonstrare a unei asertiuni deja enuntate.
Vom vedea in aceasta sectiune ca inductia matematica poate fi utilizata cu succes si in descoperirea
enuntului asertiunii. Aplicand aceasta tehnica, putem simultan sa demonstram o asertiune doar partial
specificata si sa descoperim specificatiile care lipsesc si datorita carora asertiunea este corecta. Vom
vedea ca aceasta tehnica a inductiei constructive este utila pentru rezolvarea anumitor recurente care
apar in contextul analizei algoritmilor. Incepem cu un exemplu.
si deci, f (n) O(n2). Aceasta ne sugereaza sa formulam ipoteza inductiei specificate partial IISP(n)
conform careia f este de forma f (n) = an2bnc. Aceasta ipoteza este partiala, in sensul ca a, b si c nu
sunt inca cunoscute. Tehnica inductiei constructive consta in a demonstra prin inductie matematica
aceasta ipoteza incompleta si a determina in acelasi timp valorile constantelor necunoscute a, b si c.
f (n) = a(n1)2b(n1)cn = an2(1b2a)n(abc)
Daca dorim sa aratam ca IISP(n) este adevarata, trebuie sa aratam ca f (n) = an2bnc. Prin
identificarea coeficientilor puterilor lui n, obtinem ecuatiile 1b2a = b si abc = c, cu solutia
a = b = 1/2, c putand fi oarecare. Avem acum o ipoteza mai completa, pe care o numim tot IISP(n):
f (n) = n2/2n/2c. Am aratat ca, daca IISP(n1) este adevarata pentru un anumit n 1, atunci este
adevarata si IISP(n). Ramane sa aratam ca este adevarata si IISP(0). Trebuie sa aratam ca
f (0) = a0b0c = c. Stim ca f (0) = 0, deci IISP(0) este adevarata pentru c = 0. In concluzie, am
demonstrat ca f (n) = n2/2n/2 pentru orice n.
51
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exista, din fericire, si tehnici care pot fi folosite aproape automat pentru a rezolva anumite clase de
recurente. Vom incepe prin a considera ecuatii recurente liniare omogene, adica de forma
a0tn a1tn-1 ¼ aktn-k = 0 ()
tn = xn
unde x este o constanta (deocamdata necunoscuta). Incercam aceasta solutie in () si obtinem
a0xn a1xn-1 ... akxn-k = 0
Solutiile acestei ecuatii sunt fie solutia triviala x = 0, care nu ne intereseaza, fie solutiile ecuatiei
a0xk a1xk-1 ... ak = 0
Presupunand deocamdata ca cele k radacini r1, r2, ..., rk ale acestei ecuatii caracteristice sunt distincte,
orice combinatie liniara
este o solutie a recurentei (), unde constantele c1, c2, ..., ck sunt determinate de conditiile initiale. Este
remarcabil ca () are numai solutii de aceasta forma.
Sa exemplificam prin recurenta care defineste sirul lui Fibonacci (din Sectiunea 1.6.4):
tn = tn-1 tn-2 n 2
tn tn-1 tn-2 = 0
x2 x 1 = 0
52
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
de unde determinam
c1,2 =
(n()-n)
care este cunoscuta relatie a lui de Moivre, descoperita la inceputul secolului XVI. Nu prezinta nici o
dificultate sa aratam acum ca timpul pentru algoritmul fib1 (din Sectiunea 1.6.4) este in (n).
Ce facem insa atunci cand radacinile ecuatiei caracteristice nu sunt distincte? Se poate arata ca, daca r
este o radacina de multiplicitate m a ecuatiei caracteristice, atunci tn = rn, tn = nrn, tn = n2rn, ..., tn = nm-1rn
sunt solutii pentru (). Solutia generala pentru o astfel de recurenta este atunci o combinatie liniara a
acestor termeni si a termenilor proveniti de la celelalte radacini ale ecuatiei caracteristice. Din nou, sunt
de determinat exact k constante din conditiile initiale.
tn = 5tn-1 8tn-2 4tn-3 n 3
iar t0 = 0, t1 = 1, t2 = 2. Ecuatia caracteristica are radacinile 1 (de multiplicitate 1) si 2 (de multiplicitate
2). Solutia generala este:
tn = c11n c22n c3n2n
a0tn a1tn-1 ... aktn-k = bnp(n) ()
unde b este o constanta, iar p(n) este un polinom in n de grad d. Ideea generala este ca, prin manipulari
convenabile, sa reducem un astfel de caz la o forma omogena.
tn 2tn-1 = 3n
In acest caz, b = 3 si p(n) = 1, un polinom de grad 0. O simpla manipulare ne permite sa reducem acest
exemplu la forma (). Inmultim recurenta cu 3, obtinand
3tn 6tn-1 = 3n+1
tn+1 2tn = 3n+1
53
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
tn+1 5tn 6tn-1 = 0
x2 5x 6 = 0
adica (x2)(x3) = 0.
Intuitiv, observam ca factorul (x2) corespunde partii stangi a recurentei initiale, in timp ce factorul
(x3) a aparut ca rezultat al manipularilor efectuate, pentru a scapa de parte dreapta.
Generalizand acest procedeu, se poate arata ca, pentru a rezolva (), este suficient sa luam
urmatoarea ecuatie caracteristica:
(a0xk a1xk-1 ¼ ak)(xb)d+1 = 0
tn = 2tn-1 1 n 1
tn 2tn-1 = 1
care este de forma () cu b = 1 si p(n) = 1, un polinom de grad 0. Ecuatia caracteristica este atunci
(x2)(x1) = 0, cu solutiile 1 si 2. Solutia generala a recurentei este:
tn = c11n c22n
Avem nevoie de doua conditii initiale. Stim ca t0 = 0; pentru a gasi cea de-a doua conditie calculam
t1 = 2t0 1
tn = 2n 1
Daca ne intereseaza doar ordinul lui tn, nu este necesar sa calculam efectiv constantele in solutia
generala. Daca stim ca tn = c11n c22n, rezulta tn O(2n). Din faptul ca numarul de mutari a unor
discuri nu poate fi negativ sau constant, deoarece avem in mod evident tn n, deducem ca c2 > 0.
Avem atunci tn (2n) si deci, tn (2n). Putem obtine chiar ceva mai mult. Substituind solutia
generala inapoi in recurenta initiala, gasim
1 = tn 2tn-1 = c1 c22n2(c1 c22n-1) = c1
54
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
5.3.5 Schimbarea variabilei
Uneori, printr-o schimbare de variabila, putem rezolva recurente mult mai complicate. In exemplele
care urmeaza, vom nota cu T(n) termenul general al recurentei si cu tk termenul noii recurente obtinute
printr-o schimbare de variabila. Presupunem pentru inceput ca n este o putere a lui 2.
T(n) = 4T(n/2) n n > 1
tk = 4tk-1 2k
(x4)(x2) = 0
T(n) = c1n2 c2n
Rezulta
T(n) = 4T(n/2) n2 n > 1
tk = 4tk-1 4k
cu ecuatia caracteristica
(x4)2 = 0
T(n) = c1n2 c2n2lg n
si obtinem
T(n) = 3T(n/2) cn n > 1
55
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
T(2k) = 3T(2k-1) c2k
tk = 3tk-1 c2k
cu ecuatia caracteristica
(x3)(x2) = 0
tk = c13k c22k
T(n) = c13lg n c2n
si, deoarece
alg b = blg a
obtinem
T(n) = c1nlg 3 c2n
deci,
In toate aceste exemple am folosit notatia asimptotica conditionata. Pentru a arata ca rezultatele
obtinute sunt adevarate pentru orice n, este suficient sa adaugam conditia ca T(n) sa fie eventual
nedescrescatoare. Aceasta, datorita Proprietatii 5.1 si a faptului ca functiile n2, n log n si nlg 3 sunt
netede.
Putem enunta acum o proprietate care este utila ca reteta pentru analiza algoritmilor cu recursivitati de
forma celor din exemplele precedente. Proprietatea, a carei demonstrare o lasam ca exercitiu, ne va fi
foarte utila la analiza algoritmilor divide et impera din Capitolul 7.
T(n) = aT(n/b) cnk n > n0
unde: n0 1, b 2 si k 0 sunt intregi; a si c sunt numere reale pozitive; n/n0 este o putere a lui b.
Atunci avem
56
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Unele probleme se pot rezolva, altele nu. De exemplu, o problemă notorie, a cărei imposibilitate este
riguros demonstrată în anii '30 de către matematicianul englez Alan Turing, este de a decide dacă un
program se va opri vreodată pentru o anumită instanţă a datelor de intrare.
Pe de altă parte, chiar între problemele care pot fi rezolvate, teoreticienii trag o linie imaginară între
problemele care au rezolvări ``rezonabil'' de rapide, şi restul problemelor, care se numesc ``intratabile''.
În mod arbitrar, dar nu ne-justificabil, o problemă se numeşte ``intratabilă'' dacă complexitatea ei este
exponenţială în mărimea datelor de intrare. (Nu uitaţi, este vorba de complexitate ``worst-case''
asimptotică.) O problemă este ``tratabilă'' dacă putem scrie complexitatea ei sub forma unui polinom,
de un grad oricît de mare.
Mulţimea tuturor problemelor de decizie (adică a problemelor la care răspunsul este da sau nu) cu
complexitate polinomială se notează cu P (de la polinom). De exemplu, problema de a găsi dacă o
valoare se află într-un vector este în clasa P; algoritmul exhibat mai sus este un algoritm în timp linear
(O(n)) pentru a răspunde la această întrebare.
(Ca o curiozitate: există şi probleme cu o complexitate ``ne-elementară'', care este mai mare decît
complexitatea oricărei probleme exponenţiale. O astfel de problemă este cea de decizie a adevărului
unei formule în teoria numită S1S, sau ``teoria monadică a succesorilor de ordinul 2''. Nu vă lăsaţi
intimidaţi de terminologie: aceasta este practic o teorie logică peste numerele naturale, în care avem
voie să scriem formule cu cuantificatori şi conectori logici, ca mai sus, dar avem şi dreptul să
cuantificăm peste mulţimi. Complexitatea deciziei unei formule logice într-o astfel de teorie este mai
Acest tip de algoritmi este surprinzător de bogat în consecinţe cu valoare teoretică. Aceşti algoritmi nu
sunt direct aplicabili, însă studiul lor dă naştere unor concepte foarte importante.
Surprinzătoare este şi definiţia corectitudinii unui astfel de algoritm. Un algoritm nedeterminist este
corect dacă există o posibilitate de executare a sa care găseşte răspunsul corect. Pe măsură ce un
57
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
algoritm nedeterminist se execută, la anumiţi paşi se confruntă cu alegeri nedeterministe. Ei bine, dacă
la fiecare pas există o alegere, care făcută să ducă la găsirea soluţiei, atunci algoritmul este numit
corect.
Astfel, un algoritm nedeterminist care caută ieşirea dintr-un labirint ar arăta cam aşa:
Pe scurt algoritmul se comportă aşa: dacă la nord nu e perete mergi încolo, sau, poate, dacă la sud e
liber, mergi încolo, sau la est, sau la vest. În care dintre direcţii, nu se precizează (este ne-determinat).
Este clar că dacă există o ieşire la care se poate ajunge, există şi o suită de aplicări ale acestor reguli
care duce la ieşire.
Utilitatea practică a unui astfel de algoritm nu este imediat aparentă: în definitiv pare să nu spună nimic
util: soluţia este fie spre sud, fie spre nord, fie spre este, fie spre vest. Ei şi? Este clar că aceşti algoritmi
nu sunt direct implementabili pe un calculator real.
În realitate existenţa un astfel de algoritm deja înseamnă destul de mult. Înseamnă în primul rînd că
problema se poate rezolva algoritmic; vă reamintesc că există probleme care nu se pot rezolva deloc.
În al doilea rînd, se poate arăta că fiecare algoritm nedeterminist se poate transforma într-unul
determinist într-un mod automat. Deci de îndată ce ştim să rezolvăm o problemă într-un mod
nedeterminist, putem să o rezolvăm şi determinist! Transformarea este relativ simplă: încercăm să
mergem pe toate drumurile posibile în paralel, pe fiecare cîte un pas. (O astfel de tehnică aplicată în
cazul labirintului se transformă în ceea ce se cheamă ``flood fill'': evoluez radial de la poziţia de plecare
în toate direcţiile).
Clasa tuturor problemelor care se pot rezolva cu algoritmi nedeterminişti într-un timp polinomial se
notează cu NP (Nedeterminist Polinomial). Este clar că orice problemă care se află în P se află şi în NP,
pentru că algoritmii determinişti sunt doar un caz extrem al celor determinişti: în fiecare moment au o
singură alegere posibilă.
Din păcate transformarea într-un algoritm determinist se face pierzînd din eficienţă. În general un
algoritm care operează în timp nedeterminist polinomial (NP) poate fi transformat cu uşurinţă într-un
algoritm care merge în timp exponenţial (EXP). Avem deci o incluziune de mulţimi între problemele
de decizie: P NP EXP.
Partea cea mai interesantă este următoarea: ştim cu certitudine că P EXP. Însă nu avem nici o idee
despre relaţia de egalitate între NP şi P sau între NP şi EXP. Nu există nici o demonstraţie care să
infirme că problemele din NP au algoritmi eficienţi, determinist polinomiali! Problema P=NP este cea
mai importantă problemă din teoria calculatoarelor, pentru că de soluţionarea ei se leagă o grămadă de
consecinţe importante.
58
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Problema aceasta este extrem de importantă pentru întreaga matematică, pentru că însăşi demonstrarea
teoremelor este un proces care încearcă să verifice algoritmic o formulă logică (cum am văzut mai sus
de pildă); teoremele la care există demonstraţii ``scurte'' pot fi asimilate cu problemele din mulţimea
NP (la fiecare pas dintr-o demonstraţie putem aplica mai multe metode de inferenţă, în mod
nedeterminist; un algoritm trebuie să ghicească înşiruirea de metode aplicate pentru demonstrarea
enunţului); dacă orice problemă din NP este şi în P, atunci putem automatiza o mare parte din
demonstrarea de teoreme în mod eficient!
Problema P=NP este foarte importantă pentru criptografie: decriptarea este o problemă din NP (cel care
ştie cheia ştie un algoritm determinist polinomial de decriptare, dar cel care nu o ştie are în faţa o
problemă pe care nedeterminist o poate rezolva în timp polinomial). Dacă s-ar demonstra că P=NP
acest lucru ar avea consecinţe extrem de importante, iar CIA si KGB ar fi într-o situaţie destul de
proastă, pentru că toate schemele lor de criptare ar putea fi sparte în timp polinomial (asta nu înseamnă
neapărat foarte repede, dar oricum, mult mai repede decît timp exponenţial)!
Mai mult, în 1971 Cook a demonstrat că există o problemă specială în NP (adică pentru care se poate
da un algoritm eficient nedeterminist), numită problema satisfiabilităţii (notată cu SAT). Problema este
foarte simplă: dacă se dă o formulă booleană care cuprinde mai multe variabile, poate fi formula făcută
De la Cook încoace s-au mai descoperit cîteva sute de probleme NP-complete. Unele probleme care se
ivesc foarte adesea în practică s-au dovedit NP-complete! Acesta este un alt motiv pentru care clasa atît
de abstractă NP a problemelor cu algoritmi nedeterminişti este atît de importantă: foarte multe
probleme practice au algoritmi polinomiali nedeterminişti, dar cei mai buni algoritmi determinişti iau
un timp exponenţial!
Problema comis-voiajorului (turneu Hamiltonian de cost minim): dîndu-se o reţea de oraşe, o reţea de
drumuri între oraşe şi o lungime k, există un traseu de cost mai mic decît k trecînd prin fiecare oraş o
singură dată şi revenind la punctul de plecare?
Dîndu-se o mulţime de numere naturale, se poate împărţi în două mulţimi de numere de sume egale 2?
``Clica'': dîndu-se un graf G şi un număr k, are G un subgraf complet cu k vîrfuri (adică o mulţime de k
vîrfuri unite fiecare cu fiecare)?
``Acoperire'': dîndu-se un graf G şi un număr k, pot alege k vîrfuri în aşa fel încît toate muchiile din G au
un capăt ales?
O cantitate enormă de efort şi ingeniozitate a fost risipită pentru a încerca să se demonstreze că P=NP
sau opusul acestei afirmaţii, dar nici un rezultat concret nu a fost obţinut. Credinţa cvasi-unanimă este
că P=NP, dar numai matematica poate oferi vreo certitudine...
Din cauză că foarte multe probleme practice sunt în NP, şi ca aparent nu putem avea algoritmi
determinişti eficace pentru ele, cercetătorii şi-au îndreptat atenţia asupra unor clase noi de algoritmi,
care vor face obiectul secţiunilor următoare.
Algoritmi aproximativi
În secţiunile care urmează folosim tot timpul premiza nedemonstrată că PNP. Dacă P=NP, atunci
problemele pe care ne batem capul să le rezolvăm prin metode ciudate pot fi de fapt rezolvate exact şi
eficient.
59
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Optim şi aproximare
Într-adevăr, această metodă se bucură de un oarecare succes, dar nu de unul general. Algoritmii care
rezolvă o problemă de optimizare în speranţa unui rezultat sub-optimal se numesc ``algoritmi
aproximativi''.
Teoria algoritmilor aproximativi este relativ recentă (deşi ideea există de multă vreme), iar unele
rezultate sunt extrem de complicate. Ne vom mulţumi să dăm nişte exemple pentru a ilustra algoritmi
aproximativi în acţiune, şi tipul de rezultate care se pot obţine.
Vom ilustra două rezultate diferite din teoria algoritmilor aproximativi: algoritmi de aproximare
relativă, algoritmi de aproximare absolută a soluţiei (lămurim terminologia imediat).
Să notăm o instanţă a unei probleme cu I. Fie OPT(I) valoarea soluţiei optime pentru acea instanţă
(care există, dar pe care nu ştim s-o calculăm eficient), şi fie A(I) valoarea calculată de algoritmul
nostru aproximativ. Numim aproximaţia absolută dacă există un număr K, independent de instanţa I,
care are proprietatea că |OPT(I) - A(I)| < K. Numim aproximaţia relativă dacă există un R (numit
``performanţă'') astfel ca pentru orice instanţă I avem (A(I) / OPT(I)) < R (dacă problema caută un
maximum, atunci fracţia din definiţie trebuie inversată).
Problema rucsacului
Iată o variantă a problemei rucsacului care este NP-completă , dar pentru care se poate obţine cu foarte
mare uşurinţă un algoritm aproximativ relativ eficient.
Se dau o mulţime (mare) de rucsaci de capacitate egală (cunoscută, un număr natural). Se mai dă o
mulţime finită de obiecte, fiecare de un volum cunoscut (număr natural). Întrebarea este: care este
numărul minim de rucsaci necesari pentru a împacheta toate obiectele?
Algoritmul este banal: metoda ``greedy'': pune de la stînga fiecare greutate în primul rucsac liber:
Initializari:
o, folositi := 1, 0
do o <= nrobiecte -> liber[o] := capacitate od
Algoritm:
60
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
o := 1
do o <= nrobiecte ->
r := 1
do (liber[r] < marime[o]) -> r := r+1
od
folositi, liber[r], o :=
max(r, folositi), liber[r] - marime[o], o+1
od
Vom folosi o altă problemă NP-completă, pentru care avem imediat un algoritm de aproximare relativă
de performanţă 2, dar pentru care vom demonstra că nu există nici un algoritm de aproximare absolută.
Problema este cea a acoperirii unui graf, enunţată mai sus. Ca problemă de optimizare, ea se enunţă
astfel: ``care este numărul minim de vîrfuri care trebuie ``acoperite'' astfel ca toate muchiile dintr-un
graf să fie atinse?''
Pentru această problemă algoritmul greedy nu face multe parale ca algoritm de aproximare. Există însă
un algoritm relativ simplu, cu performanţă 2, care se foloseşte însă de un alt algoritm clasic, cel al
``cuplării'' (matching). Fără a intra în detalii, există un algoritm polinomial relativ sofisticat pentru a
calcula cuplări maximale pe grafuri4. Calculăm o cuplare maximală, după care luăm capetele tuturor
muchiilor care o formează: astfel obţinem o acoperire (uşor de demonstrat) care e cel mult dublă ca
mărime faţă de optim (pentru că în optim trebuie să se găsească cel puţin cîte un vîrf pentru fiecare
muchie din cuplare, iar noi am luat cîte două).
Iată şi un rezultat negativ interesant: pentru orice K fixat, nu există nici un algoritm care să dea pentru
problema acoperirii o soluţie aproximativă absolută la distanţa K de cea optimă pentru orice instanţă.
Demonstraţia este foarte simplă, odată ce ai văzut ideea, şi se bazează pe ``tehnica amplificării''. Iată
cum se face, prin reducere la absurd:
Să presupunem că avem un algoritm A care calculează pentru orice graf o acoperire care este cu cel
mult K noduri mai mare ca cea optimă (K e fixat). Cu alte cuvinte |OPT(G) - A(G)| < K. Să luăm o
instanţă arbitrară a problemei cuplării, G. Formăm un nou graf G 1 din G, care nu este conex, şi care
constă din K+1 copii ale lui G, alăturate. Aceasta este o instanţă perfect corectă a problemei acoperirii,
aşa că rulăm pe ea algoritmul nostru A. Acesta va oferi o acoperire care are cel mult cu K noduri mai
mult decît acoperirea optimă. (Vă reamintesc notaţiile: OPT(G) este valoarea optimă: numărul minim
de noduri pentru a acoperi muchiile, iar A(G) este valoarea calculată de algoritmul nostru.
Datorită faptului că cele K+1 copii ale lui G sunt neconectate, optimumul pentru G 1 este reuniunea a
K+1 optimumuri pentru G. Din cauza asta avem relaţia OPT(G 1) = (K+1) OPT(G). Fie acum H copia
lui G pe care A a marcat cele mai multe vîrfuri; atunci A(G 1) <= (K+1) A(H). Dar din proprietăţile lui
A avem: |OPT(G1) - A(G1)| < K, sau |(K+1) OPT(H) - (K+1) A(H)| < K, ori |OPT(H) - A(H)| <
K/(K+1) < 1. Însă ştim că OPT(H) şi A(H) sunt numere naturale, deci am obţinut OPT(H) = A(H)!
61
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Asta înseamnă că dacă avem un algoritm aproximativ absolut pentru problema acoperirii, putem
imediat construi un algoritm exact la fel de rapid. Ori asta ar însemna că P=NP, ceea ce am presupus
fals.
Exemplele pe care le-am ales sunt în mod deliberat simple; teoria algoritmilor aproximativi este în
plină dezvoltare şi are rezultate foarte spectaculoase şi în general complicate. În orice caz,
aplicabilitatea ei este imediată, pentru că multe probleme practice care nu pot aştepta au numai
rezolvări aproximative.
O tehnică foarte spectaculoasă pentru rezolvarea problemelor este cea a folosiri numerelor
aleatoare. Practic algoritmii aleatori sunt identici cu cei obişnuiţi, dar folosesc în plus o nouă
instrucţiune, care s-ar putea chema ``dă cu banul''. Această instrucţiune generează un bit arbitrar ca
valoare.
Acest lucru este adevărat şi pentru alte clase de algoritmi; de pildă algoritmul quicksort are
pentru majoritatea vectorilor de intrare o comportare O(n log n). Dacă însă datele de intrare sunt prost
distribuite, atunci quicksort poate face n2 comparaţii. Pentru n=100 asta înseamnă de 10 ori mai mult!
Numărul de instanţe pentru care quicksort este slab este mult mai mic decît numărul de instanţe pentru
care merge bine. Ce te faci însă dacă într-un anumit context lui quicksort i se dau numai date rele?
(Datele preluate din măsurători reale sunt foarte rar complet uniform distribuite). O soluţie paradoxală
constă în a amesteca aleator vectorul înainte de a-l sorta.
Complexitatea medie (average case) a lui quicksort este O(n log n). Complexitatea în cazul cel
mai rău (worst case) este O(n 2). Dacă datele vin distribuite cu probabilitate mare în zona ``rea'', atunci
amestecîndu-le putem transforma instanţe care pică în zona ``worst-case'' în instanţe de tip ``average-
case''. Fireşte, asta nu înseamnă ca nu putem avea ghinion, şi ca amestecarea să producă tot o instanţă
``rea'', dar probabilitatea ca acest lucru să se întîmple este foarte mică, pentru că quicksort are puţine
instanţe rele5.
Acesta este un caz de folosire a aleatorului pentru a îmbunătăţi performanţa medie a unui algoritm.
Cîteodată cîştigul este şi mai mare, pentru că putem rezolva probleme NP-complete foarte rapid
folosind aleatorismul. De obicei avem însă un preţ de plătit. Cînd folosim algoritmi din clasa prezentată
mai jos, putem risca să nu primim răspunsul corect.
62
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Evoluţia unui algoritm care foloseşte numere aleatoare nu mai depinde numai de datele de intrare, ci şi
de numerele aleatoare pe care le generează. Dacă are ``noroc'' algoritmul poate termina repede şi bine;
dacă dă prost cu zarul, ar putea eventual chiar trage o concluzie greşită. (În cazul quicksort de mai sus
răspunsul este întotdeauna corect, dar cîteodată vine mai greu. Aceasta este diferenţa dintre algoritmii
Monte Carlo, mereu corecţi, şi cei Las Vegas, care pot uneori, rar, greşi.)
Vom defini acum algoritmii probabilişti pentru probleme de decizie (ţineţi minte, la care răspunsul este
Da sau Nu). Majoritatea problemelor pot fi exprimate în forma unor probleme de decizie, deci
simplificarea nu este prea drastică.
Există două clase de algoritmi probabilişti, dar ne vom concentra atenţia numai asupra uneia dintre ele,
pentru care vom da şi două exemple simple şi spectaculoase. Vom defini totodată clasa problemelor
care pot fi rezolvate probabilist în timp polinomial, numită RP (Random Polinomial).
Observaţi că dacă indicăm de la început care sunt numerele aleatoare care vor fi generate, evoluţia
algoritmului este perfect precizată.
Definiţie: O problemă de decizie este în RP dacă există un algoritm aleator A care rulează într-un timp
polinomial în lungimea instanţei (nc pentru un c oarecare), şi care are următoarele proprietăţi:
Dacă răspunsul la o instanţă I este ``Da'', atunci cu o probabilitate mai mare de 1/2 algoritmul va
răspunde ``Da''.
Dacă răspunsul la o instanţă I este ``Nu'', atunci cu probabilitate 1 algoritmul va răspunde ``Nu''.
De cine este dată ``probabilitatea'' de mai sus? De numărul de şiruri aleatoare. Cînd rulăm un
algoritm aleator pentru o instanţă I avem la dispoziţie 2 nc şiruri aleatoare de biţi; pentru unele dintre ele
algoritmul răspunde ``Da'', pentru celelalte răspunde ``Nu''. Ceea ce facem este să numărăm pentru cîte
şiruri algoritmul ar răspunde ``da'' şi să facem raportul cu 2nc. Aceasta este probabilitatea ca algoritmul
să răspundă ``da''. Opusul ei este probabilitatea să răspundă ``nu''.
O tehnică foarte simplă de amplificare poate creşte nedefinit această probabilitate: dacă
executăm algoritmul de 2 ori pe aceleaşi date de intrare, probabilitatea de a greşi pentru răspunsuri
``nu'' rămîne 0. Pe de altă parte, ajunge ca algoritmul să răspundă măcar odată ``da'' pentru a şti că
răspunsul este ``da'' cu siguranţă! Din cauza asta, dacă probabilitatea de eroare este p pentru algoritm,
executînd de k ori probabilitatea coboară la p k (nu uitaţi ca p este subunitar, ba chiar sub 1/2). Această
metodă se numeşte ``boost'' în engleză, şi face dintr-un algoritm probabilist slab ca discriminare o sculă
extrem de puternică!
Pentru a scădea probabilitatea de eroare a unui algoritm care poate greşi cu probabilitatea p
pînă sub o limită dorită siguranta, se procedează astfel:
Fie un polinom de mai multe variabile, x1, x2, ... xn. Acest polinom poate fi descris printr-o
formulă aritmetică, de pildă: (x1 + 1) (x2 + 1) ... (xn + 1). Întrebarea este: este acest polinom identic nul
sau nu?
63
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru polinomul de mai sus gradul este n, şi putem alege pentru K de exemplu Z p, unde p este
un număr prim relativ mare în raport cu n (de două ori mai mare ajunge!).
Alegînd arbitrar numerele v1, v2, ..., vn în Zp şi evaluînd q(v1, v2, ..., vn) mod p, putem imediat
afirma cu probabilitate mare > 1 - n/p despre q dacă este nul sau nu! Observaţi că evaluarea
polinomului nu este prea costisitoare, putîndu-se face în timp polinomial în lungimea expresiei care
descrie polinomul.
Folosind metoda de ``boost'' putem creşte rapid siguranţa noastră despre rezultatul algoritmului.
Izomorfismul arborilor
Se dau doi arbori, cu rădăcina precizată. Sunt aceşti doi arbori ``izomorfi'' (identici prin re-ordonarea
fiilor)? Această problemă este surprinzător de dificilă pentru un algoritm determinist (am impresia
chiar că este NP-completă). Iată însă o soluţie aproape imediată: construim pentru fiecare arbore cîte un
polinom care nu depinde de ordinea fiilor unui nod, în aşa fel încît dacă şi numai dacă arborii sunt
izomorfi polinoamele sunt egale. Apoi pur şi simplu testăm ca mai sus dacă polinomul diferenţă este
nul.
O metodă de a asocia recursiv un polinom unui arbore este de pildă următoarea: fiecărui nod îi
asociem o variabilă xk, unde k este înălţimea nodului (distanţa pînă la cea mai depărtată frunză).
Frunzele vor avea toate asociate variabila x 0. Apoi asociem nodului v de înălţime k cu fii v 1, ... vl
polinomul fv = (xk - fv1) (xk - fv2) ... (xk - fvl). Se arată uşor că polinoamele sunt egale pentru arbori
izomorfi, bazîndu-ne pe unicitatea descompunerii în factori a unui polinom. Gradul polinomului asociat
unui nod este egal cu suma gradelor fiilor, care la rîndul ei este egală cu numărul de frunze care se află
sub acel nod (cum se demonstrează imediat prin inducţie după înălţime). Şi asta-i tot!
Algoritmi on-line
Adesea trebuie luate decizii cu informaţii incomplete. Un caz particular este luarea de decizii
pe măsură ce datele devin disponibile. Deciziile afectează viitorul, dar sunt luate fără a avea cunoştinţe
despre datele viitoare. Sa vedem în acţiune un exemplu foarte simplu:
64
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Problema schiorului
Se pune problema: ce este mai bine: să închiriezi sau să cumperi schiuri? (Vom presupune că preţul
schiurilor este constant de-a lungul timpului, ca să simplificăm problema). Dilema constă din faptul că
în fiecare sezon, nu ştii dacă te vei mai duce odată. Dacă le cumperi şi nu te mai duci, ai dat banii
degeaba. Dacă le tot închiriezi şi te duci des, s-ar putea să le plăteşti de mai multe ori. Totuşi, trebuie să
iei o decizie. Pe care?
Există un răspuns foarte simplu, care promite nu că dă rezultatul cel mai ieftin în orice circumstanţă, ci
doar că nu vei cheltui de două ori mai mult decît în cazul în care ai face decizia perfectă (decizia
perfectă este cea care ştie precis dacă te vei mai duce, şi de cîte ori; ea nu este accesibilă decît ``post-
factum'', deci este pur teoretică).
Algoritmul este: închiriezi schiuri pînă ai dat pe chirie costul schiurilor. După aceea dacă mai vrei să
mergi le cumperi. Voi demonstra rapid că în felul ăsta orice s-ar întîmpla nu pierzi mai mult de jumate
din banii pe care i-ai fi cheltuit în cazul ideal.
Avem 3 posibilităţi:
1. Te opreşti înainte de a le cumpăra: în cazul ăsta ai jucat perfect, pentru că ai schiat şi nu puteai ieşi mai
ieftin nicicum;
2. Te opreşti imediat după ce le-ai cumpărat. În cazul ăsta ai dat de două ori preţul (odată pe închirieri, şi
odată pe cumpărare), dar ai schiat cît ai fi putut schia dînd numai odată preţul (mai ieftin de odată nu
puteai ieşi);
3. Te opreşti mai tîrziu: în cazul ăsta cel mai ieftin era tot să le cumperi din prima zi, deci iar ai cheltuit
dublu.
Orice altă schemă foloseşti pentru a decide cumpărarea, există un scenariu în care poţi cheltui mai mult
de dublu faţă de optim.
Algoritmii on-line apar foarte natural într-o mulţime de situaţii: de exemplu în reţele de calculatoare,
algoritmii care decid traseul unui pachet cu informaţii sunt algoritmi on-line; dacă decid trasee proaste,
reţeaua poate deveni supra-aglomerată în viitor; astfel de algoritmi nu au idee despre cererile viitoare,
aşa că acţionează cu informaţie incompletă.
Un alt exemplu este în sistemele de operare: algoritmii după care cache-urile (sau sistemele de
memorie virtuală) aleg paginile care trebuie înlocuite. Alegerea aceasta nu poate fi optimă în absenţa
informaţiilor despre viitoarele cereri. Cu toate acestea, anumite alegeri sunt mai bune decît altele.
Un al treilea exemplu, tot din contextul sistemelor de operare, este al algoritmilor de planificare, care
trebuie să stabilească în ce moment se execută fiecare proces pe un calculator (paralel). Acolo unde
minutul de rulare costă o grămadă de bani, deciziile trebuie să risipească cît mai puţin timp. Însă job-uri
pentru prelucrare sosesc dinamic, aşa că algoritmii trebuie să facă faţă unui mediu în continuă
schimbare.
Algoritmii on-line sunt în general analizaţi comparîndu-i cu algoritmii off-line, care ar avea înainte de a
face deciziile informaţii perfecte despre toate cererile viitoare. Este clar că informaţia aceasta este un
mare avantaj, aşa că în general algoritmii on-line au performanţe mult mai proaste decît cei
corespunzători off-line.
Cercetările în acest domeniu sunt doar la început; se explorează şi variante de algoritmi hibrizi on/off-line, în care
algoritmul are o idee despre viitor, dar nu neapărat o vedere completă.
65
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
s := s + n MOD 10
n := n DIV 10
START
REPEAT
WRITE s;
STOP. Cit. s
S := 0
DA NU
Tip. S
S := S + n MOD 10
STOP
N := N DIV 10
Cit. n
66
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
În problema anterioară am văzut cum putem izola cifrele unui număr. De menţionat că algoritmul
propus anterior izola cifrele numărului n în ordine inversă.
Exemplu: pentru numărul 162 se izolau pe rând cifrele 2, 6, şi 1. Pe de altă parte, dacă cunoaştem cifrele
unui număr putem calcula numărul respectiv.
Exemplu: din cifrele 2, 6 şi 1 putem obţine numărul 261. Aici nu este vorba de alăturarea cifrelor, cum
am fi tentaţi să credem, ci de calculul numărului sub forma:
2 * 102 + 6 * 101 + 1 * 100,
aşa cum cunoaştem din teoria bazelor de numeraţie. Cum procedăm pentru rezolvarea acestei probleme?
Considerăm o variabilă (notată ninv., care iniţial va avea valoarea 0). Pentru fiecare cifră noua valoare a lui niv va
fi vechea valoare înmulţită cu 10 la care se va adăuga cifra:
niv : = 0 * 10 + 2;
niv : = 2 * 10 + 6;
niv : = 26 * 10 + 1 = 261.
În concluzie, izolăm pe rând cifrele în ordine inversă (aşa cum am arătat în problema anterioară) şi cu
fiecare nouă cifră construim numărul cerut.
În pseudocod, algoritmul arată astfel:
Integer n, ninv;
READ n
ninv := 0;
WHILE n < > 0
ninv := ninv * 10 + n MOD 10;
n .= n DIV 10
REPEAT
WRITE ninv
STOP.
START
Cit. N
NINV := 0
NU
N0 Tip. NINV
DA
STOP
NINV := NINV * 10 + N MOD 10
67
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
i := 2
WHILE (i < n) AND (n MOD i < > 0)
i := i +1
REPEAT
IF i := n THEN WRITE ’numarul este prim’
ELSE WRITE ’numarul nu este prim’
ENDIF
STOP.
READ nr
N := 1
J := 0;
DO
prim := true
FOR i := 2,
IF n MOD i = 0 THEN prim := false
ENDIF
REPEAT
IF prim THEN
WRITE n
j := j + 1
ENDIF
n := n + 1
UNTIL j = nr
STOP.
68
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
- se împarte n la I;
dacă fm este diferit de 0 (deci s-a găsit divizor al lui n) se tipăresc I şi fm;
se adun 1 la i (se incrementează).
Să presupunem că am citit n = 12. Algoritmul decurge astfel:
se iniţializează I cu 2;
se iniţializează fm cu 0;
întrucât 2 divide pe 12, fm va lua valoarea 1 iar n valoarea 6;
întrucât 2 divide pe 6, fm va lua valoarea 2 şi n valoarea 3;
n nu divide pe 3, deci se trece mai departe;
fm este diferit de 0, se tipăreşte 2 la puterea 2;
se măreşte i cu 1;
n nu este 1, deci secvenţa se reia;
fm va lua valoarea 0;
3 divide pe 3 (i divide pe n) deci fm va lua valoarea 1 şi n va deveni 1;
3 nu divide 1, deci se trece mai departe;
fm este diferit de 0, deci se tiopăreşte 3 la pueterea 1;
i devine 4;
n este 1 şi algoritmul se încheie.
În continuare se prezintă schema logică şi algoritmul realizat în pseudocod:
INTEGER n, i, fm;
READ n
i := 2;
DO
fm := 0;
WHILE n MOD i = 0
fm := fm + 1;
n := n DIV i
REPEAT
IF fm < > 0 THEN
WRITE I, ’la puterea’ fm
ENDIF
i := i + 1
UNTIL n = 1
STOP.
69
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Pentru calculul acestor valori se utilizează se utilizează variabila p. din cele arătate rezultă
schema logică de mai jos:
START
Cit. n
S := 0
P := 1
i := 1
P := p * i
S := s + p
i := i + 1
DA NU
I<N Tip. S STOP
INTEGER n, i, s, p;
READ n
s := 0
p := 1
FOR i := 1, n
p := * i
s := s + p
REPEAT
WRITE s
STOP.
2) Se consideră şirul de numere naturale:
1, 4, 7, 10, 13, . . .
Să se calculeze suma primelor n termeni, cu n dat de la tastatură
70
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Program Problema_1;
Tipuri de constante
-intregi – numere intregi pozitive care nu pot -intregi – numere intregi pozitive cu valori
depasi valoarea 32767, valoare identificata de intre 0 si 4.294.967.295 si care sunt de trei
compilator sub numele de MAXINT;valorile tipuri:
intregi pot fi numere: -zecimale (baza 10);
-zecimale (baza 10); Exemple:43,152,7564.
Exemple:43,187,2001. -octale (baza 8),care sunt precedate de un
-hexazecimale (baza 16),care sunt zero nesemnificativ;
precedate de caracterul special $ Exemplu:0354→345(8)
Exemplu:$2F4 sau $2F4→ 2F4(16). -hexazecimale (baza 16),care sunt
-reale – numere reale cu valori absolute precedate de Ox sau OX.
cuprinse intre 5.9×10(la puterea -39) si 3.4×10(la Exemplu:0×2F4 sau 0X2F4 sau
puterea 38);atat partea intreaga,cat si cea 0×2f4-→2F4(16).
zecimala trebuie sa contina cel putin o -reale – orice valoare reala
cifra,chiar daca aceasta este 0. Exemple:32.45,0.5.
-caracter – orice caracter scris intre apostrofuri. -caracter- orice caracter scris intre
71
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Exemplu:’A’ apostrofuri.
-siruri de caractere – o succesiune de Exemplu:’A’
caractere,delimitata tot prin apostrofuri. -siruri de caractere – o succesiune de
Exemple:true/false,MAXINT. caractere,delimitata tot prin ghilimele.
-constante definite prin cuvinte-cheie
Exemplu:NULL
72
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Functii matematice
LIMBAJUL PASCAL LIMBAJUL C/C++
73
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
EXEMPLU:
LIMBAJUL PASCAL LIMBAJUL C/C++
var a,b,selector:integer; #include<iostream.h>
begin void main()
write(’a=’);readln(a);write(’b=’);readln(b); {int a,b,selector;
writeln(’Tastati una din cifre’); cout<<’’a=’’;cin>>a;cout<<’’b=’’;cin>>b;
writeln(’1-suma/2-diferenta/3-produs/4-cat’); cout<<’’Tastati una dintre cifre’’<<end1;
write(’selector=’);readln(selector); cout<<’’1-suma/2-diferenta/3-produs/4-cat’’;
case selector of cout<<’’selector=’’;cin>>selector;
1:write(’suma = ’,a+b); switch(selector)
2:write(’diferenta = ’,a-b); {case 1:cout<<’’suma=’’<<a+b;break;
3:write(’produsul = ’,a*b); case2:cout<<’’produsul=’’<<a*b;break;
4:write(’catul impartirii intregi=’,a div b); case3:cout<<’’diferenta=’’<<a-b;break;
else write(’Ati tastat o optiune inexistenta’); case4:cout<<’’catul=’’<<a/b;break;
end; default:cout<<’’Ati tastat o optiune inexistenta’’;
end. }}
74
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
repeat do
S; {S;
until (cond_logica); }while(cond_logica);
Secventa (S) se executa pana cand conditia Secventa (S) se executa cat timp conditia logica
logica este adevarata (expresia genereaza este adevarata (expresia genereaza o valoare
valoarea logica true). nenula).
Secventa se executa cel putin o data,chiar Secventa se executa cel putin o data,chiar deca
daca conditia logica este indeplinita conditia logica nu este indeplinita.
(adevarata).
75
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Compararea valorilor.Profesorul diriginte doreste sa afle cea mai mare medie a clasei
76
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Subprograme
Noţiunea de subprogram
Prin subprogram vom înţelege un ansamblu alcătuit din tipuri de date, variabile şi
instrucţiunii scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat
(rulat) doar dacă este apelat de un program sau de alt subprogram.
■ de prelucrare a şirurilor de caractere:in Pascal avem pos,length …,iar in C++ strlen, strcpy, strncat.
77
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
În acest capitol învăţăm să le creăm. Pentru a înţelege noţiunea de subprogram, vom porni de
la două exemple:
□ Se citeşte n, număr natural. Să se scrie programele care tipăresc valoarea calculată a expresiilor:
E1=1+1/2+1/3+1/4+…+1/n
E2=(1+1/2+1/3+1/4+…+1/n)ⁿ
E₂=E₁ⁿ
Cerinţa este de a scrie programe separate. Cum procedăm? Prin utilizarea cunoştinţelor
dobândite până în prezent, scriem cele două programe separat, iar în al doilea program, secvenţa care
calculează prima expresie, se copiază din primul.
Oare nu se poate lucra mai eficient? Răspunsul este afirmativ. Se scrie un program care
calculează E₁ şi care este apelat de ambele programe. Primul program va tipări valoarea transmisă de
subprogram, al doilea va ridica la putere această valoare şi va afişa rezultatul.
Desigur, ştim să rezolvăm această problemă şi clasic, în mai multe feluri, pentru că am studiat
mai mulţi algoritmi de sortare. De această dată vom rezolva problema prin utilizarea subprogramelor.
Vom scrie un subprogram care citeşte un vector, unul care tipăreşte un vector şi un al treilea
care sortează vectorul, după una din metodele cunoscute.
Faţă de scrierea clasică, aici problema a fost descompusă în altele mai mici (citire, sortare,
tipărire). În general, o problemă complexă se rezolvă mai uşor dacă o descompunem în altele mai
simple. Apoi, şansele de a greşi la scrierea unui subprogram sunt cu mult mai mici decât acelea de a
greşi la scrierea unui program mare. Acesta din urmă rezultă din “asamblarea” subprogramelor la care
se adaugă, eventual, câteva linii scrise în programul principal. Putem acum enumera avantajele
utilizării subprogramelor:
■ reutilizarea codului –o dată scris, un subprogram poate fi utilizat de mai multe programe;
■ elaborarea algoritmilor prin descompunerea problemei în altele mai simple. În acest fel, rezolvăm cu
mult mai uşor problema;
■ depistarea cu uşurinţă a erorilor –verificăm la început subprogramele, apoi modul în care le-am
asamblat (le-am apelat din cadrul programului).
Parametrii care se găsesc în antetul funcţiei se numesc parametrii formali.
Atunci când scriem o funcţie nu cunoaştem valoarea propriu-zisă a parametrilor. Funcţia trebuie să
întoarcă rezultatul corect, oricare ar fi valoarea lor. Din acest punct de vedere ei se numesc formali.
78
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
La apel, lucrurile stau altfel: valorile acestora sunt cunoscute. Prin urmare aceştia se cunosc
parametrii efectivi.
În esenţă, o funcţie este alcătuită din:
Antet – acesta conţine mai multe informaţii importante necesare compilatorului, numele funcţiei,
lista parametrilor formali, tipul rezultatului.
O funcţie poate fi apelată de sine stătător (prin nume şi lista parametrilor efectivi), dar poate fi inclusă şi în cadrul
expresiilor, caz în care, la evaluarea expresiei este apelată.
Sistemul de operare alocă fiecărui program trei zone distincte în memoria internă în care se găsesc
memorate variabilele programului.
Segment de date
Segment de stivă
Heap
1. Clasa de memorare.
2. Vizibilitate.
3. Durata de viaţă.
4. Tipul variabilei, singurul pe care l-am studiat până în prezent.
1. Clasa de memorare – precizează locul unde este memorată variabila respectivă. O variabilă poate
fi memorată în segmentul de date, în cel de stivă, în heap sau într-un registru al microprocesorului.
2. Vizibilitatea – precizează liniile textului sursă din care variabila respectivă poate fi accesată. Astfel
avem:
b. Vizibilitatea la nivel de fişier – în cazul în care programul ocupă un singur fişier sursă,
singurul caz pe care îl tratăm acum.
3. Durata de viaţă – reprezintă timpul în care variabila respectivă are alocat spaţiu în memoria
internă. Astfel avem:
a. Durata statică – variabila are alocat spaţiu în tot timpul execuţiei programului.
b. Durata locală - variabila are alocat spaţiu în timpul în care se execută instrucţiunile
blocului respectiv.
Variabile globale
Acestea se declară în afara corpului oricărei funcţii
79
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
2. Vizibilitatea – În cazul în care declaraţiile acestora sunt înaintea tuturor funcţiilor, acestea sunt
vizibile la nivelul întregului program (fişier). Dacă anumite funcţii se află plasate înaintea
declaraţiilor acestor variabile, atunci ele sunt vizibile doar pentru funcţiile care sunt plasate după
aceste declaraţii.
3. Durata de viaţă a variabilelor globale este statică. Ele au spaţiu rezervat în tot timpul execuţiei
programului.
Variabile locale
Acestea sunt declarate în corpul funcţiilor. Mai precis, pot fi declarate în orice bloc (instrucţiune
compusă) al acestora
1. Clasa de memorare a variabilelor locale este, implicit, segmentul de stivă. Există posibilitatea ca
acestea să fie alocate în registrele microprocesorului, caz în care declaraţia lor trebuie precedată de
cuvântul cheie register.
1. Variabilele locale nu sunt iniţializate implicit cu 0. În ipoteza în care acestea nu sunt iniţializate
explicit de programator, reţin o valoare oarecare, numită valoare reziduală.
Transmiterea parametrilor
Aşa cum am arătat, parametrii care se găsesc în antetul funcţiei se numesc parametrii formali,
iar cei care se găsesc în instrucţiunea de apel se numesc parametrii efectivi.
După fiecare apel al funcţiei se tipăreşte suma obţinută. Între parametrii formali şi cei efectivi trebuie
să existe o anumită concordanţă, care este descrisă prin regulile următoare:
Numărul parametrilor formali trebuie să coincidă cu numărul parametrilor efectivi. La această regulă
există o excepţie care va fi prezentată într-un paragraf separat.
Tipul parametrilor formali trebuie să coincidă cu tipul parametrilor efectivi sau tipul parametrilor efectivi
să poată fi convertit implicit către tipul parametrilor formali la fel ca în cazul atribuirii
Observaţie: Nu este obligatoriu ca numele parametrilor formali să coincidă cu numele parametrilor
efectivi.
Vom analiza modul în care sunt memoraţi parametrii transmişi, în momentul lansării în
execuţie a funcţiei.
Memorarea parametrilor transmişi se face în ordinea în care aceştia figurează în antet: de la stânga
la dreapta.
În cadrul subprogramului, parametrii transmişi şi memoraţi în stivă sunt variabile. Numele lor este
cel din lista parametrilor formali.
80
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Există două mecanisme de transmitere a parametrilor, transmiterea prin valoare şi transmiterea prin
referinţă. Acestea vor fi tratate în continuare:
A. Transmiterea prin valoare se utilizează atunci când suntem interesaţi ca subprogramul să lucreze
cu acea valoare, dar, în prelucrare, nu ne interesează ca parametrul efectiv (cel din blocul apelant)
să reţină valoarea modificată în subprogram.
1. Valorile reţinute de variabile. În acest caz, parametrii efectivi trebuie să fie numele
variabilelor.
2. Parametrii efectivi sunt expresii, care mai întâi se evaluează.
Aşa cum am arătat, transmiterea parametrilor prin valoare se utilizează atunci când nu ne
interesează ca, la întoarcerea din subprogram, parametrul efectiv să reţină valoarea modificată
acolo. Întrebare: dacă n-ar exista decât transmiterea prin valoare, ar fi posibil să modificăm
valoarea anumitor variabile care sunt declarate în blocul aparent?
În cazul transmiterii prin referinţă, parametrii efectivi trebuie să fie referinţe la variabile (vezi
tipul referinţă prezentat în capitolul anterior).
În acest caz ne putem întreba care este mecanismul prin care, deşi pentru o variabilă transmisă se
reţine adresa ei, în subprogram putem adresa variabila normal (nu indirect)? La compilare, orice
referinţă la variabila respectivă, este “tradusă” ca adresare indirectă.
Programul următor utilizează o funcţie care interschimbă valorile reţinute de două variabile.
Acestea sunt transmise prin referinţă.
Definirea şi declararea unui subprogram
Deşi aparent asemănătoare, cele două noţiuni diferă. Buna înţelegere a lor ne ajută să evităm
anumite erori. Mai mult, aceste noţiuni sunt utilizate de orice limbaj de programare.
□ A defini un subprogram, înseamnă a-l scrie efectiv, după structura anterior prezentată. O problemă
importantă este locul unde se defineşte subprogramul.
FUNCTII
LIMBAJUL PASCAL LIMBAJUL C/C++
declaratiile
FUNCTION tip_returnat_de_functie
nume_functie(parametrii:tip):tip_returnat_de_functie; nume_functie(tip parametrii)
Var variabile_locale:tip; {
Begin tip variabile_locale;
exemplu
81
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
}
Exemplu
LIMBAJUL PASCAL LIMBAJUL C/C++
declaratiile
Var s, i,n:integer; #Include<iostream.h>
procedure ss(n:integer;var s:integer); int s=0,i,n;
Begin void ss(int n, int& s)
S:=0; {
For i:=1 to n do for (i=0;i<n;i++)
S:=s+i; s=s+i;
End; }
Begin void main()
Readln(n); {
ss(n,s); cin>>n;
Write(s); ss(n,s);
End. cout<<s;
}
RECURSIVITATE
Introducere in recursivitate
Prezentare generala
Recursivitatea este una din notiunile fundamentale ale informaticii. Utilizarea frecventa a recursivitatii
s-a facut dupa anii 80.Multe din limbajele de programare evaluate si mai mult utilizate -Fortran, Cobol-
nu permiteau scrierea programelor recursive.
Recursivitatea a aparut din necesitati practice date de transcrierea directa a formulelor matematice
recursive.In timp. Acest mecanism a fost extins, fiind utilizat in elaborarea multor algoritmi.
82
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Mecanismul recursivitatii
A) Pentru a scrie o functie recursiva care efectueaza acelasi calcul, vom porni de la o
definitie recursiva a lui n !. Aceasta este :
n !=fact(n)= 1, n=0
n€N
n * fact(n-1), astfel
Care este mecanismul prin care subprogramele se pot autoapela? Sa ne amintim modul in care
subprogramele memoreaza parametrii transmisi:
● Pentru memorarea parametrilor, subprogramele folosesc o zona de memorie numita stiva (mai
exact, aceasta zona se numeste segment de stiva).
● Pentru parametrii transmisi prin valoare, se memoreaza valoarea transmisa, iar pentru cei
transmisi prin referinta se memoreaza adresa variabilei.
● In cadrul subprogramului, parametrii transmisi si memorati in stiva sunt variabile.Numele lor este
cel di lista parametrilor formali.
In capitolul anterior am studiat proprietatile structurii numita stiva. Exact aceleasi proprietati le are si
segmental de stiva.Singura diferenta este data de faptul ca gestiunea segmentului de stiva este facuta
automat de catre calculator.Mai exact, codul in limbaj masina, obtinut in urma compilarii, contine
secvente prin care se gestioneaza segmentul de stiva.
● In cazul in care subprogramul se autoapeleaza pe un al doilea nivel se depun din nou parametrii
transmisi si se rezerva un nou spatiu pentru variabilele locale.
In continuare prezentam grafic modul in care functioneaza recursivitatea in cazul functiei fact a
programului anterior. Aceasta functie nu are variabile locale, deci in stiva se depune doar parametrul
n.
83
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
n→2
n→3 Functia se autoapeleaza. De aceasta data parametrul n ia valoarea 2
.In stiva se creeaza un nou nivel, care retine n cu valoarea 2.
Var n:integer;
Procedure fact( val:integer;var prod:integer); #include <iostream.h >
Begin void fact(int val, int n,int& prod)
If (val<=n) then { if (val<=n)
Begin { prod*=val;
Prod=prod*val; fact(val+1,n,prod);
fact(val+1,n,prod); }
} }
begin main( )
readln(n); { int val,n,p=1;
p=1; cout<<”n=”; cin>>n;
fact(1,n,p); fact(1,n,p) ;
write(p); cout<<p ;
84
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end. }
1 3 Referinta catre
p
1
p val n prod
Pentru ca val este mai mic sau egal ca n se efectueaza : prod :=prod*val ;Intrucat
variabila p a fost transmisa prin referinta, programul lucreaza cu aceasta variabila, in
loc de prod.In concluzie, se efectueaza p :=p*val ;.Apoi, functia se autoapeleaza :
2 3 Referinta catre p
1 1 3 Referinta catre p
p 3 3 Referinta catre p
val n prod 2 3 Referinta catre p
1 3 Referinta catre p
2
p val n prod
Pentru ca val este 3 –mai mic sau egal cu 3 – se efectueaza prod :=prod*val, deci p
ia valoarea 6, dupa care se revine pe nivelul 2, apoi 1, apoi in programul principal.
Observatii :
▫Dupa cum rezulta din aceste exemple, subprogramul lucreaza cu datele aflate pe un
anumit nivel al stivei pentru variabilele transmise prin valoare si variabilele locale
ale sale, dar si cu variabilele functiei main( ) , daca acesteav sunt transmise prin
referinta.
85
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
▫In cazul unui numar mare de autoapelari , exista posibilitatea ca segmentul de stiva
sa se ocupe total, in caz in care programul se va termina cu eroare.
▫Recursivitatea presupune mai multa memorie(ma refer la stiva), aceasta este oricum
rezervata.
1.Wirth.O camera de luat vederi are in obiectiv un televizor care transmite imaginile
primite de la camera.Evident, in televizor se va vedea un televizor, iar in acesta
un televizor...s.a.m.d
Pe scurt :
▪ in orice televizor, se vede un televizor.
3.Constatare. Intr-o tara cu nivel de trai scazut, orice partid care ajunge la putere
afirma:de vina nu suntem noi, sunt cei de la care am preluat puterea!.
4.Logica. Orice militar aflat in ciclu 2 de instruire afirma :cand eram in ciclu 1, cei
din ciclu 2 ‘m-au chinuit inutil’.Asa fac si eu cu cei din ciclu 1.
86
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Observatii
▪Pentru orice algoritm recursiv exista unul iterativ care rezolva aceeasi problema.
87
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end. cin>>n;
citire(a,1);
tipar (a,1);
maxi=max(a,n);
cout<<a[maxi];
}
Recursiv indirect sa se calculeze sirurile date prin:a0:=a;b0=b;
an:=(A[n-1]+B[n-2])/2
si bn:=sqrt(a[n-1]*b[n-1])
LIMBAJUL PASCAL LIMBAJUL C/C++
sursele
var n,a0,b0:word; #include <iostream.h>
function a(n:word):real;forward; #include <math.h>
function b(n:word):real; double a,b;
begin int n;
if n=0 then b:=b0
else double bn (int n);
b:=sqrt(a(n-1)*b(n-1)); double an (int n);
end; { if (!n) return a;
function a; else return (an(n-1)+bn(n-1))/2;
begin }
if n=0 then a:=a0
else double bn (int n)
a:=(a(n-1)+b(n-1))/2; { if (!n) return b;
end; else return sqrt(an(n-1)*bn(n-
begin 1));
writeln('valoarea initiala a sirului a ');readln(a0); }
writeln('valoarea initiala a sirului b ');readln(b0);
write('rangul sirurilor ');readln(n); main( )
writeln('b= ',b(n):6:2,' a= ',a(n):6:3); { cout<<”a=”;cin>>a;
readln; cout<<”b=”;cin>>b;
end. cout<<”n=”;cin>>n;
cout<<an(n)<<’ ‘<<bn(n) ;
}
DIVIDE ET IMPERA
o Se citeste un vector cu n componente,numere naturale.Se cere sa se
tipareasca valoarea maxima.
Problema de mai sus este binecunoscuta.Cum o rezolvam utilizand metoda divide et
impera?
Trebuie tiparita valoarea maxima dintre numerele retinute in vector de la i la j(initial
i=1,j=n).Pt acesta procedam astfel:
Daca i=j,valoarea amxima va fi v[i];
Contrar vom imparti vectorul in doi vectori(primul vector va contine
componentele de la i la (i+j) div 2,al doilea va contine componentele de la
(i+j)div 2+1 la j),rezolvam subproblemele(aflam maximul pentru fiecare
dintre ele) iar solutia problemei va fi data de valoarea maxima dintre
rezultatele celor doua subprobleme.
88
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Conform strategiei generale Divide et impera,problema este descompusa in alte doua subprobleme de
acelasi tip si,dupa rezolvarea lor,rezultatele se combina(in particular se interclaseaza).Descompunerea
unui vector in alti doi vectori care urmeaza a fi sortati are loc pana cand avem de sortat vetori de una
sau doua componente.
In aplicatie,functia sort sorteaza un vector cu maximum doua elemente;interc interclaseaza
rezultatele ;divimp implementeaza strategia generala a metodei studiate
89
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
b[k]:=a[i]; b[k]=a[j];
i:=i+1; j=j+1;
k:=k+1; k=k+1;
end }
else if (i<=m)
begin for (j=i;j<=m;j++)
b[k]:=a[j]; {
j:=j+1; b[k]=a[j];
k:=k+1; k=k+1;
end; }
if i<=m then else
for j:=i to m do for (i=j;j<=q;j++)
begin {
b[k]:=a[j]; b[k]=a[i];
k:=k+1; k=k+1;
end }
else k=1;
for i:=j to xxx2 do for (i=p;i<=q;i++)
begin {
b[k]:=a[i]; a[i]=b[k];
k:=k+1; k=k+1;
end; }
k:=1; }
for i:=xxx1 to xxx2 do void divimp (int p,int q,int a[10])
begin {
a[i]:=b[k]; int m;
k:=k+1; if ((q-p)<=1) sort(p,q,a);
end;end;
else
procedure divimp(xxx1,xxx2:integer;var
{ m=(p+q)/2;
a:vector);
divimp(p,m,a);
var m:integer;
divimp(m+1,q,a);
begin
interc(p,q,m,a);
if (xxx2-xxx1)<=1 then
}
sort(xxx1,xxx2,a)
}
else
main( )
begin
{ int i;
m:=(xxx1+xxx2) div 2;
divimp(xxx1,m,a); cout<<”n=”;cin>>n;
divimp(m+1,xxx2,a); for (i=1;i<=n;i++)
interclasare(xxx1,xxx2,m,a); {
end;end; cout<<”a[“<<i<<”]=”;cin>>a[i];}
begin divimp(1,n,a);
writeln('n=');readln(n); for (i=1;i<=n;i++)
for i:=1 to n do cout<<a[i]<<” “;
begin }
writeln('a[',i,']=');
readln(a[i]);
end;
divimp(1,n,a);
for i:=1 to n do
write(a[i]);
readln;
end.
Pentru rezolvare este necesara o functie poz care trateaza o portiune din vector
cuprinsa intre indicii dati de li (limita inferioara) si ls(limita superioara).Rolul acestei
functii este de a pozitiona prima componenta a[li] pe o pozitie k cuprinsa intre li si
90
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
ls,astfel incat toate componentele vectorului cuprinse intre li si k-1 sa fie mai mici sau
egale decat a[k] si toate componentele vectorului cuprinse intre k+1 si ls sa fie mai
mari sau egale decat a[k].
In aceasta functie exista doua moduri de lucru:
a) i ramane constant,j scade cu 1;
b) i creste cu 1,j ramane constant.
Functia este conceputa astfel:
initial,i va lua valoarea li,iar j va lua valoarea ls (elemental care initial
se afla pe pozitia li se va gasi mereu pe o pozitie data de i sau de j);
se trece in modul de lucru a);
atata timp cat i<j,se executa:
-daca a[i] este strict mai amre decat a[j],atunci se inverseaza cele doua
numere si se schimba modul de lucru;
-i si j se modifica corespunzator modului de lucru in care se afla
programul;
-k ia vlaoraea comuna a lui i si j.
Dupa aplicarea functiei poz,este evident ca elementul care se afla initial
in pozitia li va ajunge pe o pozitie k si va ramane pe acea pozitie in
cadrul vectorului deja sortat,fapt care reprezinta esenta algoritmului.
Functoa quick are parametrii li si ls(limita inferioara si limita superioara).In cadrul ei
se utilizeaza metoda Divide et impera,dupa cum urmeaza:
-se apeleaza poz;
-se apeleaza quick pentru li si k-1;
-se apeleaza quick pentru k+1 si ls.
91
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
var st,dr:indice;x:tipelement; }
begin
st:=p;dr:=q;x:=a[p]; main( )
while st<dr do { int I;
begin cout<<”n=”;cin>>n;
while (st<dr) and (a[dr]>=x) do dec(dr); for (i=1;i<=n;i++)
a[st]:=a[dr];
while (st<dr) and (a[dr]>=x) do dec(dr); { cout<<”a[“<<i<<”]=”;cin>>a[i];}
quick(1,n);
a[st]:=a[dr]; for (i=1;i<=n;i++) cout <<a[i]<<endl;
while (st<dr) and (a[st]<x) do inc(st);
a[dr]:=a[st];
}
end;
a[st]:=x;divide:=st;
end;
procedure rapida(p,q:indice);
var m:indice;
begin
m:=divide(p,q);
if m-1>p then rapida(p,m-1);
if m+1 <q then rapida(m+1,q);
end;
begin
citire;
rapida(1,n);
afisare;
readln;
end.
92
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
readln(a[i]); }
end;end;
procedure afisare;
var i:indice;
begin
writeln('vectorul sortat este');
for i:=1 to n do
write(a[i]);writeln;readln;
end;
procedure caut(i,j:integer);
begin
if nr=a[(i+j) div 2 ]
then writeln('l-am gasi la pozitia ',(i+j) div 2)
else
if i<j then
if nr<a[(i+j) div 2 ]
then caut (i,(i+j) div 2-1)
else caut ((i+j) div 2+1,j)
end;
begin
citire;
write('pe cine cautai ');
readln(nr);
caut(1,n);
readln;
end.
o Turnurile din Hanoi.Se dau 3 tije simbolizate prin a,b,c.Pe tija a se gasesc discuri de
diameter diferite,asezate in orine descrescatoare a diametrelor private de jos in sus.Se
cere sa se mute discurile de pe tija a pe tija b,utilizand ca tija intermediara tija
c,respectand urmatoarele reguli:
La fiecare pas se muta un singur disc;
Nu este permis sa se aseze un disc cu diametrul mai mare peste un disc cu diametrul mai mic.
Rezolvare:
Daca n=1 se face mutarea ab,adica se muta discul de pe tija a pe tija b.
Daca n=2 se fac mutarile ac,ab,cb.
In cazul in care n>2 problema se complica.Notam cu H(n,a,b,c) sirul mutarilor celor n discuri de pe tija a
pe tija b,utilizand ca tija intermediara,toja c.
Conform strategiei Divede et impera incercam sa descompunem problema in alte doua subprobleme
de acelasi tip,urmand apoi combinarea solutiilor.In acest sens,observam ca mutarea celor n discuri de
pe tija a pe tija b,utilizand ca tija intermediara tija c,este echivalenta cu:
Mutarea a n-1 discuri de pe tija a pe tija c,utilizand ca tija intermediara tija b;
Mutarea discului ramas pe tija b;
Mutarea a n-1 discuri de pe tija c pe tija b,utilizand ca tija intermediara tija a.
a b, daca n=1
H(n,a,b,c)=
H(n-1,a,c,b),ab,H(n-1,c,b,a), daca n>1
Pentru n=2 avem: H(2,a,b,c)=H(1,a,c,b),ab,H(1,c,b,a)=ac,ab,cb.
Pentru n=3 avem:
H(3,a,b,c)=H(2,a,c,b),ab,H(2,c,b,a)=H(1,a,b,c),ac,H(1,b,c,a),ab,H(1,c,a,b),cb,H(1,a,b,
c)=ab,ac,bc,ab,ca,cb,ab.
93
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin int n;
if n=1 then
writeln(a,' --se pune pe--> ',b) void han(int n,char a,char b,char c)
else {
begin if (n==1) cout<<a<<b<<endl;
discurile(n-1,a,c,b); else
writeln(a,'-----se pune pe---> ',b); {
discurile(n-1,c,b,a); han(n-1,a,c,b);
end; cout<<a<<b<<endl;
end; han(n-1,c,b,a);
begin }
write('n=');readln(n); }
a:='mic';b:='mijlociu';c:='mare'; mian ( )
discurile(n,a,b,c); {
readln; cout<<”N=”;cin>>n;
end. a=’a’;b=’b’;c=’c’;
han(n,a,b,c);
}
Mentionam ca dreptunghiul de arie maxima fara gauri este retinut prin aceiasi
parametric ca si dreptunghiul cu gauri,in zonele XF,YF,LF,HF
94
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
2) xv,yv(i),1+x-xv(i),h.
In urma unei taieturi pe orizontala se obtin cele doua dreptunghiuri:
1) x,y,1,yv(i)-y;
2) x(i),yv(i),1,h+y-yv(i).
LIMBAJUL PASCAL LIMBAJUL C/C++
TABLA DREPTUNGHIULARA
TABLA #include <iostream.h>
{SE DAU COORDONATELE COLTURILOR UNEI TABLE int 1,h,I,n,xf,yf,lf,hf,xv[10],yv[10];
DREPTUNGHIULARE SI N GAURI IN EA
Stiind ca se permit numai taieturi orizontale si verticale sa se void dimp(int x,int y,int l,int h,int&
decupeze xf,int&yf,int& lf,int& hf,int xv[10],int yv[10])
o bucata de arie maxima} { int gasit=0,i=1;
type vector=array[1..100] of integer; while (i<=n && !gasit)
var x,y:vector; if (xv[i]>x && xv[i]<l && yv[i]>y &&
n:integer; yv[i]<y+h)
function max(i,j:integer):integer; gasit=1;
begin else i++;
if i<j then max:=j if (gasit)
else { dimp(x,y,xv[i]-x,h,xf,yf,lf,hf,xv,yv);
max:=i; dimp(xv[i],y,l+x-xv[i],h,xf,yf,lf,hf,xv,yv);
end; dimp(x,y,l,yv[i]-y,xf,yf,lf,hf,xv,yv);
function arie(x1,y1,x2,y2:integer):integer; dimp(x,yv[i],l,h+y-yv[i],xf,yf,lf,hf,xv,yv);
var i:integer;nusereducelaunpunct:boolean; }
begin else
i:=1;nusereducelaunpunct:=false; if (l*h>lf*hf)
repeat { xf=x;yf=y;
nusereducelaunpunct:=(x1<x[i]) and(x[i]<x2) and(y1<y[i]) and lf=l;hf=h;
(y[i]<y2);i:=i+1; }
until nusereducelaunpunct or(i=n+1); }
i:=i-1; main ( )
if not nusereducelaunpunct then { cout<<”n=”;cin>>n;
arie:=(x2-x1)*(y2-y1) for(int i=1;i<=n;i++)
else { cout<<”x[“<<i<<”]=”;cin>>xv[i];
arie:=max( max(arie(x1,y1,x[i],y2),arie(x[i],y1,x2,y2)),max(arie(x1,y1,x cout<<”y[“<<i<<”]=”;cin>>yv[i];
2,y[i]),arie(x1,y[i],x2,y2))); }
end; cout<<”l=”;cin>>l;cout<<”h=”;cin>>h;
begin dimp(0,0,l,h,xf,yf,lf,hf,xv,yv);
n:=6; cout<<”x=”<<xf<<”y=”<<yf<<”l=”<<”h=”<<hf
x[1]:=5;x[2]:=7;x[3]:=10;x[4]:=12;x[5]:=13;x[6]:=17; ;
y[1]:=3;y[2]:=4;y[3]:=5;y[4]:=13;y[5]:=16;y[6]:=22; }
writeln(arie(0,0,20,20));readln;
end.
BACKTRACKING
Aspecte teoretice
Aceasta tehnica se foloseste in reezolvarea problemelor care indeplinesc simultan urmatoarele conditii:
solutia lor poate fi pusa sub forma unui vector S=x1,x2,..,xn,cu x1 apartine de de A1,x2
apartine de A2,…,xn apartine de An;
multimile A1,A2,…,An sunt multimi finite,iar elementele lor se considera ca se afla intr-o relatie
de ordine bine stabilita;
nu se dispune de o alta metoda de rezolvare,mai rapida.
Observatii:
nu pentru toate problemele n este cunoscut de la inceput;
x1,x2,…,xn pot fi la randul lor vectori;
in multe probleme,multimile A1,A2,…,An coincide.
Observatie: tehnica Backtracking are ca rezultat obtinerea tuturor solutiilor problemei.In cazul in care se
cere o singura solutie,se poate forta oprirea,atunci cand a fost gasita.
95
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1 2 2 2 2
1 1 1 1 1 1
1 2 3
3 3 3 3 1
1 1 1 1 2 2
1 2 3 1
1 1 1 2 3 3
2 2 2 2 2 2
96
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Cum procedam?Observam, ca o dama trebuie sa fie plasata singura pe linie.Plasam prima dama pe
linia 1 coloana 1.
Observam ca a treia daman u poate fi plasata in linia a 3-a.Incercam atunci plasarea celei de-a doua
dame in coloana a 4-a.
D
97
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
D
D
D
D
D
Acum este posibil sa plasam a patra dama in coloana a-3-a si astfel am obtinut o solutie a problemei.
D
D
D
D
Algoritmul continua in acest mod pana cand trebuie scoasa de pe tabla prima dama.
Pentru reprezentarea unei solutii putem folosi un vector cu n componente (avand in vedere ca pe
fiecare linie se gaseste o singura dama).Exemplu:pentru solutia gasita avem vectorul st ce poate fi
asimilat unei stive.
Doua dame se gasesc pe aceeasi diagonala daca si numai daca este indeplinita conditia:l st(i)-st(j) l=li-
jl: diferenta, in modul, intre linii si coloane este aceeasi).
ST(4)
ST(3)
ST(2)
ST(1)
3 sau situatia:
1
4 D st(1) = 3 i = 1
2 st(3) = 1 j=3
D | st(i) – st(j) l|= | 3-1 | = 2
| i-j | = |1-3 | = 2
98
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Intrucat doua dame nu se pot gasi in aceeasi coloana, rezulta ca o solutie este sub forma de permutare.
O prima idee ne conduce la generarea tuturor permutarilor si la extragerea solutiilor pentru problema
( ca doua dame sa nu fie plasate in aceeasi diagonala).A proceda astfel, inseamna ca nu lucram
conform strategiei backtracking.
99
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
else
begin
k:=k+1;
x[k]:=0;
end
else
k:=k-1 ;
end;
readln;
end.
begin main( )
{ cout<<”n=”; cin>>n;
write('dati numarul n= '); back( );
readln(n); }
100
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
k:=1; p:=1;
x[k]:=0;
while(k>0) do
begin
repeat
succesor(x,k,as);
if as then valid(x,k,ev)
until (as and ev) or (not as);
if as then
if k=n then begin
writeln('solutia
',p);writeln('==============');
afis(x,k);
end
else
begin
k:=k+1;
x[k]:=0;
end
else
k:=k-1 ;
end;
readln;
end.
cin>>v.camp1;
…
cin>>v.campN
}
101
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
GREEDY
102
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
103
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
PROBLEMA RUCSACULUI
{Dindu-se un rucsac de o anumita capacitate si n obiecte care au un cost #include<iostream.h>
si o greutate si stiind ca se poaate lua si double c[9],g[9],ef[9],gv,man,castig;
o parte din fiecare obiect sa se gaseasca o modalitate de cistig maxim int n,i,man1,inv,ordine[9];
transportat cu rucsacul} main( )
type vector=array[1..9] of real; {cout<<''Greutatea ce poate fi transportata='';cin
var i,n,auxiliara1:integer; ef,c,greutateaobiectului :vector; cout<<''Numar de obiecte='';cin>>n;
capacitatearucsacului,auxiliara,cistig:real; for(i=1;i<=n;i++)
inv:boolean; {
ordine:array[1..9] of integer; cout<<''c[''<<i<<'']='';cin>>c[i];
begin cout<<''g[''<<i<<''];cin>>g[i];
write('greutatea ce poate fi transportata in sac '); ordine[i]=i; ef[i]=c[i] /g[i];
readln(capacitatearucsacului); }
writeln(' cite obiecte sunt'); do
readln(n); {
for i:=1 to n do inv=0;
begin for(i=1;i<=n-1;i++)
write('costul obiectului ',i);readln(c[i]); if(ef[i]<ef[i+1])
write('greutatea obiectului ',i);readln(greutateaobiectului[i]); { man=ef[i];ef[i]=ef[i=1];ef[i=1]=man;
ordine[i]:=i; man=c[i]; c[i]=c[i=1]; c[i=1]=man;
ef[i]:=c[i]/greutateaobiectului[i]; man=g[i];g[i]=g[i+1]=man;
end; inv=1;
repeat man1=ordine[i];ordine[i]=ordine[i+1];ordine[i+1]
inv:=false; }
for i:=1 to n-1 do }
if ef[i]<ef[i+1] while (inv);
then i=1;
begin while(gv>o && i<=n)
auxiliara:=ef[i]; {
ef[i]:=ef[i+1]; if (gv>g[i])
ef[i+1]:=auxiliara; { cout <<''Obieclul ''<<ordine[i]<< ' '<<1<<endl;
auxiliara:=greutateaobiectului[i]; gv-=g[i];castig+=+c[i];
greutateaobiectului[i]:=greutateaobiectului[i+1]; }
104
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
greutateaobiectului[i+1]:=auxiliara; else
auxiliara:=c[i]; {cout<<''Obiectul ''<<ordine[i]<<' ' <<gv /g[i]<<en
c[i]:=c[i+1]; castig+c[i]*gv /g[i];
c[i+1]:=auxiliara; inv:=true; gv=0;
auxiliara1:=ordine[i]; }
ordine[i]:=ordine[i+1]; i++;
ordine[i+1]:=auxiliara1; }
end; cout<<''Castig total=''<<castig;
until not inv; }
cistig:=0;
i:=1;
while (capacitatearucsacului>0) and (i<=n) do
begin
if capacitatearucsacului>greutateaobiectului[i] then
begin
writeln('obiectul cu numarul de ordine ',ordine[i],' ',1);
capacitatearucsacului:=capacitatearucsacului-greutateaobiectului[i];
cistig:=cistig+c[i];
end
else
begin
writeln('obiectul cu numarul de ordine ',ordine[i],' intra din el
',capacitatearucsacului/greutateaobiectului[i]:1:2);
cistig:=cistig+c[i]*capacitatearucsacului/greutateaobiectului[i];
capacitatearucsacului:=0;
end;
i:=i+1;
end;
writeln('cistigul maxim este ',cistig:3:2);
readln;
end.
PROGRAMARE DINAMICA
Alaturi de Greedy,programarea dinamica este o tehnica ce conduce, de cele mai
multe ori, la un timp de calcul polinomial.Mai mult, ea furnizeaza in totdeauna solutia
optima .Din nefericire, programarea dinamica nu se poate aplica tuturor problemelor, ci
numai care indeplinesc anumite conditii.
Se considera o problema in care rezultatul se obtine ca urmare a unui sir de decizii D1,
D2,......Dn. In urma decizei D1 sistemul evolueaza din starea S0 in starea S1,in urma
decizei D2 sistemul evolueaza din starea S1 in starea S2,....,in urma decizei Dn sistemul
evolueaza din starea Sn-1 in stareaSn.
Daca D1, D2,....Dn este un sir de decizii care comduce sistemul in mod optim din S0 in
Sn,atunci trebuie indeplinita una din conditiile urmatoare (principiul de optimalitate):
1)Dk...Dn este un sir de decizii ce conduce optim sistemul din starea Sk-1 in starea
Sn,Ak,1<=k<=n;
2)D1....Dk este un sir de decizii ce conduce optim sistemul din starea S0 in
stareaDk,Ak,1<=K<=;
3)Dk+1...Dn,D1...Dk sunt siruri de decizii care conduc optim sistemul starea Sk in starea
Sn, respectiv din starea D0 in starea Sk,Ak,1<=k<=n.
=>Daca principiulde optimalitate se verifica in forma 1,spunem ca se aplica programarea
dinamica metoda inainte.
=>Daca principul de oplimalitate se verifica in forma 2, spunem ca se aplica programarea
dinamica inapoi.
105
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Vom forma un triunghi,de la baza catre varf,cu sumele maxime care se pot forma cu fiecare
numar.Daca am citit triunghiul de numere intr-o matrice T si calculam sumele intr-o matrice C
vom avea relatiile urmatoare:
C[n][1]:=T[n][1];
C[n][2]:=T[n][2];
C[n][n]:=T[n][n];
Pentru linia i (i<n), cele i sume maxime care se obtin aqstfel:
C[i][j]=max{T[i][j]+C[i+1][j],T[i][j]+C[i+1][j+1]},i apatine multimii {1,2,....,n-1) iar j apartine multimii
{1,.....,i}.
Sa rezolvam problema propusa ca exemplu:
Linia 4 a matricei C va fi linia n a matricei T:5 6 1 4;
Linia 3 se calculeaza astfel:
C[3][1]=max{6+5,6+6}=12;
C[3][2]=max{3+6,3+1}=9;
C[3][3]=max{4+1,4+4}=8;
Linia 2:
C[2][1]=max{3+12,3+9}=15;
C[2][3]=max{5+9,5+8}=14;
Linia 1
C[1][1]=max{2+15,2+14}=17.
106
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
celcareretinesumamaximademomentpelinie[i,j]:=celcareretinesumamaximademo
mentpelinie[i+1,j+1]+t[i,j] ;
end;
writeln('suma este ',celcareretinesumamaximademomentpelinie[1,1]);
d:=celcareretinepozitiadinliniepentrusumamaxima[1,1];
writeln(1);
for i:=1 to n-1 do
begin
writeln(celcareretinepozitiadinliniepentrusumamaxima[i,d]);
d:=celcareretinepozitiadinliniepentrusumamaxima[i,d];
end;
readln;
end.
107
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
108
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
109
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
0 100 x x
x 0 10 x
A= x x 0 100
x x x 0
In continuare calculam:
A(1,3)=min{A(1,k)
+A(k+1,3)+DIM(1)*DIM(k+1)*DIM(4)}=min{0+10+10*1*1,100+0+10*10*1}=20;
A(2,4)=min{A(2,k)
+A(k+1,4)+DIM(2)*DIM(k+1)*DIM(5)}=min{0+100+1*10*10,10+0+1*1*10}=20;
A(1,4)=min{A(1,k)
+A(k+1,4)+DIM(1)*DIM(K+1)*DIM(5)}=min{0+20+10*1*10,100+100+10*10,20+0+10*1*10}=12
0;
.
0 100 20 120
x 0 10 20
A= x x 0 100
x x x 0
In concluzie,pt. exemplul nostru, se fac minim 120 de inmultiri,rezultat luat din matricea A si anume
A(1,4).
LIMBAJUL PASCAL LIMBAJUL C/C++
Inmultiri optimale de matrice
#include<iostream.h>
{Prin programare dinamica sa se determine numarul minim de int i,n,dim[10]
inmultiri care sa se faca long a[10] [10];
cind se dau dimensiunile matricelor
ex:n=4 void costopt(int n,int dim[10],long
10 1 10 1 10} a[10] [10])
{int k,i,j,l;
program inm_optima; long m;
const nmax=20; for (i=1;i<=n;i++) a[i] [i]=0;
type vector=array[1..nmax] of word; for (k=1;k<=n-1;K++)
tabl=array[1..nmax,1..nmax] of word; for (i=1;i<=n-k;i++)
var p:vector; { j=i+k;
m:tabl;n,i,j,k,imin:integer;min,v:word; a[i] [j]=100000;
procedure paranteze(i,j:integer); for(l=i;l<=j;l++)
var k:integer; {m=a[i] [l] +a[l+1] [j]
begin +dim[i]*dim[l+1]*dim[j+1];
if i<j then begin if (a[i] [j]>m)
k:=m[j,i]; {
if i<>k then begin a[i] [j]=m;;
write('('); a[j] [i]=l;
110
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
paranteze(i,k); }
write(')'); }
end }
else paranteze(i,k); cout<<"cost optim:"<<a[1]
write('x'); [n]<<end1;
if k+1<>j then begin
write('('); }
paranteze(k+1,j); main()
write(')') {cout<<"n=";cin>>n;
end for (i=1;i<=n+1;i++)
else paranteze(k+1,j); { cout<<"d=";cin>>dim[i];}
end costopt(n,dim,a);
else write('A',i) }
end;
begin
write('Nr. de matrici:');
readln(n);
writeln('Dimensiuni matricelor:');
for i:=1 to n+1 do read(p[i]);
for i:=n downto 1 do
for j:=i+1 to n do
begin
min:=m[i,i]+m[i+1,j]+p[i]*p[i+1]*p[j+1];
imin:=i;
for k:=i+1 to j-1 do
begin
v:=m[i,k]+m[k+1,j]+p[i]*p[k+1]*p[j+1];
if min>v then begin
min:=v;
imin:=k
end;
end;
m[i,j]:=min;
m[j,i]:=imin;
end;
writeln('Numarul minim de inmultiri este:',m[1,n]);
writeln('Aceasta se obtine pentru urmatoarea ordine a
inmultirilor');
paranteze(1,n);
readln;
end.
111
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
X:=10; cout<<*a;
A=@x; }
Write(a^);
End.
Alocare dinamica
Memoria interna poate fi privita ca o succesiune de octeti.Numarul de ordine
al unui octet se numeste adresa lui.Adresa unei variabile nu trebuie confundata cu
valoarea pe care aceasta o memoreaza.
Definitie: Adresa primului octet al variabilei se numeste adresa variabilei.
Adresele variabilelor se memoreaza cu ajutorul variabilelor de tip pointer.
LIMBAJUL PASCAL LIMBAJUL C/C++
Alocarea spatiului pentru variabila poiter p si elberarea lui
Procedure new(var p:pointer); P=new p;
Procedure dispose (var p :pointer); Delete p;
Ex: Ex:
Var adr1:^integer; Void main ()
New(adr1);adr^:=7; {
Writeln(adr1);dispose(adr1); int * adr1;
End; adr1=new int;
adr =7;cout<<*adr1;
delete adr1;
}
Tipul enumerare
LIMBAJUL PASCAL LIMBAJUL C/C++
union nume_enumerare
{
tip v0;
tip v1;
…
tip vn-1;
};
Exemplu:
#include< iostream.h>
union test
{ int a;
char b[10];
112
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
double c;
};
main()
{
test var;int I;
cin>>var.c;cout<<var.c<<endl;
cin>>var.c;cout<<var.c<<endl;
}
Siruri de caractere
LIMBAJUL PASCAL LIMBAJUL C/C++
SINTAXA: SINTAXA:
TYPE NUME=string[dimensiune]; Char nume[dimensiune] ;
Var variabila:nume; Char nume[dimensiune] =”sirul”;
Sau: Ex:
Var variabila:string[dimensiune]; #Include<iostream.h>;
Variabila[0] este lungimea sirului main()
Are maxim 255 de caractere {
Ex: char a[20];
Var a:string[3]; cin>>a;
Begin cout<<a;
A:=”cal”; }
Write(a); obs:
End. a[0] reprezinta prima componenta
a sirului
Functii care lucreaza cu siruri de caractere
LIMBAJUL PASCAL LIMBAJUL C/C++
LUNGIMEA UNUI SIR DE CARACTERE
Sintaxa: Sintaxa:
Variabila :=Length(sir); #include<string.h>
Ex: Variabila:= strlen (sir);
Var s: string; Ex:
Begin #include<iostream.h>
Readln(s); #include<string.h>
Writeln(length(s); main()
End. {
char a[100];
cin.get(a,100);
cout<<”sirul este de lungimea
“<<strlen (a);
}
113
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
READLN(S3);
S1:= s2+S3;
Writeln (s1);
End.
114
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
DELETE(SIRsursa,DE_UNDE_STERG,pana_in_ce_pozitie);
Ex:
Var s1: string;
Begin
Readln(s1);
delete(s1,1,length(s1)-2);
Write(s1);
End.
115
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
char a[100]=”11.2001”;
s=strtoi(a);
cout<<p;
}
#include<iostream.h>
#include<string.h>
main()
{
FLOAT s;
char a[100]=”11.2001”;
s=strtof(a);
cout<<p;
}
Stiva funcţionează pe principiul LIFO (Last In First Out) – “ultimul intrat, primul ieşit”.
Pentru a înţelege modul de lucru cu stiva, ne imaginăm un număr n de farfurii identice, aşezate
una peste alta (o “stivă” de farfurii). Adăugarea sau scoaterea unei farfurii se face, cu uşurinţă, numai în
vârful stivei. Oricât ar părea de simplu principiul stivei, el are consecinţe uriaşe în programare.
Stivele se pot aloca secvenţial (ca vectori). Fie ST[i] un vector. ST[1], ST[2], … , ST[n] pot reţine numai
litere sau numai cifre. O variabilă k indică în permanenţă vârful stivei, adică ultimul element introdus.
Observaţii:
În mod practic, la scoaterea unei variabile din stivă, valoarea variabilei ce indică vârful stivei scade cu 1, iar atunci
când scriem ceva în stivă, o eventuală valoare reziduală se pierde.
Pe un anumit nivel se reţine, de regulă, o singură informaţie (literă sau cifră), însă este posibil, aşa cum va rezulta
din exemplele prezentate în lucrare, să avem mai multe informaţii, caz în care avem stive duble, triple, etc.
116
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
În cazul stivei, alocarea secvenţială nu prezintă mari dezavantaje, ca în cazul mai general, al listelor, pentru că nu
se fac operaţii de inserare sau ştergere în interiorul stivei. Singurul dezavantaj, în comparaţie cu alocarea dinamică
înlănţuită este dat de faptul că numărul de noduri care pot fi memorate la un moment dat este mai mic – depinde de
gradul de ocupare al segmentului de date.
În literatura de specialitate veţi întâlni termenul PUSH pentru operaţia de adăugare în stivă a unei înregistrări şi
POP, pentru extragere.
Exemple:
Vom începe prin a studia modul de calcul al funcţiei pentru x=15 şi x=8.
f(15)=14;
f(8)=f(f(10))=f(f(f(12)))=f(f(11))=f(f(f(13)))=f(f(12))=f(11)=f(f(13))= f(12)=11.
Algoritmul va folosi o stivă ST şi o variabilă k, ce indică în permanenţă vârful stivei. Algoritmul se
bazează pe următoarele considerente:
■ la o nouă autoapelare a funcţiei f, se urcă în stivă (k se incrementează cu 1) şi se pune noua valoare.
■ în situaţia în care pentru valoarea aflată pe nivelul k se poate calcula funcţia, se coboară în stivă, punându-se pe
acest nivel noua valoare.
12 13
10 10 11 11
8 8
8 8 8
12 13
11 12
8 11
f=11
117
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
118
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
119
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
pop(v);
tipar(v);
readln;
DINAMIC IN GENERAL
{Sa se creeze o stiva.
Scrieti doua proceduri diferite care
elimina elemente in stiva}
type ref=^inr;
inr=record
nr:integer;
urm:ref;
end;
var p:ref;
i,n:integer;
procedure b(var p:ref);
var c:ref;
begin
new(c);
writeln(' pe cine pui in stiva
');readln(c^.nr);
c^.urm:=p;
p:=c;
end;
procedure s(var p:ref);
var c:ref;
begin
if p=nil then
writeln(' goala ')
else
begin
writeln(' scot din stiva pe');
writeln(p^.nr);
c:=p;
p:=p^.urm;
dispose(c);
end;
end;
procedure s1(var p:ref);
var q:ref;
begin
q:=p;
p:=q^.urm;
dispose(q);
end;
begin
write('dati un numar n>=3 ');
readln(n);
for i:=1 to n do
b(p);
writeln('-----------elimin elementul din
virful stivei');
s1(p);
120
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
for i:=1 to n do
s(p);
readln;
end.
□ Funcţia lui Ackermann. Se dă funcţia următoare, definită pe produsul cartezian NXN.. Se citesc m şi
n. Să se calculeze Ack(m, n).
| n+1, m=0
Ack(m,n)= | Ack(m-1, 1), n=0
| Ack(m-1, Ack(m, n-1)), altfel
Pentru calculul acestei funcţii, folosim o stivă dublă, ST. Iniţial, valorile m şi n se reţin la nivelul 1. Pe
nivelul k al stivei se reţin valorile curente m şi n. În funcţie de valorile acestora se procedează astfel:
■ pentru m şi n diferite de 0, este necesar un nou calcul de funcţie, caz în care se urcă în stivă şi pe noul
nivel se pun argumente m şi n-1.
■ pentru cazul n=0, se rămâne pe acelaşi nivel în stivă, punând în locul lui m valoarea m-1, iar în locul
lui n valoarea 1.
■ în situaţia în care m=0, funcţia se poate calcula; se coboară în stivă şi se înlocuieşte valoarea lui m cu
m-1, valoarea lui n cu valoarea calculată anterior.
10 01
20 11 11 11
21 21 21 21 21
10
01 11 11
11
02 02 13 12 12
12
21 12
13 03
12 13 13
13 13 13 04
121
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
ack(2,1)=5.
else else
begin {
k:=k-1; k--;
if (k>0) if (k>0)
{ st[k,0] =st[k,0] – 1; { st[k] [0] =st[k[] [0] – 1;
st[k,1] =st[k+1,1] +1; st[k] [1] =st[k+1] [1] +1;
end; }
end; }
write(”ac(“m, n”) = ”,st[1,1] +1); cout<<”ac(“<<m<<’, ‘<<n<<”) =
end. ”<<st[1] [1] +1;
}
dinamic
#include <iostream.h>
struct Nod
{
int info;
Nod* adr_inap;
};
Nod* v;
int n;
void Pop(Nod*& v)
122
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
{
Nod* c;
If (!v) cout<<”stiva este vida”;
Else
{
c=v;
cout<<”am scos”<< c-
>info<<end1;
v=v->adr_inap;
delete c;
}
}
main( )
{ Push(v,1); Push(v,2); Push(v,3);
Pop(v); Pop(v); Pop(v); Pop(v);
}
Coada funcţionează pe principiul FIFO (First In First Out) – “primul intrat, primul ieşit”.
1 2 3 4
2 3 4 5
3 4 5 6
v sf
3 5 2
123
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
7
LIMBAJUL PASCAL LIMBAJUL C/C++
COADA
{Considerind in doua fisiere niste numere ordonate crescator #include <iostream.h>
in fiecare struct Nod
sa se preia numarele in ordine descrescatoare si sa se puna {
intr-o lista simplu int info;
inlantuita care sa fie COADA pentru ca la listare sa fie afisate Nod* adr_urm;
in }
ordine crescatoare
Sa se puna datele ordonate in alt fisier din lista creata Nod* v, *sf;
anterior} int n;
type po=^nod;
nod=record void Pune( Nod*& v, Nod*& sf,
info:integer; int n)
leg:po; {
end; Nod* c;
var p,q,d,u:po; If (!v)
f,g:text; { v= new Nod; v->info=n; v-
procedure o; >adr_inap=0;
var a,b:integer; sf=v;
begin }
p:=nil; else
assign(f,'f1.pas'); { c= new Nod;
assign(g,'f2.pas'); sf->adr_urm=c;
reset(f); c->info=n;
reset(g); c->adr_urm=0;
read(f,a);read(g,b); }
while (not eof(f) and not eof(g)) do }
begin
new(q); void Scoate(Nod*& v)
if a<b then begin { Nod* c;
q^.info:=a;read(f,a); if (!v) cout<<”coada este
end vida”<<end1;
else else
if (a=b) then begin { cout<<”Am scos”<<v-
q^.info:=a; >info<<end1;
read(f,a);read(g,b); c=v; v=v->adr_urm;
end delete c;
else }
begin }
q^.info:=b;
read(g,b); void Listare(Nod* v)
end; { Nod* c=v;
IF (P=NIL) THEN BEGIN while ( c )
{ cout<<c->info<<” “;
q^.leg:=p; c=c->adr_urm;
p:=q; }
u:=p; cout<<end1;
end }
else main( )
begin { Pune(v, sf, 1); Pune(v, sf, 2);
q^.leg:=nil;u^.leg:=q;u:=q; Pune(v, sf, 3); Listare(v);
end; Scoate(v); Listare(v);
end; Scoate(v); Listare(v);
while (not eof(f)) do begin Scoate(v); Listare(v);
new(q);q^.info:=a;q^.leg:=nil; Scoate(v); Listare(v);
u^.leg:=q;u:=q; }
124
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
read(f,a);
end;
close(h);
end;
begin
o; {L;
writeln;}
Li;
readln;
end.
CU LISTE DUBLU INLANTUITE
{ Sa se creeze o structura de coada}
type ref=^inr;
inr=record
nr:integer;
as,ad:ref;
end;
var p,u:ref;i,n:integer;
procedure b(var u:ref);
var c:ref;
begin
new(c);
writeln(' pe cine pui in coada
');readln(c^.nr);
c^.ad:=nil;
c^.as:=nil;
if u<>nil then u^.ad:=c else
p:=c;
125
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
u:=c;
end;
procedure s(var p:ref);
var c:ref;
begin
if p=nil then writeln(' e goala ') else
begin
writeln(' pe cine scot ');
writeln(p^.nr);
c:=p;p:=p^.ad;
p^.as:=nil;
dispose(c);
end;
end;
begin
writeln(' cite elemente dai
n>=3');readln(n);
for i:=1 to n do
b(u);
for i:=1 to n do
s(p);
readln;
end.
Prezentarea structurii
O listă liniară este o colecţie de n≥0 noduri, X₁, X₂, … , Xn aflate într-o relaţie de ordine.
Astfel, X₁ este primul nod al listei, X₂ este al doilea nod al listei … Xn este ultimul nod.
Operaţiile permise sunt:
□ Accesul la oricare nod al listei în scopul citirii sau modificării informaţiei conţinute de acesta.
Există două metode de alocare a unei liste liniare: alocarea secvenţială şi alocarea
înlănţuită.
126
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Nodurile listei ocupă poziţii succesive în memorie. Acest tip de alocare l-am întâlnit des,
de câte ori am utilizat vectori.
Exemplu: un vector are n componente de tip real. Se cere să se sorteze vectorul crescător.
Algoritmul are ca dată de intrare o listă liniară, cu n noduri de tip real. Ieşirea este tot o listă
liniară, cu aceleaşi noduri, dar în altă ordine. Să presupunem că utilizăm sortarea prin
interschimbare. O interschimbare a nodurilor i şi j se reduce la următoarele operaţii, premise în
listă:
■ v[i] v[i+1]; - accesez nodul i+1 în vederea citirii (operaţie permisă) şi accesez nodul i în vederea
modificării informaţiei reţinute (operaţie permisă).
■ v[i+1] = man; - accesez nodul i+1 în vederea modificării informaţiei reţinute de el.
În concluzie, sortarea se realizează prin utilizarea operaţiilor permise asupra unei liste
liniare.
Avantajul alocării secvenţiale este dat de faptul că programatorul are acces direct la oricare din
nodurile listei, la fel ca la componentele unui vector.
Dezavantajul alocării secvenţiale este dat de faptul că operaţiile de adăugare, eliminare sau
schimbare de poziţie a unui nod necesită un efort mare de calcul, ca în exemplul următor, în care
se elimină un nod:
127
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
■ in₁, in₂, in₃, … , inn reprezintă informaţiile conţinute de noduri, de altă natură decât cele de
adresă;
După cum observăm, fiecare nod, cu excepţia ultimului, reţine adresa nodului următor.
2. Alocarea dublu înlănţuită. Alocarea simplu înlănţuită permite parcurgerea listei într-un
singur sens (de la stânga la dreapta). În cazul în care se doreşte ca lista să poată fi parcursă
în ambele sensuri se utilizează alocarea dublu înlănţuită. Aici fiecare nod reţine adresele
predecesorului şi succesorului său, aşa cum se vede în figura următoare:
Avantajele alocării înlănţuite sunt date de faptul că operaţiile de adăugare sau eliminare a unui
nod se fac rapid. Exemplele sunt date pentru lista liniară simplu înlănţuită, dar bine înţelese, ne
permit să deducem singuri modul de efectuare a operaţiilor respective pentru liste dublu
înlănţuite.
Fie lista:
3 adr₂
7 adr₃ 9 nil
Etapele sunt:
7 adr₃
9 nil
128
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3 adr₂
adr₁ adr₂ adrn
adrt
□ Se completează informaţiile pentru nodul creat – câmpul de adresă trebuie să conţină adresa
nodului care trebuie să-i urmeze în listă:
3 adr₂
7 adr₃
9 nil
5 adr₂
adrt
□ Se modifică adresa nodului care precede nodul nou creat. Adresa trebuie să fie a nodului nou
creat:
5 adr₂
adrt
129
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
b) Ştergerea unui nod. Pentru a exemplifica operaţiile efectuate în acest caz vom folosi a de mai
sus, la care ştergem al doilea nod (cel cu informaţia 5). Iată etapele:
□ Informaţia de adresă a nodului care îl precede trebuie să reţină adresa nodului următor:
3 adr₂ 9 nil
5 adr₂ 7 adr₃
adr₁ adrt adr₂ adrn
7 adr₃ 9 nil
3 adr₂
adr₁ adr₂ adrn
7 adr₃ 9 nil
130
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
3 adr₂
adr₁ adr₂ adrn
Observaţii:
În cazul alocării înlănţuite, adresele de memorare ale nodurilor consecutive nu sunt neapărat
consecutive. Pentru a realiza acest lucru este suficient să analizaţi cazul ştergerii unui nod (sau
acela al adăugării unui nod).
Prin alocarea memoriei pentru un nod înţelegem rezervarea spaţiului necesar memorării
informaţiilor conţinute de acesta. Evident, se poate aloca memorie doar dacă există memorie
disponibilă, adică nu este ocupată de alte variabile.
Pentru eliberarea memoriei ocupate de un nod înţelegem că spaţiul ocupat de acesta devine
disponibil – este pus la dispoziţia programatorului, pentru ca, eventual, acesta să fie din nou
alocat.
Este important să folosim termenii corect. De exemplu, nu putem folosi în loc de “alocarea
memoriei” termenul “crearea memoriei”, tot aşa cum nu este corect să folosim în loc de
“eliberarea memoriei” termenul “ştergere a memoriei”.
Noţiunile care privesc alocarea şi eliberarea memoriei sunt prezentate în paragraful următor.
131
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
132
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
133
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
134
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c:=p;
for i:=1 to cecaut-1 do
c:=c^.urm;
begin
new(pecinepun);
writeln(' pe cine vrei sa pui ');
readln(pecinepun^.nr);
pecinepun^.urm:=c^.urm;
c^.urm:=pecinepun ;
c:=c^.urm;
end;
end;
procedure pununainaintedemaimulte;
var cecaut:integer; pecinepun :ref;
begin
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=nil;
u:=oretinpepenua ;
dispose( desters);
end;
procedure stergdupaunacareocaut;
var oretinpepenua,desters:ref;cecaut:integer;
begin
writeln('dupa a cit-a intergistrare vreti sa stergeti
');readln(cecaut);
c:=p;
for i:=1 to cecaut do
135
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=c^.urm;
dispose( desters);
end;
procedure sterguele;
var oretinpepenua,desters:ref;multe:integer;
begin
writeln('cite vreti sa stergeti incepind de la sfirsit spre inceput
');readln(multe);
for i:=1 to multe do
begin
c:=p;
while (c<>u) do
begin
oretinpepenua :=c;
c:=c^.urm;
end;
desters :=c;
oretinpepenua^.urm :=nil;
u:=oretinpepenua ;
dispose( desters);
end;
end;
procedure stergdelapamaimulte;
var desters:ref;multe:integer;
begin
writeln('cite vreti sa stergeti incepind de la pa ');readln(multe);
for i:=1 to multe do
begin
desters :=p;
p:=p^.urm;
dispose( desters);
end;
end;
procedure stergdupacecaut;
var osterg:ref;cecaut:integer;
begin
c:=p;
writeln(' dupa ce valoare vrei sa stergi');
readln(cecaut);
while (c<>nil) and (c^.nr<>cecaut) do
c:=c^.urm;
if c=nil then writeln(' nu este in lista ')
else
begin
osterg:=c^.urm;
136
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c^.urm:=c^.urm^.urm;
{dispose(osterg); }
end;
end;
procedure stergcecaut;
var oretin,osterg:ref;cecaut:integer;
begin
c:=p;
writeln(' ce valoare vrei sa stergi');
readln(cecaut);
while (c<>nil) and (c^.nr<>cecaut) do
begin
oretin:=c;
c:=c^.urm;end;
if c=nil then writeln(' nu este in lista ')
else
begin
osterg:=c;
oretin^.urm:=c^.urm;
dispose(osterg);
end;
end;
procedure stergcecautdeciteoriapare;
var oretin,osterg:ref;cecaut:integer;potsterge:boolean;
begin
writeln(' ce valoare vrei sa stergi');
readln(cecaut);
potsterge:=true;
while potsterge do
begin
c:=p;
137
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
c:=p;
writeln('cu cine modifici pe pa');readln(c^.nr);
end;
procedure modificua;
begin
c:=u;
writeln('cu cine modifici pe ua');readln(c^.nr);
end;
procedure modificcepozitiecaut;
var cecaut:integer;
begin
c:=p;
writeln(' a cit-a inregistrare vrei sa o modifici');
readln(cecaut);
for i:=1 to cecaut-1 do
c:=c^.urm;
writeln(' cu cine o modifici');
readln(c^.nr);
end;
begin
init;
afisare;
inserareinaintedepa;
afisare;
inserareinaintedepamaimulte;
afisare;
adaugunlasfirsit;
afisare;
adaugunlasfirsitmaimulte;
afisare;
pununadupamaimulte;
afisare;
pununainaintedemaimulte;
afisare; writeln('o sterg pe pa ');
stergpa ;afisare;
stergdelapamaimulte; afisare;
stergua;
writeln('o sterg pe ua ');
afisare;
sterguele;afisare;
stergdupaunacareocaut;
afisare;
pununadupacecaut;afisare;
stergdupacecaut;
afisare;
stergcecaut;
afisare;
stergcecautdeciteoriapare; afisare;
modificpa;
afisare;
modificua; afisare;
modificcepozitiecaut; afisare;
readln;
end.
138
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
1) creare;
2) adaugare la dreapta;
3) adaugare la stanga;
4) adaugare in interiorul listei;
5) stergere din interiorul listei;
6) stergere la stanga listei;
7) stergere la dreapta listei;
8) listare de la stanga la dreapta;
9) listare de la dreapta la stanga.
1) Creare
2) Adaugare la dreapta
Functia add citeste informatia numerica, aloca spatiu pentru inregistrare, completeaza adresele,
modifica adresa la dreapta a inregistrarii din s cu adresa noii inregistrari si ii atribuie
lui s valoarea noii inregistrari.
3) Adaugare la stanga
Functia includ parcurge lista pentru a gasi inregistrarea cu informatia m, in dreapta careia urmeaza sa
introducem noua inregistrare, citeste informatia, aloca spatiu, completeaza informatia, completeaza
adresa stanga a noii inregistrari cu valoarea adresei inregistrarii de informatie m, si completeaza adresa
dreapta a noii inregistrari cu valoarea adresei dreapta a inregistrarii cu informatia utila m.
Functia Sterg parcurge lista pentru a gasi informatia care va fi stearsa, atribuie inregistrarii precedente
campul de adresa dreapta al inregistrarii care va fi stearsa, iar inregistrarii care urmeaza celei care va fi
stearsa i se atribuie campul de adresa stanga al inregistrarii pe care o stergem, dupa care se elibereaza
spatiul de memorie rezervat inregistrarii care se sterge.
139
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
140
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
141
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
d^.as:=q;
end;
end;
procedure listare;
var c:ref;
begin
c:=p;
while(c<>nil) do
begin
writeln(c^.nr,' ');
c:=c^.ad;
end;
end;
procedure listare1;
var c:ref;
begin
c:=u;
while(c<>nil) do
begin
writeln(c^.nr,' ');
c:=c^.as;
end;
end;
begin
creare;
writeln('------------------');
listare; writeln('sterg pe ultima ------------------');
stegultima;
writeln('o listez de la sfirsit spre inceput------------------');
listare1;
adauginaintedeprima;
writeln('------------------');
listare; writeln('------------------');
adugadupaultima; listare; writeln('------------------');
adaugadupaa_p1_acomponenta; listare; writeln(' sterg prima
------------------');
stegprima;listare; writeln('------------------');
stergA_p1_componenta; listare; writeln('------------------');
ins1; listare;
readln;
end.
Grafuri orientate
Notiuni introductive
_
Definitie.Se numeste graf orientat perechea ordonata G=(x,l ).
-Daca in acest graf [x,y] apartin multimii gama, vom spune ca x si y sunt
adiacente, iar varfurile x si y sunt incidente cu muchia [x,y].
-Daca gama(g)=multimea vida, acest graf se numeste graf nul si reprezentarea
lui in plan se reduce la puncte izolate.
142
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Definitie.Un graf partial al unui graf orientat dat este un graf G1=(x,g1) unde g1este
inclus sau = cu g.
Definitie. Un subgraf al unui graf orientat G=(x,g) este un graf H=(y1,g1),unde y1-
inclus sau = cu x, iar muchiile din g1 sunt toate muchiile din g care au ambele
extremitati in multimea y.
-Gradul unui nod x(d(x)) este de doua feluri:
*grad exterior
*grad interior
Definitie.Un drum al unui graf orientat L=[x0,x1,x2,…xp] este o succesiune de
varfuri cu proprietatea ca [x0,x1]aparrtine de g, [x1,x2] la fel, s.a.
-x0 si xp = extremitatile drumului;
-p=lungimea drumului;
-daca x0,x1,…,xp sunt distincte doua cate doua drumul=elementar;
-daca x0=xp,drumul=circuit
-daca toate varfurile circuitului, cu exceptia primului si ultimului sunt distincte,
circuitul=elementar;
-un circuit elementar care trece prin toate nodurile grafului se numeste circuit
hamiltonian.
143
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
u:=u+1; coada[sf_c]=k;
co[u]:=j;
vi[j]:=1; s[k]=1;
end; }
if i<=u then pp(i+1); I_c++;
end; Bf_r1();
begin
clrscr; }
writeln(' n=');readln(n); }
writeln(' nuamrul de muchii ');readln(m); main()
for i:=1 to m do
begin
[ Citire(“graf.txt”,A,n);
writeln('dati muchia ',i); I_c=sf_c=1;
writeln( 'primul nod al muchiei ');readln(x); Coada[I_c]=s[1]=1;
writeln(' nodul de sfirsit al muchiei ');readln(y); Bf_r1();
a[x,y]:=1;a[y,x]:=1;
end; For(I=1;I<=sf_c;I+
for i:=1 to n do +)cout<<coada[I]<<” “;
vi[i]:=0; }
writeln(' care este nodul de plecare ');readln(pl);
vi[pl]:=1;
co[1]:=pl;
p:=1;
u:=1;
while p<=u do
begin
el:=co[p];
for j:=1 to n do
if (a[el,j]=1) and (vi[j]=0) then begin
u:=u+1;
co[u]:=j;
vi[j]:=1;
end;
p:=p+1;
end;
for i:=1 to u do
write(co[i],' ');
pp(1);
writeln(' parcurgere recursiva in latime ');
for i:=1 to u do
write(co[i],' ');
readln;
end.
IN ADANCIME
IN ADANCIME
{Parcuregerea in adincime la grafuri neorientate
-se face incapand de la un nod I
ex:n=5
-dupa parcurgerea unui nod se parcurge
m=4
primul dintre descendntii sai neparcursii inca
si anume (1 2),(1 5), ( 2 3),(2 4)
EX:
nodul de pelecare este 1 =>
#include “grafuri.cpp”
12345
int s[50],A[50][50],n;
}
void df_r9int nod)
uses crt;
{
var a:array[1..20,1..20] of integer;
int k;
vi:array[1..20] of integer;
cout<<nod<<” “;
i,n,el,j,p,u,pl,m,x,y:integer;
s[nod]=1;
procedure pp(pl:integer); for (k=1;k<=n;k++)
var j:integer; if ((A[nod][k]==1) && (s[k]==0))
begin df_r(k);
write(pl,' ');vi[pl]:=1; }
for j:=1 to n do main()
if (a[pl,j]=1) and (vi[j]=0) then pp(j); {
end; Citire(‘Graf.txt”,A,n);
Df_r(1);
}
begin
clrscr;
writeln(' n=');readln(n);
writeln(' numarul de muchii ');readln(m);
144
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
for i:=1 to m do
begin
writeln('dati muchia ',i);
writeln( 'primul nod al muchiei ');readln(x);
writeln(' nodul de sfirsit al muchiei ');readln(y);
a[x,y]:=1;a[y,x]:=1;
end;
for i:=1 to n do
vi[i]:=0;
writeln(' care este nodul de plecare ');readln(pl);
pp(pl);
readln;
end.
Un graf G este conex , daca oricare ar fi doua varfuri ale sale ,exista un lant care le
leaga.
Definitie:
Se numeste componenta conexa a grafului G=(X,U),un subgraf G1=(X1,U1) a lui
G ,conex , cu propietatea ca nu exista nici un lant care sa lege un nod din X1 cu un
nod din X-X1(pentru orice nod , nu exista un lant intre acel nod si nodurile care nu
fac parte din subgraf).
Graf tare conex .Componente tare conexe
Definitie:
Un graf orientat G=(X,U) este tare conex, daca pentru oricare doua noduri x si y
apartin de X, exista un drum de la x la y precum si un drum de la y la x.
Definitie
Fiind dat un graf orientat G=(X,U), se numeste componenta tare conexa a lui
G ,un subgraf G1=(X1,U1),tare conex, si maximal in raport cu aceasta propietate
(adica pentru orice nod x apartine de X-X1, subgraful indus de X1 U{x} nu mai este
tare conex).
145
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
df_r2(k);
program tareconexe; }
type mat=array[1..50,1..50] of byte; main()
var f:text; {
n:byte; Citire(“Graf.txt”,A,n);
a:mat; Cout<<”Introduceti nodul de pornire
procedure citeste; “;cin>>I;
var i,x,y:byte; Suc[I]=pred[I]=I;
begin Df_r1(I);df_r2(I);
assign(f,'in7.pas'); For (j=1;j<=n;j++)
reset(f); If ( (suc[j]==pred[j])&& (suc[j]==I) )
readln(f,n); Cout<<j<<” “;
}
while not eof(f) do DESCOMPUNEREA IN
begin COMPONENTE TARI CONEXE
readln(f,x,y); #include “grafuri.cpp”
a[x,y]:=1; int suc[50],pred[50],A[50][50],n,nrc,I,j;
end; void df_r1(int nod)
close(f); {
end; int k;
suc[nod]=nrc;
procedure Roy_Warshall; for (k=1;k<=n;k++)
var i,j,k:byte; if ( (A[nod][k]==1)&&(suc[k]==0) )
begin df_r1(k);
for k:=1 to n do }
for i:=1 to n do void df_r2(int nod)
for j:=1 to n do {
if a[i,j]=0 then a[i,j]:=a[i,k]*a[k,j]; int k;
end; pred[nod]=nrc;
for (k=1;k<=n;k++)
procedure componente; if ( (A[k][nod]==1)&&(pred[k]==0)
var k,i,j:byte; df_r2(k);
viz:array[1..50] of boolean; }
begin main()
for i:=1 to n do viz[i]:=false; {
k:=1; Citire(“Graf.txt”,A,n);
for i:=1 to n do Nrc=1;
if not viz[i] then For (I=1;I,=n;I++)
begin If (suc[I]==0)
writeln('Componenta',k,':'); {
write(i,' '); suc[I]=nrc;
viz[i]:=true; df_r1(I);df_r2(I);
for j:=1 to n do for (j=1;j<=n;j++)
if(j<>i)and (a[i,j]<>0)and(a[j,i]<>0)then if (suc[j]!=pred[j]) suc[j]=pred[j]=0;
begin nrc++;
write(j,' '); }
viz[j]:=true; for (I=1;I<=n;I++)
end; {
k:=k+1; cout<<:”Componenta “<<I<<endl;
writeln for (j=1;j<=n;j++)
end; if (suc[j]==I) cout<<j<<” “;
end; cout<<endl;
}
begin }
citeste;
Roy_Warshall;
componente;
readln;
end.
146
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Consideram un graf orientat G=(X,U) cu n noduri, in care fiecarui arc ii este asociat un
numar intreg numit cost. Semnificatia
acestui cost poate fi foarte variata , in functie de domeniul pe care il descrie graful .
Matricea costurilor
Pentru evidentierea costurilor tuturor arcelor unui graf cu n noduri se poate defini o
matrice a, cu n linii * n coloane.Exista doua forme ale acestei matrici:
Forma a): Fiecare element a[i,j] poate fi:
c , daca exista un arc de cost c>0 intre nodurile i si j;
0, daca i=j;
+∞ ,daca nu exista arc intre nodurile i si j .
Forma b): Este absolut similara,cu singura deosebire ca in loc de +∞ avem -∞.
Forma a) se foloseste pentru determinarea drumurilor de cost minim intre doua
noduri , iar forma b) este utilizata in aflarea drumurilor de cost maxim.
Daca dorim sa citim matrice costurilor ,evident ca nu putem introduce de la tastatura
“+”! In loc de + vom da un numar intreg foarte mare.
LIMBAJUL PASCAL LIMBAJUL C/C++
CAUTAREA UNUI SIR DE CARACTERE
{Fiind dat un graf neorientat G si doua varfuri x si y in acest graf, sa se Algoritmul lui ROY-FLOYD-vom aplica
determine un lant elementar de lungime minima, avand ca extremitati strategia generala Divide et
varfurile date. Datele de intrare se citesc din fisierul Graf.dat care are Impera(pentru lungimea minima):
urmatoarea componenta: #include “grafuri.cpp”
- pe prima linie se afla numarul de varfuri ale grafului(n); float A[50][50];
- pe a doua linie sunt inscrise cele doua extremitati ale lantului int n;
elementar separate prin spatii; void Drum(int I, int j)
- pe urmatoarele n linii se gasesc valorile matricei de adiacenta {
separate int k=1,gasit=0;
prin spatii. Datele de iesire se vor afrsa pe ecran si vor consta in: while ( (k<=n) && !gasit)
- mesajul "Nu exista lanl elementar Fntre cele doua varfuri" {
sau if ( (I!=) && (j!=k) && (A[I][j]==A[I]
- mesajul "Lantul minim are lungimea .... ", iar pe linia urmatoare [k]+A[k][I]) )
varfurile {
lantului Drum(I,k);Drum(k,j);
separate printr-un spatiu. Gasit=1;
K++;
Rezolvare }
Rezolvarea acestei probleme se bazeaza pe formarea matricei if (!gasit) cout<<j<<” “;
lanturilor. Un }
element al acestei matrici va contine Iungimea lantului minim dintre void Scriu_drum(int Nod_Initial, int
varfurile Nod_Final)
corespunzatoare liniei si coloanei.} {
program lant_elementar; if (A[Nod_Initial][Nod_Final]<Pinfinit)
const infinit=100; {
type matrice=array[1..20,1..20] of byte; cout<<”Drumul de la
var n,x,y:byte;a:matrice;f:text; “<<Nod_Initial<<” la “<<Nod_Final<<”
procedure citeste; are lungimea “<<A[Nod_Initial]
var i,j,p,q:byte; [Nod_Final]<<endl;
begin cout<<Nod_Initial<<” “;
147
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
assign(f,'in2.pas');reset(f); Drum(Nod_Initial,Nod_Final);
readln(f,n); }
else
for i:=1 to n do cout<<”Nu exista drum de la
for j:=1 to n do “<<Nod_Initial<<” la “<<Nod_Final;
if i=j then a[i,j]:=0 }
else a[i,j]:=infinit; void Lungime_Drumuri()
readln(f,x,y); {
while not eof(f) do int I,j,k;
begin for (k=1;k<=n;k++)
readln(f,p,q); for(I=1;I<=n;I++)
a[P,q]:=1; a[q,P]:=1; for (j=1;j<=n;j++)
end; if (A[I][j]>A[I][k]+A[k][j]
close(f) A[I][j]=A[I][k]+A[k][j];
}
end; main()
prOcedure mat_drumuri; {
var i,j,k:byte; Citire_cost(“Graf.txt”,A,n);
begin Lungime_Drumuri();
for k:=1 to n do Scriu_drum(4,2);
for i:=1 to n do }
for j:=1 to n do
if a[i,j]>a[i,k]+a[k,j] then *Algoritmul ROY-FLOYD pentru a gasi
begin drumuri de lungime maxima:
a[i,j]:=a[i,k]+a[k,j]; #include “grafuri.cpp”
a[j,i]:=a[i,j]; float A[50][50]
end; int n;
end; void Drum(int I,int j)
procedure drum(v1,v2:byte); {
var k:byte;gasit:boolean; int k=1,gasit=0;
begin while ( (k<=n) && !gasit)
k:=1;gasit:=false; {
while(k<=n)and not gasit do if ( (I!=k) && (j!=k) && (A[I][j]==A[I]
begin [k]+A[k][j]) )
if(v1<>k)and(v2<>k)and(a[v1,v2]=a[v1,k]+a[k,v2])then {
begin Drum(I,k0;Drum(k,j);
drum(v1,k);drum(k,v2); Gasit=1;}
gasit:=true; K++;
end; }
k:=k+1; if (!gasit) cout<<j<<” “;
end; }
if not gasit then write(v2,' '); void Scriu_drum(int
end; Nod_Initial,Nod_Final)
begin {
citeste; if (A[Nod_Initial][Nod_Final].Minfinit)
mat_drumuri; {
if a[x,y]=infinit then writeln('Nu exista lant elementar intre cele doua cout<<”Drumul de la “<<Nod_Initial<<”
varfuri') la “<<Nod_Final<<” are lungimea
else “<<A[Nod_Initial][Nod_Final]<<endl;
begin cout<<Nod_Initial<<” “;
writeln('Drumul minim are lungimea:',a[x,y]); Drum(Nod_Initial,Nod_Final);
write(x,' '); }
drum(x,y); else
end; cout<<”Nu exista drum de la
readln; “<<Nod_Initial<<” la “<<Nod_Final;
end. }
void Lungime_Drumuri()
{
int I,j,k;
for (k=1;k<=n;k++)
148
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
for (I=1;I<=n;I++)
for (j=1;j<=n;j++)
if (A[I][j]=A[I][k]+A[k][j];
}
main()
{
Citire_cost1(“Graf.txt”,A,n);
Lungime_Drumuri();
Scriu_drum(1,2);
}
ALGORITMUL
ALGORITMUL DIJKSTRA DIJKSTRA
{ Fie n localitati intre care exista o retea de drumuri.
Fiind dat un graf memorat prin matricea
Un turist care se gaseste in localitatea A doreste sa viziteze
ponderilor, se cere sa se determine pentru
localitatea
orice x,y apartin de X lungimea minima a
B cu cheltuieli minime. Cheltuielile turistului sunt direct proportionale
drumului de la nodul x la nodul y.Prin
cu distanta parcursa dintr-o localitate in alta.
lungimea unui drum intelegem suma
Cunoscandu-se lungimea fiecarui drum dintre localitati, sa se
ponderilor arcelor care-l alcatuiesc.
determine un
Include “grafuri.cpp”
traseu pe care sa-l urmeze calatorul din localitatea A pana in
Float A[50][50],D[50],min;
localitatea B
Int S[50],T[50],n,I,j,r,poz;
astfel incat costul calatoriei sa fie minim. Un drum intre doua localitali
Void drum(int I)
poate fi unidirectional sau bidirectional, pentru fiecare drum
{
cunosandu-se
if (T[I]) drum(T[I]);
lungimea.
cout<<I<<” “;
}
. Rezolvare
main()
Programul determina drumul minim intre doua varfuri ale unui graf
{
orientat
Citire+cost(“Graf.txt”,A,n);
folosind algoritmul Dijkstra.
Cout<<”Introduceti nodul de pornire
n-numarul de localitati
“<<endl;
a-matricea ponderilor asociata grafului;
Cout<<”r=”;cin>>r;S[r]=1;
d-vectorul care contine lungimea drumului minim dintre localitatea de
For (I=1;I<=n;I++)
plecare si o alta localitate;
{
D[I]=A[r][I];
p-vectorul care memoreaza varfurile prin care se trece pentru a
If (I!=r)
obtine
If (D[I]<Pinfinit) T[I]=r;}
drumul minim.}
For (I=1;I<=n;I++)
program drum_minim;
{
const infinit=1e38;
min=Pinfinit;
type matrice=array[1..50,1..50] of real;
for(j=1;j<=n;j++)
multime=set of byte;
if (S[j]==0)
vect=array[1..50] of real;
var n:byte;a:matrice;f:text;v1,v2:byte; if (D[j]<min)
d:vect;p:array[1..50] of byte; {
procedure citeste; min=D[j];
var i,x,y,j:byte;cost:real; poz=j;
begin }
assign(f,'in8.pas'); S[poz]=1;
reset(f); For (j=1;j<=n;j++)
readln(f,n); If (s[j]==0)
for i:=1 to n do If (D[j]>D[poz]+A[poz][j])
for j:=1 to n do {
if i=j then a[i,j]:=0 D[j]=D[poz]+A[poz][j];
else a[i,j]:=-1; T[j]=poz;
readln(f,v1,v2); }
while not eof(f) do for (I=1;I<=n;I++)
begin if (I!=r)
readln(f,x,y,cost); if(T[I])
a[x,y]:=cost; {
149
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Grafuri neorientate
Notiuni introductive
150
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
Definitie.Un graf partial al unui graf neorientat dat G=(X,g) este un graf G1=(X,g1
unde g1 inclus sau=cu g.
Definitie.Unsubgraf al unui graf neorientat G=(X,g) este un graf H=(Y<g1), unde
Yinclus in X, iar muchiile din g1 sunt toate muchiile din g care au ambele extremitati
in multimea Y.
Definitie.Lant.Pentru graful neorientat , un lant este o succesiune de varfuri cu
proprieatea ca oricare doua varfuri sunt adiacente.
Grafuri hamiltoniene
Definitie:
Se numeste ciclu hamiltonian intr-un graf, un ciclu elementar care contine toate varfurile
grafului .
Se numeste graf hamiltonian ,un graf care contine un ciclu hamiltonian.
Se numeste lant hamiltonian intr-un graf, un lant elementar care contine toate varfurile
grafului.
Teorema:
Daca intr-un graf G=(X,U) cu n>=3 varfuri, gradul fiecarui varf x verifica conditia
d(x)>=n/2, atuncigraful este hamiltonian,
151
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
var i:integer; }
begin main () { st[1]=1;k=2;st[k]=1;
for i:=1 to k do CitireN(“graf.txt”,a,n);
write( x[i] ,' '); Back();
write(x[1]:4); }
writeln;
end;
begin
Grafuri euleriene
Definitie:
Se numeste ciclu eulerian intr-un graf, un ciclu care contine toate muchiile grafului.
Se numeste graf eulerian, un graf care contine un ciclu eulerian.
Teorema:
Un graf fara varfuri izolate este eulerian, daca si numai daca este conex, si
gradele tuturor varfurilor sunt numere pare
LIMBAJUL PASCAL LIMBAJUL C/C++
152
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
153
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
end; main()
begin { CitireN(“Graf.txt”,A,n);
write(' cite noduri are graful n='); if (conex())
readln(n); if (grade_pare())
write(' cite muchii are graful m='); {
readln(m); Alista=new Nod;
for I:=1 to n do Alista->nd=1;Alista->adr_urm=0;
for j:=1 to n do While (adauga());
a[i,j]:=0; Indice=Alista;
writeln('dati muchiile '); While (Indice)
for i:=1 to m do { cout<<Indice->nd<<” “;
begin Indice=Indice->adr_urm;
writeln('primul nod al muchiei ',i,' este ');readln(x); }
writeln('urmatorul nod al muchiei ',i,' este }
');readln(y); else cout <<”Graful nu indeplineste conditiile de
a[x,y]:=1; paritate”;
a[y,x]:=1; else cout<<”Graful nu este conex”;
end; }
eulerian:=not izolate and gradepare and conex;
if not eulerian then writeln ('graful nu este eulerian
')
else
begin
writeln('este eulerian ');
nd[1]:=1;
k:=1;
repeat
for j:=1 to n do
if a[nd[k],j]=1 then begin
k:=k+1;
nd[k]:=j;
a[nd[k-1],j]:=0;
a[j,nd[k-1]]:=0;
grd[j]:=grd[j]-1;
grd[nd[k-1]]:=grd[nd[k-1]]-1;
break;
end;
until nd[k]=1;
while k-1 <m do begin
for i:=1 to k-1 do
if grd[nd[i]]>0 then begin
c1[1]:=nd[i];
L:=i;
break;
end;
k1:=1;
repeat
for j:=1 to n do
if a[c1[k1],j]=1 then begin
k1:=K1+1;
c1[k1]:=j;
a[c1[k1-1],j]:=0;
a[j,c1[k1-1]]:=0;
grd[j]:=grd[j]-1;
grd[c1[k1-1]]:=grd[c1[k1-1]]-1;
break;
end;
until c1[k1]=c1[1];
for j:=k downto L do
nd[j+k1-1]:=nd[j];
154
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
155
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
156
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
157
Rezolvarea temelor pentru concursurile de titularizare si grade didactice in informatica
Prof.Bogdan Constantin
CUPRINS
Prefata…………………………..……………………………………………………………..1
Exemple de roboti………….………………………………………………………………….2
Structura robotilor…………………………………………………………………………..…5
Sistemul mecanic al robotului…….……………………….………………………………..…
33
Sistemul de actionare si comanda la roboti……………………………………………………
39
Senzori…………………………………………………………………………………………
48
Aplicatii roboti ficşi si mobili in
industrie……………………………………………………..62
Constructia electronica a unui robot……….………………………………………………...…
93
Cuprins……………………………………………………………………………………...…
117
158