VIZAT

Decan Prof. Univ. Dr. Rodica TRANDAFIR

Sef de catedra Conf. Univ. Dr. Rodica IOAN

FISA DISCIPLINEI
I. UNIVERSITATEA FACULTATEA DOMENIUL DE LICENTA SPECIALIZAREA Anul universitar Forma de invatamant II. DENUMIRE DISCIPLINA SPIRU HARET MATEMATICA-INFORMATICA INFORMATICA INFORMATICA 2008 - 2009 ZI TEHNICI AVANSATE DE PROGRAMARE

III. CODUL DISCIPLINEI IV. Statut disciplina Obligatorie Optionala Facultativa (se marcheaza cu X) X V. Structura disciplinei (nr. ore) Semestrul Curs Seminar Laborator Lucrari practice Proiecte (numar de (nr. ore/sapt. (nr. ore/sapt. (nr. ore/sapt. (nr. ore/sapt. (nr. ore/sapt. la 1 la 6) si total si total si total si total si total nr.ore/sem.) nr.ore/sem.) nr.ore/sem.) nr.ore/sem.) nr.ore/sem.) 4 2/28 2/28 VI.(ETCS) Numar credite 6 VII. OBIECTIVELE DISCIPLINEI 1. Valorificarea cunostintelor acumulate in cadrul cursurilor de Programare Procedurala, Algoritmi si Structuri de date, Proiectare si Programare Orientata Obiect in vederea programarii unor algoritmi avansati elaborati cu metode specifice. 2. Crearea deprinderilor de a gandi si programa folosind sabloane (templates) 3. Insusirea unor algoritmi avansati in domeniul prelucrarii sirurilor. 4. Cresterea capabilitatii in utilizarea in programarea generica a limbajelor C++ si Java. 5. Asigurarea compatibilitatii cu invatamantul de excelenta : University of Cambridge (http://www.cl.cam.ac.uk/DeptInfo/CST05/node30.html); Imperial College London (http://www3.imperial.ac.uk/computing/teaching/undergraduate/computing/lectures); Princeton University (http://www.cs.princeton.edu/academics/catalog/ugrad) VIII. CONTINUT TEMATIC I. Structuri de date fundamentale (Recapitulare) II. Metode avansate de proiectarea algoritmilor: 1. Recursivitate 2. Metoda Greedy 3. Metoda Backtracking

4. 5. 6. 7.

Metoda Divide et impera Metoda Programării dinamice Metoda Branch&Bound. Procesarea sirurilor

IX. TEME SEMINAR X. LUCRARI DE LABORATOR 1. Metode de elaborarea algoritmilor (14 ore) 2. Biblioteca Standard de Sabloane (STL) a limbajului C++ (6 ore) 3. Cautare in siruri (2 ore) 4. Programare generica in Java (6 ore). XI. LUCRARI PRACTICE XII. PROIECTE XIII. Forma de evaluare (procent din nota finala) Examen Colocviu Verificare pe Lucrari parcurs practice 70% XIV. Bibliografie Obligatorie minimala 1. Albeanu G., Algoritmi si limbaje de programare, Editura FRM, 2000 (pag. 207233) 2. Albeanu G. (coord), L. Rapeanu, L. Radu, A. Averian, Tehnici de programare, Editura FRM, 2003. 3.Doina Logofatu, Algoritmi fundamentali in Java/C++. Aplicatii. Polirom, 2007 (integral). 4. Valeriu Iorga, Cristian Opincaru, Corina Stratan, Alexandru Chirita, Structuri de date si algoritmi. Aplicatii in C++ folosind STL, Polirom, 2005. XV. Suplimentara 1. Java, Using and Programming Generics in J2SE 5.0, http://java.sun.com/devel oper/technicalArticles/J2 SE/generics/ 2. C. Galatan, Introducere in C++ Standard Template Library, Ed. All, 2008. 3. R. Neapolitan, K. Naimipour , Foundations of Algorithms Using C++ Pseudocode, Jones and Bartlett Publishers, 2004. Laborator 30% Proiecte -

Facultativa 1. N.M. Josuttis, The C++ Standard Library, AddisonWesley, 1999. 2. A. Drozdek, Data structures and algorithms in C++, Brooks/Cole, 2001. 3. Roberge J., Brandle S., Whittington D., A laboratory course in C++ data structures (ed. 2), Jones and Bartlett Publishers, 2003.

Metode didactice (clasice/moderne) 1. Prelegerea - proiecţie in amfiteatru, programe demonstrative; 2. Recomandarea, pentru studiul individual, a unor paragrafe din bibliografia indicată, în vederea aprofundării sau extinderii cunoştinţelor căpătate la curs/laborator ; 3. Prezentarea unor exemple şi a unor probleme aplicative în cadrul cursului pentru sporirea interesului cursantilor. 4. Evaluare folosind platforma Blackboard. Data _____________________ Titular disciplina Titlul didactic, Numele si Prof. Univ. Dr. GRIGORE prenumele ALBEANU Semnatura _______________________

structuri arborescente.2. Ele sunt mult mai flexibile decât cele statice şi din această cauză sunt extrem de avantajoase. Operaţiile curente care se fac în liste sunt: inserarea unui nod. Liste: O listă este o colecţie de elemente de informaţie (noduri) aranjate într-o anumită ordine. Structuri de date O structură de date este o mulţime de date organizate într-un anumit mod împreună cu relaţiile dintre acestea. conform ordinii nodurilor în listă. Structurile de date semistatice ocupă o zonă de memorie de dimensiune constată. Alocarea dinamică permite gestionarea memoriei în timpul executării programului. mulţimea. • structuri de date semistatice: stiva alocată static. Alocarea 31 . Avantajele acestei tehnici sunt accesul rapid la predecesorul/succesorul unui nod şi găsirea rapidă a primului/ultimului nod. numărarea elementelor unei liste etc. Fişierele sunt structuri de date externe (vezi capitolul 1). • Implementarea înlănţuită. Dezavantajele sunt inserarea/ştergerea relativ complicată a unui nod şi faptul că nu se foloseşte întreaga memorie alocată listei. ştergerea (extragerea) unui nod. înregistrarea. structurile de date se clasifică în: • structuri de date statice : tabloul. În funcţie de modul de alocare. Structura corespunzătoare de date trebuie să ne permită să determinăm eficient care este primul/ultimul nod în structură şi care este predecesorul/succesorul (dacă există) unui nod dat. Structurile de date dinamice ocupă o zonă de memorie de dimensiune variabilă. fişierul. Lungimea unei liste este numărul de noduri din listă. • structuri de date dinamice: lista înlănţuită. Structurile de date statice ocupă o zonă de memorie constantă pe toată durata de executare a blocului în care apare declaraţia şi elementele ocupă poziţii fixe. Fiecare nod conţine două părţi: informaţia propriu-zisă şi adresa nodului succesor. alocată pe toată durata executării blocului în care apare declaraţia de structură. concatenarea unor liste. în locaţii succesive de memorie. Implementarea unei liste se poate face în principal în două moduri: • Implementarea secvenţială. alocată dinamic. iar elementele ocupă poziţii variabile pe parcursul executării programului. Limbajele Pascal sau C(++) oferă posibilităţi de implementare a acestor structuri atât static cât şi dinamic. coada alocată static.

O lista circulară este o lista în care. foarte rapidă. Se rezervă zonă de memorie în memoria heap pentru nodul curent. în schimb. unde urm este adresa următorului nod (pointer către următorul nod). urm: lista. Operaţii asupra listei simplu înlănţuite Crearea unei liste simplu înlănţuite: 1. Accesul la un nod necesită parcurgerea tuturor predecesorilor săi. struct nod *urm. Fiecare nod conţine un pointer a cărui valoare reprezintă adresa nodului următor din listă. O listă dublă are două legături: legătura de tip următor şi legătura de tip precedent sau anterior. după ultimul nod. iar inf este un câmp de informaţie utilă. urmează primul. ceea ce poate lua ceva mai mult timp.1. 2. Pentru a accesa lista avem nevoie de o variabilă care să păstreze adresa primului element (cap sau prim). Limbajul Pascal type lista = ^nod nod=record inf:tip . }lista. deoarece lista la început este goală. end. Liste simplu înlănţuite Între nodurile unei liste simplu înlănţuite este definită o singură relaţie de ordonare. Listele se pot clasifica după locul în care se fac operaţiile de adăugare/eliminare astfel: • stive • cozi 2. deci fiecare nod are succesor şi predecesor. Inserarea/ştergerea unui nod este. Se iniţializează pointerul prim cu Nil/NULL. în timpul rulării programului. Listele se pot clasifica după numărul de legături în: • liste simple • liste duble • liste circulare O listă simplă are o singură legătură.memoriei fiecărui nod se poate face în mod dinamic. Limbajul C(++) typedef struct nod { tip inf. 32 . legătura ultimului element este adresa NIL/NULL.

parcurgerea. Se reia cu pasul 2 dacă se introduce un nod nou. adăugarea unui nod la începutul listei. Se determină adresa ultimului nod şi se realizează legătura cu nodul creat. cât timp q<>NIL şi cheie(q)<>x execută q←urm(q) 3. Observaţii: Limbajul Pascal: Procedura NEW(pointer). 33 . Inserarea unui element x al cărui câmp cheie a fost iniţializat în faţa unei liste înlănţuite LISTA-INSEREAZA(p. 5. Trebuie inclus fişierul antet: stdlib.3. Procedura DISPOSE(pointer)eliberarea memoriei ocupate de către variabila dinamică pointer.x) 1.h sau alloc. adăugarea unui nod la sfârşitul listei. q←p 2. LISTA-CAUTA(p. prelucrăm informaţiile din nod etc.x) 1: urm(x) ←p 2: dacă p<>NIL atunci p←x Căutarea într-o listă înlănţuită p a elementului x se realizează prin subprogramul LISTA-CAUTA şi returnează pointerul la acest obiect. ştergerea unui nod de pe o poziţie dată. returnează q Probleme rezolvate 1. Fiind dată o listă simplu înlănţuită cu elemente numere întregi să se realizeze un program care să execute următoarele operaţii: crearea.alocarea dinamică a memoriei pentru variabila dinamică pointer. 4.h Rezolvare: Parcurgerea unei liste liniare simplu înlănţuite se realizează cu un pointer care pleacă de la capul listei şi va referi pe rând fiecare nod. Se încarcă nodul curent cu date. Limbajul C(++) Funcţia MALLOC se foloseşte pentru a rezerva octeţi din memoria heap. prelucrând informaţiile din nod apoi se trece la următorul nod.

se realizează legătura între nodul p-1 şi p+1 şi. procedure adaug_inc(var cap:lista. {realizarea legaturii si primul nod devine nodul creat} end. begin new(nou).inf. procedure sterge(var cap:lista.cap:=nou.nou^.x:integer. q^. var p. apoi se eliberează memoria ocupată de nodul p. while q^.nou^. procedure listare(cap:lista).Ştergerea unui nod de pe o poziţie dată p din interiorul listei se realizează astfel: se parcurge lista până la pozitia p-1. if cap=nil then cap:=nou else begin q:=cap.x:integer). {trecerea la urmatorul nod} end. 34 . {crearea nodului nou} if cap=nil then cap:=nou else begin nou^. Implementare în Pascal: type lista=^nod.urm.urm:=nou.x:integer). {prelucrarea informatiei} t:=t^.nou^.{listarea listei} var t:lista. begin new(nou). p:integer). end.q:lista.cap:lista.urm:=nil. se păstrează nodul de pe poziţia p.inf:=x. begin t:=cap. {adaugarea la sfarsitul listei} var nou. end.inf:=x.urm.nou^. end.urm<> nil do q:=q^. while t<>nil do begin write(t^.' '). urm:lista end.{adresa primului nod al listei} procedure adaug(var cap:lista.urm:=cap. {adaugarea la inceput} var nou:lista. nod=record inf:integer. end.urm:=nil.

write('informatia adaugata la sfarsit').x). end else if (cap<> nil) then begin t:=cap.urm end.urm. end. }lista. write('pozitia').urm^.{stergerea nodului de pe pozitia p} var q. dispose(q). t^. lista *creare(void). listare(cap).urm=nil then write('nu exista suficiente pozitii') else begin w:=t^. if t^. read(x).sterge(cap. struct nod*urm. dispose(w) end end end.t:lista. 35 .urm:=t^.read(p).p). cap:=cap^. listare(cap).h> #include<alloc.h> #include<stdlib.w.i:integer. lista *prim.urm.adaug(cap. i:=1.urm<> nil) and (i+1<p) do begin inc(i) . begin if cap=nil then writeln('Lista vida !!! ') else if p=1 then begin {stergere la inceputul listei} q:=cap.urm.h> typedef struct nod { int inf. listare(cap) end. void parcurgere(lista *p). begin read(x).read(x). while (t^. Implementare în C: #include <stdio.t:=t^.x). while x<>0 do begin adaug_inc(cap.

prim=(lista*)malloc(sizeof(prim)). } lista *creare(){ int n.i).lista* sterg_inc(lista *prim){ lista *p. parcurgere(prim).&q->inf).&inf). lista *prim.q. p->inf=inf. q=p. scanf("%d". prim=prim->urm. printf("\n"). } void main(){ lista *prim. prim->inf=inf. prim=sterg_inc(prim). prim=creare(). } void parcurgere(lista *p){ lista *q.&n). free(p). return prim.*q. for(q=prim. } return(prim).i.p=p->urm) q=(lista*) malloc(sizeof(q)). printf("informatia primului nod"). } 36 . adauga(prim). %d:".p->urm=NULL. q->urm=p.q->inf). printf("nr.i<=n.scanf("%d".&inf).i++){ printf("inf .q=q->urm) printf("%d ". } void adauga(lista*prim) { /*adauga un nod la o lista simplu inlantuita si returneaza pointerul spre nodul adaugat sau zero daca nu s-a realizat adaugarea*/ lista *p. for (p=prim. p->urm=q.p->urm!=NULL. p=(lista*)malloc(sizeof(p)).inf. p=prim. for (q=p.i=2. q->urm=NULL. parcurgere(prim).prim->urm=NULL.scanf("%d".*q. parcurgere(prim). scanf("%d".*p. de elemente").

Inversarea legăturilor într-o listă simplu înlănţuită. var i. procedure creare(var p:lista. p^. var q:lista.n.urm:=nil end else begin q:=p. p1:=p2. q:=q^. end. end. p^.urm^.urm:=nil.urm:=nil. lista *p1.inf:=x. p2->urm=p1. p2:=p3.urm. return p1. } end. 37 .p3:lista. while q<>nil do begin write(q^. var q:lista.' '). p:lista.urm<>nil do q:=q^. p1=p2.x:integer. Implementare Pascal: program invers.p2. p->urm=NULL. type lista=^nod. while q^. p2=p->urm.urm^. p3 care vor face referire la elementele consecutive din listă.urm. x:integer).inf:=x.*p2. begin p1=p.urm). begin if p=nil then begin new(p). Subprogramul de inversare în C: lista* invers(lista*p){ var p1. p^. nod=record inf:integer. while (p2){ while p2<>nil do begin p3=p2->urm. p2^. p3:=p2^.2. } end. urm:lista end.urm end. function inversare(p:lista):lista. q^. end. p1:=p. q^. inversare:=p1. p2=p3. begin q:=p. procedure listare(p:lista). p2:=p^. p1 va fi capul listei modificate.urm:=p1. p2.urm.inf.*p3. new(q^. Rezolvare: Se parcurge lista iniţială folosind trei variabile dinamice p1.

':').readln(p^.writeln. procedure listare(p:lista). b^.coef. {b este adresa ultimului nod} for i:=2 to n do begin new(a). Rezolvare: Lista are ca informaţie gradul şi coeficientul fiecărui termen de coeficient nenul.grad). writeln(#8. creare(p. urm:lista end. procedure creare(var p:lista). begin write('cati coeficienti nenuli are polinomul'). a^. Pentru a calcula suma este necesar să parcurgem listele celor două polinoame şi să adăugăm corespunzător în cea de-a treia listă. p:=inversare(p).p^. b^.readln(n). Să se efectueze suma a două polinoame rare (polinom cu foarte mulţi coeficienţi egali cu zero) folosind liste simplu înlănţuite. for i:=1 to n do begin read(x). end. write('coef '.' ').grad). nod=record grad:1. 38 . coef:integer.' +').i. i.b.m:integer. var a:lista.grad.n.readln(a^.'x^'. new(p). a:=a^.q. Implementare Pascal: type lista=^nod. listare(p) end. listare(p). b:=a.readln(a^. write('grad '.p.i. p^.r:lista.urm end. 3.urm:=nil end end.5000.x) end.urm:=nil.coef.urm:=a.begin read(n). begin a:=p.':').b:=p. var a.coef). while a<>nil do begin write(a^..

r^. {c este adresa ultimului nod pentru lista suma} while (a<>nil) and (b<>nil) do if a^.coef:=b^.urm:=d.coef:=a^.urm:=nil end. r:=c.c:=d.grad=b^.c^.urm:=nil. d^. c^.grad.r:=c. d^. c^. c^.coef:=a^.urm:=nil.c^. d^.grad:=b^.grad:=a^.coef.grad then begin if r=nil then begin new(c).urm:=d.coef:=a^.coef. c^. r^.c:=d.coef:=b^.c^. d^.grad.grad<b^.procedure aduna(p.c^.grad. c^. b:=b^.d:lista. r:=c.urm:=nil. end else if a^.c.grad.grad:=b^.coef +b^. var a. d^.urm:=nil.b.c:=d. end else begin new(d). end else begin new(d).coef . c^.urm.coef.coef.coef+b^.grad:=a^. begin a:=p. r^.b:=q. a:=a^. end else begin new(d).urm. end.urm.q:lista.grad:=a^. end else begin if r=nil then begin new(c).grad then begin if r=nil then begin new(c).coef:=a^.grad:=a^.urm:=d.var r:lista).coef.urm:=nil. 39 .grad. a:=a^. c^.grad. end.c^.b:=b^.urm. end. d^.

end. Să se implementeze în C aplicaţia de mai sus. Intersecţia celor două liste se determină parcurgând 40 if a<>nil then c^. Se parcurge prima listă şi pentru fiecare nod se verifică dacă este în cea de-a doua listă. 2. Exerciţii: 1. readln. să se afiseze diferenţa celor două liste şi elementele comune celor două liste.urm:=a. r:=nil.q. Valoarea unui polinom se va calcula prin parcurgerea listei şi adăugând la valoare produsul dintre coeficient şi valoarea dată la puterea gradului din nod.r). Să se calculeze valoarea unui polinom într-un punct dat. begin creare(p). aduna(p.urm:=b.end.listare(q). if b<>nil then c^. 4. .creare(q).listare(p). Indicaţie: Calcularea produsului se va face prin parcurgerea tuturor perechilor de termeni astfel: -fiecare pereche generează un nod în polinomul produs -gradul noului nod va fi suma gradelor nodurilor din pereche -coeficientul noului nod va fi produsul coeficienţilor termenilor din pereche -se elimină nodurile din lista de termeni prin păstrarea fiecărui grad o singură dată astfel: dacă există două noduri cu acelaşi grad unul din ele va fi eliminat. 3. iar coeficientul celuilalt va avea valoarea sumei coeficienţilor celor doi termeni. Rezolvare: Diferenţa celor două liste conţine elementele primeia care nu sunt în cea de-a doua. dacă nu se află atunci se adaugă listei trei. Să se scrie un subprogram pentru calcularea produsului a două polinoame rare.Dându-se două liste simplu înlănţuite cu elemente numere intregi distincte. listare(r).

41 . q2:lista. nou.urm:=nou end end.urm<>nil do q:=q^.urm. begin write('nr elem').inf). read(n). procedure diferenta(cap1. Implementare Pascal: type lista=^nod.inf).inf. q^. procedure afisare(cap:lista). read(cap^. while q2<>nil do begin if q2^.inf=x then gasit:=true. cap^. q:=cap.cap3:lista.' ').i:integer. var x:integer. urm:lista end.cap1. while q<>nil do begin write(q^. var q:lista. end.prima listă şi pentru fiecare nod se verifică dacă elementul se află şi în cea de-a doua listă. gasit:=false. var n. while q^. q:=q^. var q.urm:=nil.urm end end. q:=q^. while q<>nil do begin x:=q^. nod = record inf:integer.urm end. procedure creare(var cap:lista).q:lista. dacă da atunci se adaugă în cea de-a treia listă.urm end. ' '). q2:=q2^. for i:=2 to n do begin new(nou). writeln. read(nou^.urm:=nil. new(cap). begin q:=cap. gasit:boolean. if not gasit then write(x. q2:=cap2. nou^.inf. begin q:=cap1.cap2.cap2:lista).

afisare(cap2). cap1).cap2). while q3^. Exerciţiu: Să se implementeze aplicaţia de mai sus in C. afisare(cap3). end. creare(cap2). cu informaţie numerică astfel încât la orice moment al inserării lista să fie ordonată crescător după informaţie.inf.cap3).procedure intersectie(cap1.urm:=nil. 42 . diferenta(cap2.q3:lista. q2:=q2^.urm<> nil do q3:=q3^. Să se creeze o listă simplu înlănţuită.inf=x then gasit:=true.nou. while q<>nil do begin x:=q^.urm. intersectie(cap1. var cap3:lista).urm end end.urm:=nil end else begin new(nou). cap3^. gasit:=false. q:=q^.cap2. nou^.inf:=x .q2. writeln('intersectie'). afisare(cap1).cap2:lista.inf:=x. begin q:=cap1. cap3^.urm. writeln. x:integer. 5. q3^. if gasit then if cap3=nil then begin new(cap3). q2:=cap2. Rezolvare: Paşii: -crearea unui nod nou -dacă informaţia care se adaugă este mai mică decât informaţia din capul listei atunci se inserează în faţa primului nod -altfel se parcurge lista până la primul nod a cărei informaţie este mai mare decât informaţia noului nod şi se inserează. var q. end. nou^. diferenta(cap1. begin creare(cap1). while q2<>nil do begin if q2^.urm:=nou end. q3:=cap3.

prim=nou.&inf).prim->urm=NULL. for (q=p.h> #include <alloc. parcurgere(prim).i++){ printf("informatia nod"). } 43 . } void parcurgere(lista *p){ lista *q. lista *creare(void).h> typedef struct nod { int inf.} else{q->urm=nou. lista *prim. nou=(lista *)malloc(sizeof(lista)). } else { p=q=prim.inf. nou->urm=NULL. } else if (prim->inf>inf){ nou->urm=prim.} } } return prim. printf("nr.q=q->urm) printf("%d ".&n). lista *prim. void parcurgere(lista *p).scanf("%d". while(p&&p->inf<inf){q=p.} if (p) {q->urm=nou.*p. if (prim==NULL){ prim=nou.*nou. de elemente"). p=p->urm.*q.Implementare C: #include <stdio.q. nou->inf=inf. prim=NULL.q->inf).h> #include <stdlib. void main(){ lista *prim. nou->urm=p.i<=n. struct nod*urm. prim=creare().} lista. for(int i=1.scanf("%d". } lista *creare(){ int n.

Să se scrie un program pentru interclasarea a două liste ordonate simplu înlănţuite. } else { prim=prim1. void parcurgere(lista *p). 44 .*ultim. while(prim1&&prim2) if (prim1->inf>prim2->inf){ ultim->urm=prim2. else ultim->urm=prim2.Exerciţiu: Să se implementeze aplicaţia de mai sus în Pascal. Implementare C: #include <stdio. prim2=prim2->urm. } ultim=prim.}lista. Rezolvare: Se va parcurge simultan cele două liste urmând ca introducerea unui nod în lista finală să fie făcută din lista care are valoarea informaţiei din nod mai mică. struct nod*urm. } if (prim1) ultim->urm=prim1. return prim. prim1=prim1->urm. } lista *creare(void). lista *inter(lista *prim1. } else {ultim->urm=prim1.prim2=prim2->urm.h> typedef struct nod {int inf. 6. prim1=prim1->urm.h> #include <stdlib.h> #include <alloc. lista*prim2){ lista *prim. if (prim1->inf>prim2->inf){ prim=prim2. ultim=prim1. ultim=prim2.

void main(){ lista *prim1,*prim2,*prim; prim1=creare(); prim2=creare(); /* parcurgere(prim1) */; prim=inter(prim1,prim2); parcurgere(prim1); } lista *creare(){ int n,inf; lista *prim,*p,*q,*nou; printf("nr. de elemente");scanf("%d",&n); prim=NULL; for(int i=1;i<=n;i++){ printf("informatia nod");scanf("%d",&inf);; nou=(lista *)malloc(sizeof(lista)); nou->inf=inf; if (prim==NULL){ prim=nou; prim->urm=NULL; } else if (prim->inf>inf){ nou->urm=prim;prim=nou; } else { p=q=prim; while(p&&p->inf<inf){q=p;p=p->urm;} if(p) {q->urm=nou;nou->urm=p;} else { q->urm=nou;nou->urm=NULL; } } } return prim; } void parcurgere(lista *p){ lista *q; for (q=p;q;q=q->urm) printf("%d ",q->inf); } Exerciţiu: Să se implementeze aplicaţia de mai sus în limbajul Pascal.
45

2.2. Liste dublu înlănţuite Pentru liste duble create dinamic modul de definire a unui nod este:
Limbajul Pascal type lista=^nod; nod=record inf:tip; urm, ant:lista; end; typedef struct nod{ inf tip; struct nod *urm; struct nod *ant; }lista;

Operaţiile care se pot defini asupra listelor dublu înlănţuite sunt aceleaşi ca şi în cazul listelor simplu înlănţuite: - crearea unei liste dublu înlănţuite; - accesul la un element al unei liste dublu înlănţuite; - inserarea unui nod într-o listă dublu înlănţuită; - ştergerea unui nod dintr-o listă dublu înlănţuită; - ştergerea unei liste dublu înlănţuite. Probleme rezolvate 1. Să se scrie un program care va conţine un meniu cu principale operaţii asupra listei dublu înlănţuite. Implementarea Pascal a soluţiei: type lista=^nod; nod=record inf:integer; urm,ant:lista end; var cap:lista; x:integer; procedure creare(var cap:lista); begin new(cap); write('inf=');readln(cap^.inf); cap^.urm:=nil;cap^.ant:=nil; end; procedure adaugare(var cap:lista); var q,nou:lista; begin new(nou);readln(nou^.inf);nou^.urm:=nil; q:=cap; while q^.urm <> nil do q:=q^.urm; q^.urm:=nou;nou^.ant:=q; end;
46

procedure inserare(var cap:lista); var nou,q:lista; k,i:integer; begin writeln('unde inserezi? '); read(k);new(nou); write('ce? ');readln(nou^.inf); if k=1 then begin cap^.ant:=nou; nou^.urm:=cap; nou^.ant:=nil; cap:=nou; end else begin q:=cap; i:=1; while (q^.urm<>nil) and (i<k) do begin q:=q^.urm; inc(i) end; if i=k then begin nou^.ant:=q^.ant; q^.ant^.urm:=nou; nou^.urm:=q; q^.ant:=nou; end else begin write('nu exista'); readln end end end; procedure stergere(var cap:lista); var q,p:lista; k,i:integer; begin write('unde stergi? '); readln(k); if cap<>nil then if k=1 then begin q:=cap; cap:=cap^.urm; dispose(q); cap^.ant:=nil; end else begin p:=cap;i:=1; while (p^.urm<>nil) and(i<k) do begin p:=p^.urm; inc(i); end;
47

writeln('5. 3:inserare(cap).parcurgere'). end end end.urm<>nil do q:=q^. p^.parcurgere_inv'). readln end . while q<>nil do begin write(q^.ant^. procedure parcurgere_inv(var cap:lista).urm end.iesire').urm.end end. 6:parcurgere_inv(cap).inserare').adaugare'). writeln('3. begin while x<> 7 do begin writeln('1. var q:lista. readln end. 48 if i=k then begin q:=p. case x of 1:creare(cap). 2:adaugare(cap). writeln('4. end. var q:lista.stergere'). readln. 4:stergere(cap). p^. begin q:=cap. dispose(q). ' '). 5:parcurgere(cap). begin q:=cap. writeln('7.inf. ' ').ant:=p^. q:=q^.creare').ant. writeln('2.ant end. writeln('6. end else begin write('nu exista'). while q^.urm^.urm:=p^. while q<>nil do begin write(q^.inf. readln(x). q:=q^. procedure parcurgere(var cap:lista).urm.

&p->inf). puts("\n Parcurgere indirecta"). prim->urm=prim->ant=NULL. Crearea şi parcurgerea listei dublu înlănţuite în limbajul C: #include<stdio. scanf("%d". parcurg(p->urm).h> #include<stdlib.&prim->inf). printf("informatia primului nod").scanf("%d".i<=n. } void creare(int n){ int i.*ultim.&n).scanf("%d". void parcurg1(lista*ultim). void parcurg(lista*prim). lista *p. ultim=prim. p->ant=ultim. for(i=2. prim=(lista*)malloc(sizeof(lista)). } 49 .parcurg1(ultim). lista*prim . p->urm=NULL.q->inf). void creare(int n). for (q=p. } } void parcurg1(lista *p){ lista *q.parcurg(prim).q. printf("inf="). } lista. creare(n). } } void parcurg(lista*p){ if (p){ printf("%d ". ultim=p.h> typedef struct nod{int inf. void main(){ int n.i++){ p=(lista*)malloc(sizeof(lista)).ultim->urm=p. struct nod*urm.q=q->ant) printf("%d ".2. puts("\n Parcurgere directa").*ant.p->inf). printf("numarul de elemente:").

/*parcurgerea listei*/ printf("%d ". Listele circulare simple sunt liste simple care au în plus propietatea că valoarea câmpului următor a ultimului nod este adresa capului listei. p=prim.i++){ q=(lista*)malloc(sizeof(lista)). } p->urm=prim.3.2. Liste circulare După numărul de legături. p->urm=q.i<=n. } Problemă rezolvată: Se dă un grup de n copii aşezaţi în cerc.p=q. printf("inf="). Dându-se pasul de eliminare m se cere să se precizeze ordinea ieşirii din cerc. void main(){ lista *prim.h> typedef struct nod{ int inf.prim->inf). for (q=prim->urm.scanf("%d".}lista. int i. printf("nr de elemente"). Crearea şi parcurgerea listei circulare simplu înlănţuite în limbajul C: #include<stdio.h> #include<conio.*p. care sunt număraţi din m în m. listele circulare se împart în: liste simple şi liste duble.*q. prim=(lista*)malloc(sizeof(lista)). for (i=2.&q->inf).n. /*crearea listei circulare*/ printf("inf primului nod"). Listele circulare duble sunt liste duble care au propietatea că legătura următor a celui de-al doilea cap este primul cap şi legătura anterior a primului cap este al doilea cap.q=q->urm) printf("%d ".&n).scanf("%d".q->inf).h> #include<stdlib. Copilul care a fost numărat cu valoarea m este eliminat. 50 .q!=prim. scanf("%d".&prim->inf).prim->urm=NULL. struct nod *urm.

prim. begin new(q).urm. q:=p^. write(q^. Implementarea Pascal (Lista circulară este simplă. procedure listare(prim:lista). writeln('castigator='.urm:=prim.urm:=prim end.i).urm.x:integer).n. p^.p:lista. for i:=2 to n do adaugare(prim. p^. procedure creare(var prim:lista. urm:lista end.inf. listare(prim). end. read(m). dispose(q).m. begin new(q).urm. write(q^.' ') end.inf:=x.' ').p^.q.urm.x:integer). creare(prim. procedure adaugare(var prim:lista. end.inf.inf). prim^.urm:=q^.' ').j:integer. p:=prim. begin {program principal} read(n).1). Numărarea se va face parcurgând m elemente de la poziţia de unde s-a efectuat ultima ştergere.inf:=x.urm<>prim do begin q:=q^. q:=prim. prim^. q^.Rezolvare: Simularea eliminării copiilor se realizează cu o listă circulară la care se realizează eliminarea nodului care are ca informaţie numărul copilului scos din joc. end. new(p).urm<>prim do q:=q^. nod=record inf:integer.p:lista.) type lista=^nod.q:=prim. 51 . var q. end.urm else for j:=1 to m-1 do p:=p^. var q:lista.urm. write(q^. begin new(prim).inf. for i:=1 to n-1 do begin if i=1 then for j:=1 to m-2 do p:=p^. var i. while q^.p^.urm:=p. while q^.

&m). void creare(void).Implementarea C (Lista circulară este dublă).p->inf). i<=n.free(q).p->inf).*p. struct nod *urm.prim->inf=1. printf("%d ".h> typedef struct nod{int inf.p=p->urm) printf("%d". /* p=p->urm.p=p->urm. p=q. lista *prim. printf("pasul de numarare").k. prim->urm=prim->ant=NULL.i++. parcurgere().i=1. q->ant=p.prim->ant=q. while (p!=p->ant){ for( i=1. q->inf=i. i++){ q=(lista*)malloc(sizeof(lista)). int n.m.*/ } void creare(){ printf("nr. p->urm->ant=p->ant.scanf("%d".h> #include<stdlib. } q->urm=prim. q=p.*q.p->inf).i. p->ant->urm=p->urm. void main(){ creare(). p->urm=q. prim=(lista*)malloc(sizeof(lista)).scanf("%d".&n). } void parcurgere(){ for (p=prim. }lista.i<=n. #include <stdio. void parcurgere(void). } 52 . p=prim. } printf("%d".i++)p=p->urm. de copii").*ant. for (i=2.i<m.

Stive O stivă (stack) este o listă liniară cu proprietatea că operaţiile de inserare/extragere a nodurilor se fac în/din vârful listei. iar ultimul în S[top]... Last In First Out) sau liste pushdown. deci nu depind de mărimea stivei. unde top este o variabilă care conţine adresa (indicele) ultimului nod inserat. unde n este numărul maxim de noduri. push pop Cel mai natural mod de reprezentare pentru o stivă este implementarea secvenţială într-un tablou S[1 .2. Ultimul nod inserat va fi şi primul şters. al doilea în S[2]. Algoritmii de inserare şi de ştergere (extragere) a unui nod: function push(x. n]) {adauga nodul x in stiva} if top = n then return “stiva plina” top ←top+1 S[top]← x return “succes” function pop(S[1 .. stivele se mai numesc şi liste LIFO (eng. 53 . Primul nod va fi memorat în S[1]. S[1 .4. n]) {sterge ultimul nod inserat din stiva si il returneaza} if top =0 then return “stiva vida” x ← S[top] top ← top-1 return x Cei doi algoritmi necesită timp constant. n].

procedure sterge(var cap:stiva). var q:stiva. if cap=nil then cap:=nou else begin nou^. begin if cap=nil then writeln('Stiva vida') else begin q:=cap. nod=record inf:integer. end.Problemă rezolvată: Realizaţi un meniu în limbajul Pascal care să conţină operaţii asupra stivei. type stiva=^nod. nou^. cap:=nou. begin q:=cap.'|'). var nou:stiva.inf. readln(nou^.urm end. var q:stiva. 54 Rezolvare: Implementarea Pascal: . end. procedure adauga(var cap:stiva).q^. urm:stiva end.urm:=cap. cap:=cap^. begin new(nou). writeln('Ce sa adaug? '). procedure parcurgere(cap:stiva). var cap:stiva.inf). end.urm. writeln('___') end.urm:=nil. while q<> nil do begin writeln('|'. x:integer. dispose(q) end. q:=q^.

Indicaţie: Se doreşte partiţionarea vagoanelor în k submulţimi care au vagoanele ordonate crescător 2. First In First Out). 3:parcurgere(cap) end end end. 2:sterge(cap). n-1]. Fie p variabila care conţine indicele locaţiei predecesoare primei locaţii ocupate şi fie u variabila care conţine indicele locaţiei ocupate ultima oară.Adaugare'). readln(x). Cozile se numesc şi liste FIFO (eng. Variabilele p şi u au aceeaşi valoare atunci şi numai 55 . writeln('Dati optiunea'). iar extragerile doar din coada listei. Să se transforme un număr din baza 10 în baza b folosind o stivă.. Exerciţiu: Să se implementeze în limbajul C aplicaţia de mai sus. Cunoscând ordinea iniţială a vagoanelor. liniile de manevră sunt destul de lungi încât să încapă pe o singură linie toate cele n vagoane. writeln('3.2 .Listare').5.Iesire'). să se obţină la ieşire vagoanele în ordine: 1.n. writeln('4. case x of 1:adauga(cap). O reprezentare secvenţială pentru o coadă se obţine prin utilizarea unui tablou C[0 . Probleme propuse 1. queue) este o listă liniară în care inserările se fac doar în capul listei. într-o ordine oarecare. writeln('2. Să se scrie un program care citind numere întregi din fişierul in. n vagoane numerotate de al 1 la n.begin while x<> 4 do begin writeln('1. pe care îl tratăm ca şi cum ar fi circular: după locaţia C[n-1] urmează locaţia C[0]. Linia continuă cu alte k linii de manevră. Pe o linie de cale ferată se găsesc. Cozi O coadă (eng. 2.txt creează o stivă şi o afişează.Stergere').

50] of integer..o.n. Operaţii asupra cozii: function insert-queue(x. end.atunci când coada este vidă. Pentru gestionarea cozii este nevoie de două elemente: p poziţia primului element şi u poziţia de după ultimul element din coadă. begin if p<>(u mod n)+1 then begin c[u]:=x..u:integer. 56 . var p. n-1]) {adauga nodul x in capul cozii} p ← (p+1) mod n if p=u then return “coada plina” C[p] ← x return “succes” function delete-queue(C[0 . Inserarea şi ştergerea (extragerea) unui nod necesită timp constant. C[0 . Se folosesc efectiv numai n-1 locaţii din cele n ale tabloului C.x:integer. var c:coada. Rezolvare: Cea mai simplă implementare a cozii static este folosirea unui tablou. Iniţial. p. procedure adaugare(var c:coada. Se va face o utilizare circulară a spaţiului alocat astfel: următoarea poziţie este p mod n +1. atunci nu am putea distinge situaţia de “coadă plina” şi cea de “coadă vidă”. deoarece în ambele situaţii am avea p = u. n-1]) {sterge nodul din coada listei si il returneaza} if p=u then return “coada vida” u ← (u+1) mod n x ← C[u] return x Testul de coadă vidă este acelaşi cu testul de coadă plină. Dacă s-ar folosi toate cele n locaţii.u.x:integer). deci se pot implementa astfel cozi cu cel mult n-1 noduri. avem p= u= 0. Problemă rezolvată: Relizarea unui meniu pentru implementarea statică a cozii. u:=u mod n +1 end else writeln('coada plina').. Implementarea Pascal: TYPE coada=array[1.

adaugare'). repeat writeln('1. p:=p mod n+1 end else writeln('coada goala'). end.procedure stergere(var c:coada.. writeln('2.u. begin writeln('nr max de elem'). if p<>u then writeln(x). 3: listare(c. 2: begin stergere(c. adaugare(c. read(n).p. end. while i<>u do begin write(c[i].x). end.listare'). i:=i mod n+1 end. end. end. Exerciţiu: Să se implementeze aplicaţia de mai sus în limbajul C++. 57 .p. writeln. until o=4. writeln('3.stergere'). begin if p<>u then begin x:=c[p]. end.' ').u). case o of 1: begin write('introduceti numarul adaugat'). write('citeste optiunea').u. begin if p=u then writeln('coada goala') else begin i:=p..u:integer).p.x). var p.u..u:=1. end. p:=1.readln(o).x:integer). procedure listare(c:coada.readln(x).p. var i:integer.n:=n+1.

i++){ cout<<"inf "<<(i+1)<<":".nou->urm=NULL. prim=NULL. }lista. for (int i=0. de noduri=". Rezolvare: Implementarea în limbajul C++: #include <conio. lista*prim.x). } } lista * creare(){ int n. while (p!=NULL){ cout<<p->inf<<' '.h> // intrări-ieşiri în C++ typedef struct nod {int inf. p=prim.cin>>n. else { nou->urm=prim. struct nod *urm. p=p->urm. void adaug(lista* &prim. clrscr().x. prim=nou. clrscr(). } void parcurgere(lista *prim){ lista *p. cout<<"\n nr. if (prim==NULL) prim=nou.i<n. getch(). *p. cin>>x.h> #include<stdlib. } 58 .} cout<<'\n'. nou=new lista. } return prim. // crearea unui nod în C++ nou->inf=x.Problemă rezolvată: Să se creeze un program care să conţină un meniu cu operaţii asupra unei cozi alocate dinamic. adaug(prim. int x){ lista *nou.h> #include<iostream.

cout<<"2. }while (opt<1&&opt>5). do{ cout<<"optiunea".break. cout<<"Coada\n". } case 3:{ clrscr(). if (prim==NULL) cout<<"coada este vida". cout <<"5.Creare coada\n". } } }while (opt!=5).break. } } void main(){ lista *prim=NULL. while (p->urm->urm!=NULL){p=p->urm.x). cout<<"4.Iesire\n". getch(). switch(opt){ case 1:{prim=creare(). cout<<"3.} case 2:{ clrscr(). } 59 . p->urm=NULL.cin>>x. else { p=prim.void sterg(lista *&prim){ lista *p.Parcurgere\n". adaug(prim. sterg(prim).cin >>opt. noua:". cout<<"inf stearsa="<<(prim->inf).cout<<"inf.Stergere\n".} delete p->urm.x. do{ clrscr(). int opt. } case 4:{ parcurgere(prim).break.break.Adaugare\n". cout<<"1.

Fiind date două liste simple cu informaţii de tip întreg. Se va lucra cu un vector de stive pentru cele k tije. reuniunea. să se separe în două liste elementele de pe poziţii pare de elementele de pe poziţii impare. Fiind dată o listă dublă cu informaţii de tip şir de caractere. Se cere să se 60 . 10. să se realizeze subprograme pentru următoarele operaţii: intersecţia.txt. O maşină trebuie să parcurgă toate oraşele şi să se întoarcă de unde a plecat. Parcurgerea se poate face în ambele sensuri. Pe o tijă sunt n bile colorate cu cel mult k culori. 12.Exerciţiu: Să se realizeze programul în Pascal corespunzător aplicaţiei de mai sus. folosind structuri dinamice. Probleme propuse: 1. Să se realizeze operaţii cu matrici rare folosind alocarea dinamica. Se va parcurge stiva şi se adaugă în stiva corespunzătoare culorii. Să se elimine dintr-o listă simplu înlănţuită toate nodurile care au o informaţie dată. Fiind dată o listă dublă. 5. 7. 2. Fiind dată o listă simplu înlănţuită având informaţii numere întregi să se elimine numerele negative. 3. Să se afişeze bilele de pe fiecare din cele k tije. Să se mute bilele pe alte k tije. informaţia dintr-un nod va fi compusă din numărul bilei şi numărul culorii. 4. să se facă ordonarea elementelor listei. Să se realizeze interclasarea a n liste simplu înlănţuite ordonate crescător. 11. Se vor folosi liste simplu înlănţuite. Fie un traseu circular ce cuprinde n oraşe. 6. 9. diferenţa şi diferenţa simetrică a elementelor celor două liste. pe fiecare punând numai bile din aceeaşi culoare. apoi se şterge din stiva iniţială. 8. fiecare bilă având o etichetă cu un număr de la 1 la n. Indicaţie: Tija iniţială reprezintă o stivă. Să se scrie un program care citeşte cuvintele dintr-un fişier text in. cuvintele sunt separate prin spaţii şi afişează numărul de apariţii al fiecărui cuvânt din fişier. Fiind dată o listă dublă cu informaţii de tip întreg să se construiască o listă dublă numai cu elemente prime. Să se implementeze subprograme pentru operaţiile de bază cu liste circulare duble.

determine un traseu posibil de parcurgere astfel încât să nu rămână în pană ştiind că în fiecare oraş există o staţie de benzină cu o cantitate de benzină suficientă. să se facă un subprogram de inserare a unui element pe o poziţie dată. Fiind dată o listă circulară dublă. Indicaţie: Programul de simulare a problemei indicate construieşte o coadă de aşteptare cu persoanele care sosesc la agenţie în intervalul de timp indicat. adresa expeditorului. Deoarece în gară se inversează poziţia vagoanelor. Indicaţie: se creează o stivă în care se păstrează datele fiecărui vagon. În acest scop se realizează o simulare pe calculator a situaţiei existente care să stabilească o medie a orelor suplimentare efectuate zilnic pe o perioadă de un an. adică un nod al listei simplu înlănţuite. Să se realizeze un subprogram care şterge elementele egale cu zero dintr-o listă circulară. După ce datele au fost puse în stivă. dar publicul aflat la coadă este deservit în continuare. La o agenţie CEC există un singur ghişeu care se deschide la ora 8 şi se închide la ora 16. adresa destinatarului. Să se creeze o listă de liste. să se parcurgă şi să se şteargă. pentru fiecare vagon. următoarele date: codul vagonului. în ordinea alfabetică a cuvintelor respective. 61 . ele se scot de acolo şi se listează. codul conţinutului vagonului. iar maşina consuma c litri la 100 de kilometri. 15. Lista conţine. Într-o gară se consideră un tren de marfă ale cărui vagoane sunt inventariate într-o listă. Se cunosc operaţiile efectuate la agenţie şi timpul lor de execuţie. Se va folosi funcţia random pentru a determina operaţia solicitată şi apoi pentru a determina intervalul de timp între două persoane care vin la agenţie. 13. 19. 14. Să se scrie un program care citeşte cuvintele dintr-un text şi afişează numărul de apariţii al fiecărui cuvânt din textul respectiv. 16. Deoarece la ora închiderii coada este destul de mare se ridică problema oportunităţii deschiderii a încă unui ghişeu la agenţia respectivă. se cere listarea datelor despre vagoanele respective în noua lor ordine. 18. Datele corespunzătoare unui vagon constituie un element al stivei. 17. Să se scrie un program care citeşte cuvintele dintr-un text şi scrie numărul de apariţie al fiecărui cuvânt.

dacă între oricare două vârfuri i si j există un drum de la i la j şi un drum de la j la i. un arbore este un graf neorientat în care există exact un drum între oricare două vârfuri. Un arbore este un graf neorientat aciclic conex. Sau. b). a2). a3}. Un graf parţial este un graf <V. dacă graful este neorientat. M">. a3). dacă între oricare două vârfuri există un drum. care coincid. iar M = VxV este o mulţime de muchii. cu excepţia primului şi ultimului vârf. Împărţirea unui graf G = <V. . unde V este o mulţime de vârfuri.. M'>. an) sau de forma {a1. (an-1. secundară. adică un subgraf conex în care nici un vârf din subgraf nu este unit cu unul din afară printr-o muchie a grafului iniţial. Un drum simplu este un drum în care nici un vârf nu se repetă. Să se realizeze un program care implementează subprograme pentru crearea şi exploatarea unei cozi duble. această noţiune este întărită: un graf orientat este tare conex.. dacă graful este orientat.6. Un ciclu este un drum care este simplu. Se dă o matrice rară memorată într-o listă. iar M' este formată din muchiile din M care unesc vârfuri din V'. Pentru grafuri orientate. 2. M> în componentele sale conexe determina o partiţie a lui V şi una a lui M. şi cu mulţimea {a. (a2. Se cere: a) să se afişeze toate elementele diferite de zero de pe diagonala principală. Două vârfuri unite printr-o muchie se numesc adiacente. {an-1. O componenta conexă este un subgraf conex maximal. În cazul unui graf neconex. Vârfurilor unui graf li se pot ataşa informaţii numite 62 .. fără reconstituirea ei în memorie.. se pune problema determinarii componentelor sale conexe. Un drum este o succesiune de muchii de forma (a1. Un subgraf al lui G este un graf <V'. Un graf neorientat este conex. b}. . 21. {a2. a2}. Grafuri Noţiuni introductive Un graf este o pereche G = <V. an} după cum graful este orientat sau neorientat.. Un graf aciclic este un graf fără cicluri.. O muchie de la vârful a la vârful b este notată cu perechea ordonată (a. Un graf parţial care este arbore se numeşte arbore partial. b) să se afişeze pe ecran matricea sub forma obişnuită. M>.20. Lungimea drumului este egală cu numărul muchiilor care îl constituie. echivalent. unde M" ⊆ M. unde V' ⊆ V.

deoarece dimensiunea ei este limitată de dimensiunea stivei. 63 . Aceasta reprezentare este eficientă atunci când avem de examinat toate muchiile grafului. În cazul grafurilor neorientate. Exemplu de graf orientat: 8 7 5 2 6 0 1 3 4 0 1 2 3 4 5 6 7 8 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 1 0 0 3 0 0 0 0 1 0 0 0 0 4 0 0 0 0 0 1 0 0 0 5 0 0 0 1 0 0 0 1 0 6 0 0 0 0 0 0 0 0 0 7 0 0 1 0 0 0 0 0 1 8 0 0 0 0 0 0 0 0 0 b) Listele de muchii Această metodă de memorare presupune reţinerea unei matrice cu 2 linii şi m coloane. în caz contrar. această matrice este simetrică. iar muchiilor li se pot ataşa informaţii numite uneori lungimi sau costuri. dacă există muchie (arc) de la vârful i la vârful j şi 0. pe fiecare coloană fiind reţinute două extremităţi ale unei muchii.uneori valori. folosindu-se efectiv numai jumătate din spaţiul matricei. Matricea de adiacenţă este folosită în general pentru grafuri cu un număr mic de noduri. definită în felul următor: 1. În unele probleme este eficient ca cealaltă jumătate a matricei să fie folosită pentru reţinerea altor informaţii. Metode de reprezentare a grafurilor a) Matricea de adiacenţă Cea mai cunoscută metodă de memorare a grafurilor neorientate este matricea de adiacenţă.

algoritmi de drum minim etc. ceea ce este mai puţin eficient decât consultarea unei valori logice în matricea de adiacenţă. lista de adiacenţă a lui j). c) Listele de vecini. putându-se memora astfel grafuri de dimensiuni mari. Într-un graf cu m muchii. cum ar fi de exemplu algoritmul Kruskal de aflare a arborelui parţial de cost minim în cazul grafurilor rare (cu număr mic de muchii). Este posibil să examinăm toţi vecinii unui vârf dat.) este obţinută numai folosind liste de vecini.2) reţine coloana pe care se găseşte următorul element din lista respectivă sau 0 dacă lista s-a terminat. spatiul folosit este gestionat dinamic. posibil. 2. respectiv m. este necesar ca muchia să plece din i). 64 .1) reţine un element din lista curentă. Pentru fiecare listă este suficient să păstrăm o singură santinelă (cea de început a listei). Prin liste de vecini (adiacenţă) se realizează ataşarea la fiecare vârf i a listei de vârfuri adiacente lui (pentru grafuri orientate. pentru a determina dacă două vârfuri i şi j sunt adiacente. introducerea vârfurilor făcându-se mereu la începutul listei (deoarece ordinea vârfurilor în listă nu contează). muchii şi puncte critice. pentru o anumită coloană i din T. dacă graful este orientat. trebuie să analizăm lista de adiacenţă a lui i (şi. a) Prima dintre ele foloseşte o matrice T cu 2 linii şi 2m coloane şi un vector C cu n elemente care reţine pentru fiecare nod indicele coloanei din T pe care este memorat primul element al listei nodului respectiv (sau 0 dacă vârful respectiv nu are vecini). Dacă numărul muchiilor în graf este mic. Există două modalităţi de implementare a listelor de vecini. în medie. Listele de vecini sunt cele mai recomandate în tratarea algoritmilor din teoria grafurilor din două motive principale: 1. conexitate. în mai puţin de n operaţii.Listele de muchii sunt folosite în cazul algoritmilor care prelucrează secvenţial muchiile. T(i. b) Cea de-a doua implementare foloseşte pentru fiecare nod o listă simplu înlănţuită memorată în heap. suma lungimilor listelor de adiacenţă este 2m. iar T(i. complexitatea optimă pentru majoritatea algoritmilor fundamentali din teoria grafurilor (parcurgeri. dacă graful este neorientat. această reprezentare este preferabilă din punct de vedere al memoriei necesare. Pe de altă parte. Apoi.

5 Implementarea acestei metode se 6 face folosind o stivă. dar există şi cazuri în care este recomandată 4 o implementare nerecursivă. parcurgerea să fie continuată cu primul vecin al nodului v nevizitat încă. O persoană care caută ceva într-un labirint şi aplică această tehnică are avantajul ca “următorul loc în care caută” este mereu foarte aproape. Parcurgerea vârfurilor în adâncime se 1 2 face în ordinea: 1 3 4 5 2 6 Cel mai cunoscut mod de imple3 mentare a parcurgerii DF se realizează cu ajutorul unei funcţii recursive. a) Parcurgerea DF (parcurgerea în adâncime) Parcurgerea DF (Depth First) presupune ca dintr-un anumit nod v. Aceasta este iniţia65 . Parcurgerea în adâncime a fost formulată cu mult timp în urmă ca o tehnică de explorare a unui labirint. ordine care să permită prelucrarea optimă a informaţiilor ataşate grafului.Exemplu: 8 7 5 2 6 0 1 3 4 0 1 2 3 4 5 6 7 8 2 6 6 4 5 3 5 7 2 8 Parcurgerea grafurilor Parcurgerea unui graf presupune examinarea în vederea prelucrării tuturor vârfurilor acelui graf într-o anumită ordine.

adică prin ataşarea la fiecare vârf a listei de vârfuri adiacente lui. ea depinde atât de alegerea vârfului iniţial. La fiecare pas. atunci numărul total al acestor testări este m. 66 . Parcurgerea în adâncime a unui graf nu este unică. testăm marcajul fiecărui vecin al său. când vizităm un vârf. Dacă reprezentăm graful prin liste de adiacenţă. dacă graful este orientat. Algoritmul recursiv: procedure DF(G) for fiecare v ∈ V do marca[v] ← nevizitat for fiecare v ∈ V do if marca[v] = nevizitat then ad(v) procedure ad(v) {varful v nu a fost vizitat} marca[v] ← vizitat for fiecare virf w adiacent lui v do if marca[w] = nevizitat then ad(w) Algoritmul iterativ: procedure iterad(v) S ← stiva vida marca[v] ← vizitat push(v.lizată cu un nod oarecare al grafului. S) pop(S) unde funcţia ftop returnează ultimul vârf inserat în stivă. În procedura ad. avem n apeluri ale procedurii ad. se ia primul vecin nevizitat al nodului din vârful stivei şi se adaugă în stivă dacă nu mai există se coboară în stivă. S) while S nu este vida do while exista un varf w adiacent lui ftop(S) astfel incat marca[w] = nevizitat do marca[w] ← vizitat push(w. cât şi de ordinea de vizitare a vârfurilor adiacente. Problemă: Cât timp este necesar pentru a parcurge un graf cu n vărfuri şi m muchii? Rezolvare: Deoarece fiecare vârf este vizitat exact o dată.

Parcurgerea în lăţime este folosită de obicei atunci când se explorează parţial anumite grafuri infinite. n)) = O(m+n). se obţine un timp de executare de O(n2). dacă graful este neorientat. se vizitează nodul aflat în vârful cozii şi se adaugă în coadă toţi vecinii nevizitaţi ai nodului respectiv. Algoritmul necesită un timp O(n) pentru apelurile procedurii ad şi un timp O(m) pentru inspectarea mărcilor. b) Parcurgerea BF (parcurgerea în lăţime) Parcurgerea BF (Breath First) presupune faptul că după vizitarea unui anumit nod v. apoi toate vârfurile nevizitate adiacente vârfurilor adiacente lui v etc. La fiecare pas. sunt parcurşi toţi vecinii nevizitaţi ai acestuia.şi 2m. unde i este un vecin nevizitat al nodului ic Pentru a efectua o parcurgere în laţime a unui graf (orientat sau neorientat). Dacă reprezentăm graful printr-o matrice de adiacenţă. C) 67 . Parcurgere_BF(nod start) Coada ← start Vizitat(start) ←adevărat cât timp coada nu este vidă ic ←nodul de la începutul cozii adaugă toti vecinii nevizitati ai lui ic în coadă Vizitat(i) ← adevărat. apoi toţi vecinii nevizitaţi ai acestora din urmă. Timpul de executare este O(max(m. procedure lat(v) C ← coada vida marca[v] ← vizitat insert-queue(v. sau când se caută cel mai scurt drum dintre două vârfuri. până la vizitarea tuturor nodurilor grafului. parcurgerea în lăţime nu este în mod natural recursivă. Implementarea acestei metode se face folosind o coadă. Aceasta este iniţializată cu un nod oarecare al grafului. îl marcăm şi vizităm apoi toate vârfurile nevizitate adiacente lui v. aplicăm următorul principiu: atunci când ajungem într-un vârf oarecare v nevizitat. Spre deosebire de parcurgerea în adâncime.

Notăm cu C mulţimea vârfurilor disponibile (candidaţii) şi cu S mulţimea vârfurilor deja selectate. C) Pentru compararea celor două metode apelăm procedurile iterad şi lat din procedura parcurgere(G) procedure parcurge(G) for fiecare v ← V do marca[v] ← nevizitat for fiecare v ← V do if marca[v] = nevizitat then {iterad sau lat} (v) Aplicaţia 2. un tablou D conţine lungimea celui mai scurt drum special către fiecare vârf al grafului. S conţine doar vârful sursă. toate vârfurile din graf sunt în S. Soluţia se va construi în tabloul D[2 . deci toate drumurile de la sursă către celelalte vârfuri sunt speciale şi valorile din D reprezintă soluţia problemei. cel mai scurt drum special către v va fi. În fiecare moment.6. unde X este mulţimea vârfurilor şi U este mulţimea muchiilor. Unul din vârfuri este desemnat ca vârf sursă. Vom folosi un algoritm greedy.. în timp ce mulţimea C conţine toate celelalte vârfuri. Când algoritmul se termină. La fiecare pas al algoritmului. Matricea M dă lungimea fiecarei muchii. Dijkstra (1959). S conţine acele vârfuri a căror distanţă minimă de la sursă este deja cunoscută. Problema este să determinăm lungimea celui mai scurt drum de la sursă către fiecare vârf din graf. datorat lui E. cu M[i.W.while C nu este vida do u ← delete-queue(C) for fiecare virf w adiacent lui u do if marca[w] = nevizitat then marca[w] ← vizitat insert-queue(w. j) nu există. j] = +∞. La început. Algoritmul este: S = {0} for i = 1 to n D[i] = M[1][i] 68 . cel mai scurt dintre toate drumurile către v. de asemenea. n].1: Algoritmul lui Dijkstra Fie G = (X. dacă muchia (i. După ce adăugăm un nou vârf v la S. iar în final S conţine toate vârfurile grafului. Fiecare muchie are o lungime nenegativă. La fiecare pas.U) un graf orientat. adăugam în S acel vârf din C a cărui distanţă de la sursă este cea mai mică.

h> #define FALSE 0 #define TRUE 1 #define MAXN 20 int setupDijkstra (int *nod_p.h> #include <string. int a[MAXN][MAXN]. i<*nod_p. int D[MAXN]. }while ((i < 0) || (i > 1)). doDijkstra(nod. do{ printf("Introduceti 0 pentru a specifica graful. int nod). a[2][4]=a[4][2]=1. int *startnod_p){ int i. j. return 0. j<*nod_p. if (i == 1){ *nod_p = 5.sau 1 pentru exemple "). int a[MAXN][MAXN]. int main(){ int nod. for (i=0. startnod. &startnod)) return 1.for i = 1 to n-2 caut cel mai mic D[v] pentru fiecare v ∉ S S = S ∪ {v} for toate vârfurile u ∉ S if (D[u] > D[v] + M[v][u]) then D[u] = D[v] + M[v][u] Implementare în C: #include <stdio. a[1][4]=a[4][1]=2. int a[MAXN][MAXN]. } int setupDijkstra (int *nod_p. if (setupDijkstra(&nod. i++) for (j=0. j++) a[i][j]=99. a[1][2]=a[2][1]=3. &i). a. void doDijkstra (int nod. startnod). int startnod). printf("Algoritmul lui Dijkstra\n"). a[3][4]=a[4][3]=4. a[0][3]=a[3][0]=2. a. a[0][1]=a[1][0]=1. int *startnod_p). scanf("%d". 69 . int a[MAXN][MAXN]. void traceinfo (int S[MAXN].

i+1). 'a'+i). . j++) if (scanf("%d". i<*nod_p. } return 0. int D[MAXN]. a[i][j]). j<*nod_p. } printf("Initializare\n"). &i) != 1) return 4. for (j=0. *nod_p). int startnod){ int S[MAXN]. *startnod_p = i-1. i++) {D[i] = a[startnod][i]. for (j=0. i++){ printf("Introduceti randul %d matricii: ". j<*nod_p. i++){ printf(" %c". if ( (i < 1) || (i > *nod_p) ) return 5. j.} }} 70 } else { printf("Enter number of nod (1-%d) ". for (i=1. } *startnod_p = 0. if (scanf("%d". j++) printf("%3d". for (i=0. for (i=0. i<*nod_p. i<nod.} void doDijkstra (int nod. int a[MAXN][MAXN]. mic. if (scanf("%d". int i. j<nod. j++){ if (!S[j]){ if (D[j] < mic){ mic = D[j]. for (i=0. if ( (*nod_p < 1) || (*nod_p > MAXN) ) return 2. S[startnod] = TRUE. /* initializare */ for (i=0. printf("\n").urmnod = j. D. for (j=0. printf("A Matrix: a b c d e\n"). urmnod. } printf("introduceti nodul (1-%d) ". traceinfo(S. nod). MAXN). i++){ urmnod = 999. i<nod. &a[i][j]) != 1) return 3. i<nod. i++) S[i] = FALSE. mic = 999. nod_p) != 1) return 1.

Această problemă este rezolvată de algoritmul Bellman-Ford. for (j=0. \ D[urmnod]+a[urmnod][j]). 71 . D[j]. în ordine crescătoare a distanţei faţă de aceasta. */ if (D[j] > D[urmnod] + a[urmnod][j]){ D[j] = D[urmnod] + a[urmnod][j].acum . j<nod. 'a'+j. int D[MAXN]. j++){ if (!S[j]){ /* printf("Compara D[%c]=%2d si D[%c]+M[%c][%c]=%2d. i<nod. 'a'+urmnod. */ } } traceinfo(S. 'a'+urmnod. printf("}\n"). printf(" S = {"). D[j]). for (i=0. Dacă graful conţine muchii de cost negativ. printf("adauga nodul %c to S\n". care în plus determină şi existenţa ciclurilor de cost negativ care pot fi atinse pornind din nodul sursă. } Aplicaţia 2.2: Algoritmul lui Bellman-Ford (determinarea drumurilor minime dintre un nod şi celelalte noduri într-un graf care poate să aibă cicluri negative). 'a'+urmnod. \ 'a'+j. ".6. printf(" D = "). algoritmul Dijkstra nu mai funcţionează corect. int nod){ int i. deoarece nu putem găsi . i<nod. */ } else /* printf("nu schimba\n"). // printf(" D[%c]=%2d.nodurile cele mai apropiate de sursă. 'a'+urmnod). } } void traceinfo(int S[MAXN]. ". /*printf("D[%c] schimba %2d\n". 'a'+j. 'a' + i). Ca şi în cazul algoritmului Dijkstra. for (i=0. S[urmnod] = TRUE. mic). nod). D. D[i]). i++) if (S[i]) printf("%c". printf("\n"). i++) printf("%3d".if (urmnod >= nod) return.

vom folosi vectorul D care reţine distanţa minimă găsită la un moment dat de la s la celelalte noduri. Algoritmul foloseste o coadă Q, care este iniţializată cu nodul s. La fiecare pas, algoritmul scoate un nod v din coadă şi găseşte toate nodurile w a căror distanţă de la sursă la acestea poate fi optimizată prin folosirea nodului v. Dacă nodul w nu se află deja în coadă, el este adăugat acesteia. Aceşti paşi se repetă până când coada devine vidă. Algoritmul utilizează tehnica de relaxare, procedând la descreşterea estimării d[v] a drumului minim de la sursa s la fiecare vârf v ∈V până când este obţinut costul adevărat δ(u,v) corespunzător unui drum minim. Algoritmul returnează adevarat dacă şi numai dacă nu conţine cicluri de cost negativ accesibile din sursă. Algoritmul este: BELLMAN-FORD(G,c,s) 1.INIT(G,s) 2. pentru i 1,|X[G]|-1 executa 3. pentru fiecare muchie (u,v) ∈U 4. RELAXEAZA(u,v,c) 5. pentru fiecare muchie (u,v) ∈U executa 6. daca d[v]>d[u]+c(u,v) 7. returneaza FALS 8. returneaza ADEVARAT Implementare în C: #include <stdio.h> #include <string.h> #define FALSE 0 #define TRUE 1 #define MAXN 26 #define INFINIT 999 int setupBellman(int *nod_p, int a[MAXN][MAXN], int *start_p); int doBellman(int nod, int a[MAXN][MAXN], int start); void traceinfo(int D[MAXN], int nod); int main(){ int nod, start; int a[MAXN][MAXN]; printf("Algoritmul lui Bellman-Ford\n"); if (setupBellman(&nod, a, &start)) return 1; if (doBellman(nod, a, start)){ printf(" Ciclu negativ\n"); return 2;} return 0;}
72

int setupBellman (int *nod_p, int a[MAXN][MAXN], int *start_p){ int i, j; do{ printf("Introduceti 0 pentru graf, or 1 pentru exemple "); scanf("%d", &i); }while ((i < 0) || (i > 1)); if (i == 1){ *nod_p = 5; for (i=0; i<*nod_p; i++) for (j=0; j<*nod_p; j++) a[i][j]=99; a[0][1]=a[1][0]=1; a[1][2]=a[2][1]=3; a[0][3]=a[3][0]=2; a[3][4]=a[4][3]=4; a[1][4]=a[4][1]=2; a[2][4]=a[4][2]=1; printf("A Matrix: a b c d e\n"); for (i=0; i<*nod_p; i++){ printf(" %c", 'a'+i); for (j=0; j<*nod_p; j++) printf("%3d", a[i][j]); printf("\n"); } *start_p = 0; } else{ printf("Introduceti nr. noduri (1-%d) ", MAXN); if (scanf("%d", nod_p) != 1) return 1; if ( (*nod_p < 1) || (*nod_p > MAXN) ) return 2; for (i=0; i<*nod_p; i++){ printf("Introduceti randul %d al matricii: ", i+1); for (j=0; j<*nod_p; j++) if (scanf("%d", &a[i][j]) != 1) return 3; } printf("Introduceti nodul de start (1-%d) ", *nod_p); if (scanf("%d", &i) != 1) return 4; if ( (i < 1) || (i > *nod_p) ) return 5; *start_p = i-1; } return 0; } int doBellman(int nod, int a[MAXN][MAXN], int start){ int D[MAXN]; int i, u, v; /* initializare */
73

/*

for (i=0; i<nod; i++){ if (i == start) D[i] = 0; else D[i] = INFINIT; } printf("Initializared\n"); traceinfo(D, nod); for (i=1; i<nod; i++){ for (u=0; u<nod; u++){ for (v=0; v<nod; v++){ if (a[u][v] < 99){

printf("Compara D[%c]=%3d si D[%c]+M[%c][%c]=%3d, ",\ 'a'+v, D[v], 'a'+u, 'a'+u, 'a'+v, D[u]+a[u][v]); */ if (D[v] > D[u] + a[u][v]){ D[v] = D[u] + a[u][v]; printf("D[%c] schimba to %2d\n", 'a'+v, D[v]); } else printf("nu schimba\n"); } } } traceinfo(D, nod); } for (u=0; u<nod; u++){ for (v=0; v<nod; v++){ if (a[u][v] < 99){ /*printf("Compara D[%c]=%3d and D[%c]+M[%c][%c]=%3d, ",\ 'a'+v, D[v], 'a'+u, 'a'+u, 'a'+v, D[u]+a[u][v]); */ if (D[v] > D[u] + a[u][v]) return 1; else printf("nu exista ciclu negativ\n"); } } } return 0; } void traceinfo(int D[MAXN], int nod){ int i; printf(" D = "); for (i=0; i<nod; i++) printf("%4d", D[i]); printf("\n");}
74

j]). procedure df(X:integer)..100. k=1. for i:=1 to n do if viz[i]=0 then begin df(i). reset(f). var i:byte. readln(f).Probleme rezolvate R2.. for i:=1 to n do if (a[x.n).a[i. ' '). procedure citire. end. viz:array[1.gasit. begin write(x.i.writeln end.1.txt').s[10]. end.n. begin assign(f. begin citire. Exerciţiu: Implementaţi în lumbajul C aplicaţia de mai sus folosind funcţia Df (iterativă) de mai jos.j:integer. f:text.'matrice. for i:=1 to n do begin for j:=1 to n do read(f.100] of integer. void df(int x){ int i. viz[x]:=1. Să se afişeze componentele conexe folosind parcurgerea DF a grafului.6.100] of integer.1. Graful este reprezentat prin matricea de adiacenţă citită din fişier TEXT.k.y. end. Rezolvare: Implementarea Pascal folosind parcurgerea DF recursivă: var a:array[1.i]=1) and (viz[i]=0) then df(i). 75 . end. readln(f.. for i:=1 to n do viz[i]:=0.

n. p:=1. u:=1.n). Rezolvare: Implementare în limbajul Pascal: Var a:array[1.txt'). write('Dati nodul de plecare '). c[1]:=v. readln(v).x). for i:=1 to n do begin for j:=1 to n do read(f. } if (!gasit) k--. gasit=1.x:integer. begin assign(f.. //vecin nevizitat viz[i]=1.s[1]=x.2. end.i. reset(f). Să se parcurgă un graf reprezentat prin matricea sa de adiacenţă folosind parcurgerea BF.j.c:array[-2. f:text. procedure bf(v:integer). begin viz[v]:=1.i++) if (viz[i]==0&&a[y][i]==1) { printf("%d ".write(v..'matrice. } } R2.a[i.u..100] of integer.6.viz[x]=1. for(i=1.i<=n. end. s[++k]=i.gasit=0.p. break.' ').100] of integer.j]). readln(f.i).1. 76 . while (k>=1) /*cat timp stiva este nevida */ { y=s[k]. viz. procedure citire.100.printf("%d ".v. readln(f).

const nmax=100. end.k.j. end.' ').j]=0 then a[i. bf(v) end. p:=p+1. m:marcaj. end. readln(i. for i:=1 to n do viz[i]:=0.j]. readln(n). Exerciţiu: Să se implementeze aplicaţia de mai sus în limbajul C.j) :'). unde a este matricea drumurilor . k:=1. var a:graf.j]=a[j.n:integer. for i:=1 to n do if not m[i] then begin 77 .nmax. modificare:boolean. begin write('Dati nr de noduri: '). type graf = array[1.j)..x]=1) then begin write(i. u:=u+1.nmax] of boolean.. Implementare Pascal: program tare_conexe. for k:=1 to n do for i:=1 to n do for j:=1 to n do if a[i.nmax] of byte.1. for i:=1 to n do if (viz[i]=0) and (a[i. writeln('dati arcele grafului (i. end. readln(i.j]:=1. c[u]:=i.j]:=a[i. Rezolvare: Componenta tare conexă care va conţine vârful i va fi dată de subgraful indus de multimea nodurilor j pentru care a[i. R2. while i*j<>0 do begin a[i. writeln('0 0 pentru sfarsit ').3. viz[i]:=1..j).i]=1.6.k]*a[k. begin citire. Să se determine componentele tari conexe ale unui graf orientat. marcaj = array[1.while p<=u do begin x:=c[p]. i.

k++) for(i=1. } } 78 .viz[10].i++) for(j=1.a[x][y]=1.x.&n).':'.j++)a[i][j]=0.i++) for(j=1.k.i. printf("n=").&y).i++)m[i]=0. /*citirea arcelor si construirea matricei de adiacenta */ for(i=1. Implementare în limbajul C: #include <stdio.k.m[10].k<=n.j<=n.scanf("%d". k=1.j).i<=n. m[j]:=true.componenta tare conexa */ printf("componenta tare conexa %d: %d ". writeln.i.' '). printf("\n").i<=m. a[10][10]. m[j]=1.end. //se construieste matricea drumurilor for (k=1.h> int n.i++) { scanf("%d %d".i<=n.i++) if(!m[i]) { /* daca varful i nu a fost introdus intr.j]<>0)and (a[j.j++) if (j!=i&&a[i][j]==1&&a[j][i]==1){ printf("%d ".i]<>0) then begin write(j.j<=n. write('componenta tare conexa '.i<=n. end.y.j++) if(a[i][j]==0) a[i][j]=a[i][k]&&a[k][j]. printf("m="). } k++. citire().i<=n. for(i=1.scanf("%d".} } void main(){ int k. for j:=1 to n do if (j<>i) and (a[i.' '). for(i=1.j.j<=n.&x.&m).i).i. end. for (j=1.j. inc(k). void citire(){ int m. for (i=1.

.i. Rezolvare: Implementarea Pascal este: uses crt. end. var x.i. readln(y).x]:=1. a[y. for i:=1 to m1 do begin write('Dati primul capat al muchiei '.m.R2. readln(n).j]:=0. n. write('Dati numarul de varfuri'). b[y. readln(m).6.n1.i. write('Dati numarul de varfuri').x]:=1 end end. write('Dati numarul de muchii').m1. write('Dati numarul de muchii')..' : '). readln(y).b:mat. write('Dati al doilea capat al muchiei '. 79 . type mat=array[1.y.readln(n1).i.1. end. var a. begin writeln(' MARTICEA 1'). var x.4.100.y. begin WRITELN(' MATRICEA 2').y]:=1.i. procedure creare1.y]:=1. b[x.' : ').j:integer. procedure creare. for i:=1 to m do begin write('Dati primul capat al muchiei '. readln(x).i.i.j]:=0.' : ').j:integer. for i:=1 to n do for j:=1 to n do a[i. readln(x). write('Dati al doilea capat al muchiei '. for i:=1 to n1 do for j:=1 to n1 do b[i. a[x.j:integer.100] of integer.readln(m1).' : '). Dându-se două grafuri reprezentate prin matricea de adiacenţă să se precizeze dacă cel de-al doilea graf este graf parţial sau subgraf al primului graf.

k]+c[k. Rezolvare: Se foloseşte algoritmul lui ROY-FLOYD.j]=min(c[i.') else writeln(' B e subgraf al lui A. Se porneşte de la matricea costurilor C.100.').') else writeln(' B e graf partial al lui A. n. if s=false then writeln(' B nu e subgraf al lui A.n execută pentru j=1. v:array[1.j.j]) Simultan cu determinarea lungimilor minime ale drumurilor pot fi reţinute drumurile folosind un tablou d.i.100] of longint. var s:boolean.1.'). end. unde d[i. graf_p. for i:=1 to n1 do for j:=1 to n1 do if (a[i.nr:integer.procedure subgraf.if n<> n1 then g:=false.n execută c[i.if n1>n then s:=false. end.j]=0) then s:=false..n execută pentru i=1. Determinarea drumurilor minime între oricare două noduri.j].c[i.j] reprezintă mulţimea predesesorilor lui j pentru drumul minim de la i la j.5..m.100] of set of 1.100..1. begin s:=true. procedure graf_p.creare1..k.100]of integer. begin g:=true. x. var g:boolean. Exerciţiu: Să se implementeze aplicaţia de mai sus în limbajul C. begin clrscr. pentru k=1. creare. end.j]=1) and (b[i.y:integer.. if g=false then writeln(' B nu e graf partial al lui A.j]=0) and (b[i. for i:=1 to n do for j:=1 to n do if (a[i.subgraf. R2. Implementare Pascal: Var c:array[1.6.. 80 . d:array[1.10.j]=1) then g:=false.

end.j]+d[k. begin write('nr. writeln. d[i.j]:=[]. begin citire.k]+c[k. {determina multimea predecesorilor.j]:=d[i.x. drum(i. var cost. readln(x. end.readln(n).k]+c[k. for i:=1 to m do begin write('Dati capetele arcului si costul ').cost).j] then d[i.j:integer).j]>c[i. initializeaza multimea D} begin for i:=1 to n do for j:=1 to n do if (i<>j) and (c[i. de muchii').j] then begin c[i.k]+c[k. de noduri'). c[x. end.y:integer.j] then begin inc(nr). begin if i<>j then for k:=1 to n do if k in d[i. 81 .j]<maxint) then d[i.j]:=maxint else c[i.j]:=d[k.j]:=0. write('nr.j]:=[i] else d[i.procedure citire.y. procedure drum(i. ' ').initializare.j]. end else begin for k:=nr downto 1 do write(v[k]. for i:=1 to n do for j:=1 to n do if i<>j then c[i. v[nr]:=k.j] end else if c[i.j]=c[i.k). end.j]:=c[i. procedure initializare. end.j].y]:=cost. {reconstituirea drumului} var k:integer. for k:=1 to n do for i:=1 to n do for j:=1 to n do if c[i. dec(nr).readln(m).

c[x.y) end end Exerciţiu: Să se implementeze algoritmul Roy-Floyd în limbajul C.while t^.y].y). Implementare Pascal: type lista=^nod.6. nod= record inf:integer.urm.urm:=q.q:lista. i.end. t^.q^. var bl:array[1. if c[x.y]=maxint then write('nu exista') else begin nr:=1. end. f:text.x:integer). R2.'la '. procedure adaugare (var p:lista. if p=nil then p:=q else begin t:=p. var t.v[1]:=y. begin new(q). urm:lista end.y). complet:boolean. for x:=1 to n do for y:=1 to n do begin writeln('drum de la '. writeln end.n.urm:=nil. end.100] of lista. Rezolvare: Se foloseşte un tablou de liste unde bl[i] reprezintă lista vecinilor lui i. ' drumurile minime=' ).urm<>nil do t:=t^.x:integer. for i:= 1 to n do begin for j:=1 to n do write(c[i. drum(x. 82 . writeln('costul minim= '.x. readln(x. Să se verifice dacă un graf reprezentat dinamic este conex sau complet.j]:4).6. write('Dati doua noduri')..q^.inf:=x.

inf]=0 then begin new(q). while t<> nil do begin if viz[t^.urm:=nil. numarare:=nr end. t:=t^. while t<> nil do begin write(t^.inf. viz:array [1.100] of integer. end. 83 .st:=q.urm end.write(i.urm end. gasit:=false. var q.q^.t:=p.st:lista.' '). viz[t^. write(t^. t:=t^.urm. end.urm:=nil. end. st:=st^.inf. function numarare( p:lista):integer.urm. for j:=1 to n do if viz[j]=0 then conex:=false.viz[i]:=1. conex. if not gasit then begin t:=st.t. q^. var nr:integer.inf. while t<>nil do begin nr:=nr+1.urm:=st. st:=q.gasit:boolean. begin nr:=0. procedure df(i:integer). q^.inf. begin t:=p. q^.' '). end.procedure listare(p:lista).inf:=i.new(q).inf]:=1. dispose(t) end.. end. writeln. q^. t:lista. t:=t^. conex:=true. break. if conex then write('conex') else write('nu este conex'). while st<>nil do begin x:=st^. j:integer. gasit:=true. var t:lista. t:=bl[x].' '). begin for j:=1 to n do viz[j]:=0.inf:=t^.

'in.6. adaugare(bl[i]. Rezolvare: Un graf este aciclic dacă este fără cicluri. Implementare Pascal: Var f:text. writeln. nume:string.i.k:integer. df(1). reset(f).1000]of integer. assign(f.7. procedure ciclic.reset(f). readln(f. să se verifice dacă este aciclic. for i:=1 to n do if numarare(bl[i])<>n-1 then complet:=false.n). if complet then write('complet') else write ('incomplet'). R2.x). while not seekeoln(f) do begin readln(f. Fiind dat un graf. for i:=1 to n do a[i]:=i.nume).begin assign(f. readln(f). for i:=1 to n do begin while not eoln(f) do begin read(f. end. n:integer. var i. end..txt'). readln(f. dacă nu sunt în aceeaşi componentă conexă toate nodurile care sunt în aceeaşi componentă cu extremitatea a doua trec în componenta conexă a extremităţii 1.j. Se ia fiecare muchie şi dacă extremităţile sunt în aceeaşi componentă conexă atunci adăugând aceea muchie se formează ciclu. begin writeln('Care este numele fisierului de intrare ?').n). Presupunem că fiecare nod face parte dintr-o componentă conexă.x) end. Exerciţiu: Să se implementeze aplicaţia de mai sus în limbajul c. readln(nume). a:array[1. 84 .j). complet:=true.

halt.' nu contine cicluri').h> #include <iostream.txt". if a[i]=a[j] then begin writeln('Graful din fisierul '. close(f). } 85 . Implementare C: #include <stdlib. k<=n.&j). k++){ if (a[k]==a[j]) a[k]=a[i]. begin ciclic end.end.k. end. writeln('Graful din fisierul '. void ciclic(){ int i. fclose(f). close(f).h> #include <conio.h> #include <stdio. ciclic()."%d". exit(1).h> FILE *f.i++)a[i]=i.nume.clrscr().a[10]. fscanf(f. } cout<<"nu contine cicluri".&n).nume. } void main(void){ f=fopen("in.&i. for(i=1. } for (k=1.j."r"). fscanf(f. end.i<=n."%d %d". for k:=1 to n do if a[k]=a[j] then a[k]:=a[i].' contine cel putin un ciclu'). if (a[i]==a[j]) { cout<<"contine ciclu". int n.

begin assign(f.j. i:=i+1 end. writeln('dati matricea de adiacenta:').i.txt')..k:integer. c[1]:=1.9.1.p:integer. end.20. gasit:=true.j]=1 then begin for p:=1 to k do if c[p]=j then gasit:=false. begin write('dati numarul de noduri.20] of integer.. reset(f).20] of integer.j]).'c:\lucru\graf. k:=1. {vectorul unde pastram nodurile accesibile} n. {matricea de adiacenta} c: array[1. R2. f:text. i:=1.1. se cere să se determine toate nodurile accesibile din acest nod.').. Rezolvare: Implementarea Pascal: var i.6. Rezolvare: Implementare Pascal: var a: array[1. a:array[1.n)..n. gasit:boolean..50] of integer.considerat ca nodul nr.'. 1.k.readln(n).50. Exerciţiu:Să se implementeze aplicaţia de mai sus în limbajul C. if k=n then writeln('Toate nodurile sunt accesibile. c[k]:=j end end.6.R2.') else for i:=1 to k do write(c[i].8. while i<=k do begin for j:=1 to n do if a[i. for i:=1 to n do for j:=1 to n do read(a[i. Se dă un graf şi un nod .j. Determinarea ciclului de lungime 3 dintr-un graf. n='). 86 . if gasit then begin k:=k+1. read(f.

a vârfurilor numerotate cu n+1. for i:=1 to n-2 do for j:=i+1 to n-1 do for k:=j+1 to n do if (a[i. Un arbore binar cu n vârfuri şi de înălţime i este complet.i]:=1 end.j]:=0. while not eof(f) do begin readln(f. Dacă fiecare vârf al unui arbore cu rădacină are până la n fii. Într-un arbore binar. arborele respectiv este n-ar. Arbori Fie G un graf orientat.j. T[2k+1-1] (cu posibila excepţie a nivelului 0. 2i+1-1. …. ca şi în cazul listelor înlănţuite. 2. de la stânga la dreapta.j]:=1. adresa celui mai vârstnic fiu şi adresa următorului frate. se numeste arbore plin. dacă este cazul. Acest tip de arbore se poate reprezenta secvenţial folosind un tablou T. dacă există în G un vârf r din care oricare alt vârf poate fi ajuns printr-un drum unic. Fiecare vârf va fi memorat în trei locaţii diferite.i]=1) then writeln(i. Un arbore binar este un arbore în care fiecare vârf are cel mult doi descendenţi. Reprezentarea unui arbore cu rădăcină se poate face prin adrese.i. dacă se cunoaşte de la început numărul maxim de vârfuri.' '. prin eliminarea.7. a[i. iar dacă are exact 2i+1-1 varfuri. nivelul unui vârf este înălţimea arborelui minus adâncimea acestui vârf. for i:=1 to n do for j:=1 to n do a[i. Vârfurile unui arbore plin se numerotează în ordinea adâncimii.k]=1) and (a[k.j). Înălţimea arborelui este înalţimea rădăcinii. atunci implementarea arborilor cu rădăcina se poate face prin tablouri paralele.k). n+2. G este un arbore cu radacina r. dacă se obţine din arborele binar plin de înălţime i. făcându-se distincţie între descendentul stâng şi descendentul drept al fiecărui vârf. T[2k+1]. 87 . numărul maxim de vârfuri de adâncime k este 2k. a[j. care poate fi incomplet). punând vârfurile de adâncime k.' '. Un arbore binar de înălţime i are cel mult 2i+1-1 vârfuri. înălţimea unui vârf este lungimea celui mai lung drum dintre acest vârf şi un vârf terminal. Păstrând analogia cu listele înlănţuite. în poziţiile T[2k]. Adâncimea unui vârf este lungimea drumului dintre rădăcina şi acest vârf. ….j]=1) and (a[j.end. reprezentând informaţia propriu-zisă a vârfului (valoarea vârfului).

end. struct nod *st.1) 88 .0.8.Reprezentarea arborilor binari Reprezentarea prin paranteze: se începe cu rădăcina arborelui.-1. 9(.1.dr:arbore.(4(3. Reprezentarea cu doi vectori DESC şi TATA: În vectorul DESC. 3.1. Pentru arborele de mai sus.4.8.7.0. 0.10))) Reprezentarea standard: În care pentru fiecare vârf i este precizat descendentul său stâng ST(i) descendentul său drept DR(i) = i informaţia asociată v`rfului INF(i): ♦ static:ST şi DR sunt două tablouri ST=(0.0 se precizează pentru fiecare nod ce fel de descendent este el pentru părintele său iar în vectorul TATA se indică pentru fiecare vârf. 4.1.6. Dacă lipseşte un descendent subexpresia corespunzătoare este cuvântul vid.6. struct nod *dr. typedef struct nod{ int inf. reprezentarea este: 6(2(1. 0) DR=(0. 0.1. 5. iar fiecare vârf care are descendenţi este urmat de expresiile ataşate subarborilor care au ca rădăcină descendenţii vârfului. despărţite prin virgulă şi cuprinse între paranteze. 0. 1.0) rad=6 ♦ dinamic: type arbore=^nod.-1.5)). nodul părinte. si se declara arbore *rad. 0. nod=record inf:integer. }arbore.2.4. având valori –1. 0. Pentru exemplul de mai sus: TATA=(2.-1.10. 0. st. 2. 1. 9. 0. 8. 8(7.9) DESC=(-1.

creare(p^. să se afişeze drumurile de la rădăcină la frunze şi să se calculeze adâncimea arborelui creat.. Aplicaţia 2.' '). {Procedura creare arbore binar} procedure creare(var p:arbore). se traversează subarborele drept în preordine. end.7. preordine(p^.dr). nod =record st. begin if p<>nil then begin write(p^. end. type arbore=^nod.prin preordine} procedure preordine(p:arbore). 89 . write('Dati dreapta lui '.x. var p:arbore.a:array[1.1. end. se traversează subarborele drept în postordine. se traversează subarborele stâng în preordine. se traversează rădăcina.x).dr:arbore. begin read(x). {Procedura parcurgere arbore binar . preordine(p^.100] of integer.max.Parcurgerea arborilor binari ♦ preordine:se vizitează rădăcina.st). creare(p^.inf:=x.x). inf:integer end. ♦ inordine: se traversează subarborele stâng în inordine.k. ♦ postordine: se traversează subarborele stâng în postordine. Să se creeze un arbore binar şi apoi să se parcurgă în preordine. var x:integer. să se afişeze cheile de pe un anumit nivel dat. write('Dati stanga lui '.z:integer. end. Rezolvare: Implementare Pascal: program arb_binar. se traversează subarborele drept în inordine.dr). să se caute un nod în arbore.inf. p^. se vizitează rădăcina. if x=0 then p:=nil else begin new(p).st).y.

end.st.k. adancime(p^. drum_frunze(p^.k:integer).x).' '). begin if p<>nil then begin if k=x then write(p^. drum_frunze(p^.x:integer).inf.max).st.dr. begin if (p^. nivel(p^. end.inf.inf then cautare:=true else cautare:= cautare(p^.st.x). begin if p=nil then cautare:=false else if x=p^.k+1. 90 .k+1. writeln end else if p<>nil then begin a[k]:=p^. for i:=1 to k do write(a[i].{Cautarea unui nod din arbore} function cautare(p:arbore. {Afisarea numarului maxim de nivele} procedure adancime(p:arbore.dr. end.x) or cautare(p^. end.dr.k+1.k+1.max). nivel(p^. {Afisarea tuturor cheilor de pe nivelul dat} procedure nivel(p:arbore. begin if p<>nil then begin if k>max then max:=k.k:integer.st=nil)and(p^.dr.dr=nil) then begin a[k]:=p^.k+1).' ').k+1). var i:integer.inf. adancime(p^.st. var max:integer). end. end end. x:integer):boolean.x). {Drumurile de la radacina la frunze} procedure drum_frunze(p:arbore.

0.arbore *p.h> #include <alloc. if (x==0) return NULL. cout<<"inf dreapta a lui"<<x. p->dr=creare(). {Pentru procedura adancime} adancime(p. p->st=creare(). cout<<"inf st. (p)->inf=x. } return p.p->inf).y). preordine(p). a lui"<<x. arbore *rad.h> typedef struct nod{ int inf. preordine(p->st). cout<<"inf".read(y). writeln(cautare(p. preordine(p->dr).nivel(p. {Pentru procedura cautare} read(x). {Pentru procedura drum_frunze} drum_frunze(p.begin creare(p).1).x)).h> #include <iostream. } void preordine(arbore *p){ if (p){ printf("%d ". writeln('Numarul de nivele este: '.0. int a[10]. *dr. }arbore.h> #include <conio.max). arbore *creare(){ int x. struct nod *st. else { (p)=(arbore*) malloc(sizeof(arbore)). } } 91 .max). end. Implementare în C++ : #include <stdio. {Pentru procedura nivel} write('Nivelul= '). cin>>x. max=0.

p->inf).k+1).p->inf).i++) printf("%d ". printf("%d". drum_frunze(p->st. postordine(p->dr).int k){ int i.k+1). printf("%d". nivel(p->dr.x). }} 92 . } } void postordine(arbore *p){ if (p){ postordine(p->st). adancime(p->dr. } } void drum_frunze(arbore*p. int k. } else return 0.printf("\n"). for (i=1.adancime(p->st. } else{ if(p) { a[k]=p->inf.x)||cautare(p->dr. nivel(p->st. if ((p->st)&&(p->dr)) { a[k]=p->inf. } } } void adancime(arbore *p. drum_frunze(p->dr.void inordine(arbore *p){ if (p){ inordine(p->st).a[i]). int x){ if(p){ if (p->inf==x) return 1. } void nivel(arbore*p. } } int cautare(arbore *p.k+1).k+1. int k){ if (p) { if (k>max) max=k.k+1) .i<=k.x).k+1.p->inf). return cautare(p->st.int x){ if(p){ if (k==x) printf("%d ". inordine(p->dr).x).

scanf("%d".dr:arbore end.x). În arborele binar de căutare informaţia din noduri este unică. se reia pentru subarborele din stânga. Rezolvare: Implementare Pascal: type arbore=^nod. Crearea se realizează adăugând în arbore rând pe rând câte un nod corespunzător fiecărei informaţii. Dacă este mai mare.0). st.void main(){ int x.1).2. cout<<"drumuri:".x:integer. rad=creare().drum_frunze(rad. if (cautare(rad. Căutarea se realizează astfel: se caută în nodul curent. nod = record inf:integer. } Arbori binari de căutare Arborele binar de căutare este un arbore binar în care pentru orice nod. cout<<"nivelul". preordine(rad). var p:arbore. altfel în subarborele stâng. iar în caz de egalitate se afişează eroare.nivel(rad. cout<<"nodurile de pe nivelul "<<x<<":". astfel dacă informaţia este mai mare decât informaţia din nodul curent.max). Program pentru crearea şi exploatarea unui arbore binar de căutare. se reia procesul pentru subarborele din dreapta. algoritmul se încheie. Prin parcurgerea în inordine a arborelui de căutare se obţine în ordine crescătoare valorile din câmpurile cheie.x)) printf("exista").else printf("nu exista"). Adăugarea unu nod: ♦ dacă arborele nu are nici un nod se crează rădăcina. dacă este mai mică. cheia din succesorul său stâng este mai mică decât cheia din nod.cin>>x. dacă informaţia s-a găsit. &x). Aplicaţia 2. iar cheia din succesorul său drept este mai mare decât cheia din nod. printf("inf cautata:"). 93 .0. printf("adancimea=%d".7. ♦ dacă arborele există se compară informaţia nodului nou cu cea din nodul curent. se caută în subarborele drept al acestuia. adancime(rad.

procedure srd(p:arbore). q^.inf:=x.x) else inserare(p^. q^.dr<>nil do t:=t^. srd(p).dr=nil then begin t:=p. t^.dr.dr:=nil. p:=p^.inf:=t^.st.inf<x then inserare(p^. 94 .p:=p^.procedure inserare(var p:arbore. while x<>0 do begin inserare(p.dr).st.dr.x) else if p^.x:integer). end. while t^. q^.dr:=nil end end. var t:arbore. dispose(t^.dr) end end.stergere(p.inf>x then stergere(p^.st. var q:arbore.srd(p). if p=nil then p:=q else if p^.x). begin new(q).dr.dr^. begin if p<>nil then begin srd(p^.st.inf=x then write('Exista') else if p^. end else begin t:=p^.inf.x).inf<x then stergere(p^.st=nil then begin t:=p. begin if p=nil then write('nu exista') else if p^. dispose(t) end else if p^.read(x).x) end.x) else if p^. write(p^.inf.dr^. read(x) end.dispose(t).st). p^. begin read(x). srd(p^.dr. procedure stergere(var p:arbore.' ').st:=nil.x:integer).

cauta(p.p=p->st. arbore *rad.x). inordine(p->dr).*dr. else if (p->inf<x) { q=p.}arbore. printf("%d".p=p->st. void adaug(arbore* &p. int x){ if (p==NULL) return NULL. for (i=1.x). cout <<"n=". else if (p->inf<x) adaug(p->dr.cauta(p. } else return p. } void creare(arbore* &p){ int x.n.cin>>x.x). else cout <<"informatia exista". } } void inordine(arbore *p){ if (p){ inordine(p->st).h> typedef struct nod {int inf.h> #include<stdio.i<=n. } 95 .i.Implementare C++: #include<iostream. p->inf=x.x). arbore *q.p->inf). nod *st. } else if (p->inf>x){ q=p. } } arbore *cauta(arbore*p.h> #include<conio. adaug(p.int x){ if (p==NULL){ p=new nod.cin>>n. p->st=p->dr=NULL. } else if (p->inf>x) adaug(p->st.i++){ cout<<"inf".x).

} } 96 . } else { q->st=p->dr. delete t. q1->inf=q1->st->inf.void sterge(arbore *&r.*q1. q1=q1->st.int x){ arbore *t. } else if (t->dr==t->st){ if (t->inf<q->inf) q->st=NULL.*p. else q->st=t->st. } while (q1->st&&q1->inf<q1->st->inf){ a=q1->inf. q1->st->inf=a. else q->dr=t->dr. getch(). if(t==NULL){ cout<<"informatia nu se gaseste". } else if (t->st==NULL&&t->dr){ if(q->inf>t->inf) q->st=t->dr. if (p->dr==p->st){ q->st=NULL. t->inf=p->inf. t=cauta(r. while (p->st!=NULL){q=p. delete t. delete p. } else if (t->st==NULL&&t->st){ if (q->inf<t->inf) q->dr=t->st. delete t. delete p.} } q1=t.x). int a. } else { p=t.p=p->st.

inf.' ').st). p3(p^. arbore *rad=0.dr) else p4:=1 end. function p4(p:arbore):longint. if p^.2). } Probleme rezolvate în limbajul Pascal R2.dr) end end. end. inordine(rad). creare(rad). Să se scrie un subprogram pentru aflarea produsului cheilor pozitive dintr-un arborele binar.inf<0 then nr1:=nr1+1. p2(p^.inf >0 then p4:=p^. Să se scrie un subprogram pentru afişarea numărului cheilor negative şi pozitive dintr-un arbore binar.7. begin if p<>nil then begin if p^. sterge(rad.st).void main(){ int x. p2(p^. Să se scrie un subprogram pentru afişarea cheilor impare dintr-un arborele binar. if p^.7. procedure p2(p:arbore).3. R2.st)*p4(p^.st)*p4(p^.inf>=0 then nr2:=nr2+1.dr). begin if p<>nil then if p^.7.2. end.dr) else p4:=p4(p^. 97 . R2. procedure p3(p:arbore).inf*p4(p^.inf mod 2 =1 then write(p^. begin if p<>nil then begin p3(p^.1.

Fie G = (X.st<>nil) and (p^.7. procedure p6(p:arbore). aceeaşi matrice a drumurilor şi având un număr minim de arce (se pot scoate.U) un graf orientat cu n vârfuri.7. Fie G = (X.' ').st=nil) and (p^.inf. R2.st.U) un graf orientat şi fară circuite. Să se scrie un subprogram pentru afişarea nodurilor care au un succesor dintr-un arbore binar.dr. begin if p<>nil then begin if ((p^. Să se scrie un subprogram pentru aflarea numărului de frunze dintr-un arborele binar .dr.dr) end end. p6(p^. Să se determine o renumerotare a vârfurilor sale astfel încat dacă (u. atunci numărul de ordine al lui u este mai mic decât numărul de ordine al lui v (sortare topologică). function p7(p:arbore.7.k+1)+p7(p^.5. Se dă un graf orientat cu n noduri.st).st. Să se verifice dacă există un nod având gradul interior n-1 şi gradul exterior 0. begin if p<>nil then if k=l then p7:=1+p7(p^. 2. p6(p^. 3. introduce noi arce)..6.k+1) else p7:=p7(p^.k:integer):integer.k+1)+p7(p^.v)∈U. Să se determine un alt graf având aceleaşi vârfuri.k+1) else p7:=0 end.dr<>nil)) or ((p^. 98 . begin if p=nil then p5:=0 else if (p^.R2.st)+p5(p^.dr=nil) then p5:=1 else p5:=p5(p^.dr) end. Probleme propuse: 1. R2.st=nil) and (p^.4.dr=nil)) then write(p^. function p5(p:arbore):integer. Să se scrie un subprogram pentru aflarea numărului de noduri de pe un nivel dat dintr-un arbore binar.

Se numeşte diametrul unui graf. 9. un ciclu care conţine două noduri date. poate să-i aşeze în aşa fel pe cavaleri la o masa rotundă încât nici unul dintre ei să nu stea alături de vreun duşman. Fie G=(X.j]=1 daca i cunoaste pe j =i 0 dacă i nu cunoaşte pe j). 99 . unde l[i] este lungimea drumului maxim care are ca extremitate iniţială vârful i. notat d(G). 6. 5. La curtea regelui Artur s-au adunat 2n cavaleri şi fiecare din ei are printre cei prezenţi cel mult n-1 duşmani. Să se calculeze diametrul grafului. Un graf turneu este un graf orientat cu proprietatea că între oricare două vârfuri distincte există un arc şi numai unul. dar având sens opus. 8. Soluţia nu este unică.k. graful care are aceeaşi mulţime de noduri. fie intercalat în listă. Dându-se G prin matricea de adiacenţă sau prin liste de vecini.U) un graf conex cu n noduri. Să se determine. consilierul lui Artur. Să se determine. Să se determine eficient cel mai mic k astfel încât ştergând nodurile etichetate cu 1. Fiecare din vârfurile următoare se adaugă la drumul creat anterior fie în faţă. într-un graf turneu. Indicaţie: Se asociază problemei date un graf orientat cu n noduri şi se construieşte matricea de adiacenţă (a[i. Numim transpusul unui graf G = (X.2. să se construiască o listă care să cuprindă toţi jucătorii astfel încat doi jucători i. j sunt alături dacă jucătorul i la învins pe jucătorul j. în această ordine să rezulte un graf ale cărui componente conexe au toate cel mult n/2 noduri.U) un graf ponderat. Ştiind că nu există jocuri egale.. Relaţia “x cunoaşte pe y” nu este în mod normal nici simetrică. La un turneu participă n jucători. 10. Pentru fiecare persoană neataşată la un moment dat unui grup se va construi grupul din care face parte aceasta. dar nu conţine un al treilea nod. 11. un drum elementar care trece prin toate vârfurile.. Să se formeze grupuri în care fiecare persoană să cunoască toate celelalte persoane din grup (o persoană aparţine unui singur grup). Indicaţie: Se adaugă arcul format din nodurile 1 şi 2 într-o listă liniară. într-un graf conex. Find date n persoane în care fiecare persoană se cunoaşte pe sine şi eventual alte persoane. arcele sale fiind arcele grafului G. Fie G=(X. d(G)=max{l[i]/ i∈X}. nici tranzitivă. să se determine în fiecare caz transpusul grafului dat.4.U). Să se arate că Merlin. fiecare jucător jucând pe rând împotriva celorlalţi jucători. fie la sfârşit. 7.

14. Să se realizeze un program care să deseneze un graf (planar)şi apoi să se marcheze succesiv pe desen drumul de lungime minimă între două noduri date. Să se determine un circuit elementar care să treacă prin toate vârfurile grafului care să aibă cost minim. transmiterea ei facându-se numai între doi prieteni. Pentru un graf dat în numerotare aciclică (orice arc u = (x. în care numărul maxim de arce în orice drum este k. Se consideră un grup de n persoane. Un graf orientat se numeşte semi-conex dacă pentru pentru orice pereche de vârfuri diferite x şi y există drum de la x la y sau drum de la y la x. iar în final cartea să ajungă din nou la proprietarul cărţii. precum şi câte un drum de lungime minimă. Să se determine o modalitate prin care cartea să circule pe la fiecare persoană o singură dată. Să se determine o partiţie a mulţimii vârfurilor grafului în cel mult k submulţimi.y din aceeaşi submulţime să nu existe drum de la x la y şi nici de la y la x. 16. determinaţi distanţa minimă de la vârful 1 la toate celelate vârfuri z pentru care există drumuri de la 1 la z. Să se verifice dacă G este semi-conex. Să se formeze grupuri de cursanţi între care există relaţii de prietenie reciprocă. 13. Să se determine pătratul unui graf când graful este reprezentat fie prin liste de adiacenţă. Sunt date arcele şi lungimile lor.y) din U satisface condiţia x<y). 20.12. Pătratul unui graf orientat G se determină astfel: există arc de la x la y în pătratul unui graf dacă există în G un drum de lungime 2 de la x la y. nu neaparat reciproce. Una din persoane are o carte pe care fiecare doreşte să o citească. 18. 15. 17. fie prin matricea de adiacenţă. Fiecare persoana are cel puţin n/2 prieteni şi cel mult k duşmani în grup. Un cursant nu poate să aparţină mai multor grupuri. Indicaţie: Graful este aciclic. deci există noduri cu gradul 0 şi se formează prima submulţime cu aceste noduri şi apoi se vor elimina aceste noduri din graf împreuna cu arcele ce pleacă din ele obţinânduse un graf orientat aciclic pentru care se reia procedeul. Se dă un graf orientat aciclic. Fie G un graf orientat în care fiecare arc are asociat un cost pozitiv. Se consideră o clasă de n ( n <= 40 ) cursanţi între care există relaţii de simpatie. Se dă un graf orientat aciclic şi se cere aranjarea vârfurilor sale astfel încât orice arc are prima extremitate înaintea celei de-a doua extremităţi în aranjare. 100 . astfel încât pentru orice două noduri x. 19.

Fiecare subproblemă se rezolvă direct dacă dimensiunea ei este suficient de mică încât să poată fi rezolvată imediat cu un procedeu specific. urmată de combinarea soluţiilor subproblemelor rezolvate pentru a obţine soluţia problemei iniţiale.1. function divimp(X: problema) if (X este suficient de mica) then y ← rezolvă(X) else{ descompune problema x în subproblemele X1. x2.1.1.2. Să se calculeze cmmdc pentru numere date. X2. Metode pentru rezolvarea problemelor 3.….xn. altfel este împărţită în subprobleme mai mici folosind acelaşi procedeu prin care a fost descompusă problema iniţială. Algoritmul fiind de natură repetitivă şi deoarece subproblemele au aceeaşi formă cu cea a problemei iniţiale.3. yk pentru a obţine y soluţia problemei X */ y ← combină(y1. 101 . Probleme rezolvate R3. 3. yk) return y } Uneori recursivitatea se poate înlocui cu un ciclu iterativ. [Cel mai mare divizor comun] Fie n numere naturale nenule x1. Procedeul se reia până când. …. y2. în urma descompunerilor repetate. ….1. Metoda Divide et Impera 3. Versiunea iterativă poate fi mai rapidă şi foloseşte mai puţină memorie comparativ cu varianta recursivă care utilizează o stivă pentru memorarea apelurilor. Prezentarea metodei Metoda generală de programare cunoscută sub numele de divide et impera (“dezbină şi stapâneşte”) constă în împărţirea repetată a unei probleme în subprobleme de acelaşi tip. y2. se ajunge la probleme care admit rezolvare imediată.1. dar de dimensiune mai mică. Xk for i ← 1 to k do yi ← divimp(Xi) /* combină y1. metoda “Divide et impera” poate fi implementată elegant folosind o funcţie recursivă.1. În continuare este dată funcţia generală care implementează algoritmul.….

readln(x[i]) end. să se afişeze poziţia acestuia. end.x[hi]) else begin m:=(lo+hi) div 2. writeln('Introduceti numerele'). i:integer.m-1) else cauta:=cauta(m+1. R3. if nr=x[m] then cauta:=m else if nr<x[m] then cauta:=cauta(lo..hi:integer):integer.hi) end else cauta:=0 end. cmmdc(m+1. readln(n). Rezolvare: program cautare. [Căutare binară] Fie x1.1.hi)).100] of integer. function Divizor(a. end. var m:integer. cmmdc:= Divizor(cmmdc(lo. begin write('n = '). end. cmmdc(1.hi:integer):integer. for i:=1 to n do begin write('x['.2. function cmmdc(lo. var m:integer. uses crt.i. n. nr:integer.m). begin if (lo<=hi) then begin m:=(lo+hi) div 2. var x:array[1. Să se verifice dacă x se află printre elementele şirului şi dacă da. begin while a<>b do if a>b then a:=a-b else b:=b-a. function cauta(lo.n)).'] = ').25] of integer. begin if (hi-lo<=1) then cmmdc := Divizor(x[lo].…. 102 .b:integer):integer.Rezolvare: program divizor_comun.. writeln('cmmdc:= '. var x:array[1. x2. Divizor := a end.xn un şir de numere întregi ordonate crescător şi x un număr întreg.

rightp=right. }while (leftp < rightp).i. begin write('n = '). ch:=UpCase(readkey). Rezolvare: #include <stdio.leftp-1). [Sortare rapidă] Fie n ∈ N* şi numerele x1.3.1. ch:char. if pos <> 0 then writeln(nr.' se afla in sir la pozitia '. repeat writeln.rightp+1.int right){ int leftp. readln(x[i]) end.pos:integer. R3. table[rightp] = aux. int left.left.xn. write('Continuati (y/n) ?[y] '). end. table[leftp] = table[rightp]. Să se scrie o procedură recursivă de sortare (quicksort) în ordine crescătoare a numerelor date.'] = '). readln(nr). write('Numarul cautat = '). for i:=1 to n do begin write('x['. pos := cauta(1. if ( right-rightp >1) QSort(table. if ( leftp-left > 1) QSort(table.' nu se afla in sir!').i. } else type ? rightp--: leftp++. pos) else writeln(nr. x2. until ch = 'N'.readln(n). unsigned type = 1. writeln('Introduceti numerele').rightp. do{ if ( table[leftp]>table[rightp] ){ type ^= 1.n).h> void QSort (int *table.var n. } 103 .…. leftp =left.aux. aux = table[leftp].right).

Descrieţi un algoritm de ordonare a numerelor prin metoda de sortare prin interclasare.%d\n". for (i=0. • pe fiecare tijă deasupra unui disc pot apare numai discuri cu diametru mai mic.h> void Hanoi(int n.2).%d\n".&d). 2. Hanoi(n.n-1). } R3. Rezolvare: #include <stdio. Hanoi(n-1.h> #define MAX 100 104 .5.4.&n).1. else { Hanoi(n-1. 6-a-b. scanf(“%d”. printf("\%d .x[i]).i++) printf(“%8d”.i++) scanf(“%d”. 6-a-b).1.a. } R3.b). Iniţial toate discurile se află pe tija 1 în ordinea descrescatoare a diametrelor lor. [Sortare prin interclasare] Se consideră un vector ne numere intregi de lungime n.0.b).i. a. int x[100]. printf("Numarul de discuri = ").1. } } void main(){ int n.b).&x[i]). int a. for (i=0. în sensul de la bază la vârful tijei. scanf("%d". cu diametre diferite.a. [Problema turnurilor din Hanoi] Se dau 3 tije numerotate cu 1.i<n. printf(“n = ”). 3 şi n discuri perforate. int b){ if (n==1) printf("\%d .void main(){ int n. Se pune problema de a muta toate cele n discuri pe tija 2 (utilizând şi tija 3) şi respectând urmatoarele reguli: • a fiecare pas se mută un singur disc. Rezolvare: #include<stdio.i<n. Qsort(x.

0. i. k <= hi. mid = (lo+hi) / 2. mid). int hi){ int mid. int lo. k <= hi. 3.tabel[i]). } MSort(tabel. descrieţi un program “Divide et Impera” care să determine al k-lea cel mai mic element din şir (k ∈N. k++) if ( (t_hi > hi || tabel[t_lo] < tabel[t_hi]) && (t_lo <= mid) ) temp[k] = tabel[t_lo++]. x2. scanf("%d". k++) tabel[k] = temp[k]. Se consideră un vector de x cu n componente numere intregi.xn}. MSort(tabel.i<n. Probleme propuse 1. 105 . } 3. printf("n = "). t_hi = mid+1.&n). else temp[k] = tabel[t_hi++]. 2.void MSort(int tabel[]. x2. for (k = lo. t_hi. x2. int temp[MAX]. hi).…. } void main(){ int n. temp. n-1). t_lo = lo.temp. Să se sorteze componentele vectorului folosind metoda de sortare prin interclasare.int temp[].i).3.…. Să se determine max{x1. printf("Introduceti numerele:\n").i<n. if (lo >= hi) return. scanf("%d". k. lo. t_lo. for(i=0.temp. k<n). Fie x1.xn un şir de numere reale. for (k = lo. Se dă x1.1.&tabel[i]). int tabel[MAX]. for(i=0.i++) printf("%d ".i++){ printf("tabel[%d] = ". MSort(tabel.xn (cu n∈N) un şir de numere.…. mid+1.

Să se evalueze polinomul în punctul x0 folosind metoda “Divide et Imera”. subarborele stâng este arborele cartezian al subvectorului stâng (faţă de poziţia elementului din rădăcină). subarborele drept este arborele cartezian al subvectorului drept. 10. Comparaţi numărul de mutări efectuate. Se dau un pătrat şi un cerc. Fie P(x) un polinom de grag n cu coficienţi reali. 106 . Coordonatele se citesc de la tastatură şi sunt numere reale. Se cere să se calculeze aria lor comună cu precizie de o zecimală. Dacă n este impar elementul din mijloc se elimină. Se cere să se decupeze o bucată dreptunghiulară de arie maximă şi fără găuri ştiind că sunt permise numai tăieturi orizontale şi verticale.4. Se consideră un vector de lungime n. 6. 9. 11. 8. Elementele rezultate după pliere vor avea numeroatarea jumătăţii receptoare. Se dă un vector de dimensiune n. Dreptunghiul trebuie descompus în pătrate cu laturi numere naturale. Se dă o placă de tablă cu lungimea x şi lăţimea y având n găuri date prin coordonatele lor întregi. Se numeşte plierea vectorului operaţia de suprapunere a unei jumătăţi (donatoare) peste cealaltă jumătate (receptoare). Plierea se poate repeta până când se obţine un singur element (final). Scrieţi un program care să determine toate elementele finale posibile şi să afişeze succesiunile de plieri corespunzătoare. Scrieţi o procedură “Divide et Impera” pentru inversarea unui şir de caractere. Se cere numărul minim de pătrate în care se poate descompune dreptunghiul. Să se afişeze arborele său cartezian. 7. paralele cu laturile dreptunghiului iniţial. 5. Aria se va afişa pe ecran. Un arbore cartezian al unui vector este un arbore binar definit recursiv astfel: rădăcina arborelui este elementul cel mai mic din vector. Rezolvaţi problema turnurilor din Hanoi folosint două tije de manevră. Rezolvaţi aceiaşi problemă ţinând cont că la pliere fiecare element receptor se dublează şi din acesta se scade elementul donator corespunzător. Se dă un dreptunghi prin dimensiunile sale numere naturale.

Paşii pentru rezolvarea unei probleme folosind programarea dinamică: 1. Dacă d1.. 2. dn este un şir optim de decizii care duc un sistem din starea iniţială în starea finală.2... d2. Principii fundamentale ale programării dinamice: 1.dn. d2. Probleme rezolvate R3.. prin aceasta evitând recalcularea soluţiei dacă subproblema mai apare din nou şi subprobemele care apar în descompunere nu sunt independente..2..2. . d2. . . Metoda programării dinamice se aplică problemelor de optimizare. di şi di. atunci pentru orice i (1≤i≤n) di. .. . 3. d2.. Să se determine cel mai lung subşir crescător din acesta... dn este un şir optim de decizii. apoi. Principii fundamentale ale programării dinamice Programarea dinamică. di. Dacă d1. atunci pentru orice i (1≤i≤n) d1. Dacă d1.1.. Definirea recursivă a valorii unei soluţii optime. di+1.. 3.2. memorează soluţia într-un tablou.. d3. . 3. di+1 . Metoda programării dinamice 3. Un algoritm bazat pe programare dinamică rezolvă fiecare subproblemă o singură dată şi. Exemplu: n=8 7 1 8 2 11 4 12 3 Subşirul crescător maximal: 7 8 11 12 cu lungimea 4 Rezolvare: Se construieşte tabloul L reprezentând lungimea maximă a unui subşir maximal care îl conţine ca prim element pe a[i] astfel 107 . [Subşir crescător maximal] Se consideră un şir de n numere întregi. rezolvă problemele "combinând" soluţiile subproblemelor... dn este un şir optim de decizii care duc un sistem din starea iniţială în starea finală. di+1. Construirea unei soluţii optime din informaţia calculată.. 2. unde di transformă problema din starea si-1 în starea si. dn sunt două şiruri optime de decizii. Calculul valorii unei soluţii optime 4. d2. atunci pentru orice i (1≤i≤n) d1.1.. În problemele de optim metoda constă în determinarea soluţiei pe baza unui şir de decizii d1. di este un şir optim de decizii.. . dn este un şir optim de decizii care duc un sistem din starea iniţială în starea finală.. ..2. d2. ca şi metoda divide et impera. Caracterizarea structurii unei soluţii optime.3.

poz:=i end.i. write(a[poz].h> void main(){ int n.l[100]. write(a[poz].scanf("%d". begin write('n=').read(n). for i:=n-1 downto 1 do begin max:=0. for i:=1 to n do if max<l[i] then begin max:=l[i]. Implementare Pascal: var i. for i:=1 to n do l[i]:=0. l.L[n]=1 şi L[i]=1+max{L[j]/ j>i şi a[j]>a[i]} pentru i de la n-1 la 1 (metoda înainte . printf("n="). Implementare C: #include<stdio. for j:=1+i to n do if (a[j]>a[i]) and (max<l[j]) then max:=l[j].&a[i]).i<=n.j.poz.poz. max:=max-1 end.a:array[1. for i:=1 to n do begin write('a['. 108 .i++) scanf("%d". l[i]:=1+max end. l[n]:=1. for (i=1. while max>1 do begin if (a[i]>a[poz]) and (l[i]=max-1) then begin poz:=i.deoarece soluţia unei subprobleme se află pe baza subproblemelor din urmă).']='). max:=0.j.30] of integer.. read(a[i]) end. i:=i+1 end end.' ').n.max.' ').i. i:=poz.max:integer.&n).a[100].

Rezolvare: Elementele tabloului L se calculează după formula L[i]=a[i]+max{L[j] / j>i+1]} Implementare Pascal: var a. } . for (i=n-1. i=poz. R3. Să se determine suma maximă pe care o poate recupera banca şi care sunt împrumuturile restituite.l:array[1. begin read(n).2..i<=n.j. El trebuie să restituie banii băncii.a[poz]). for(i=1.j<=n. } max=0. 109 for(i=1.a[poz]).} Exerciţiu: Să se rezolve această problemă folosind varianta “înapoi” de programare dinamică (soluţia unei subprobleme se află pe baza subproblemelor dinainte).n.100]of integer. dar după prima restituire ştie că nu mai poate restitui toate sumele împrumutate la rând ci doar acelea care nu au fost împrumutate în etape succesive. max=max++. l[n]=1. max.poz:integer.} printf(" %d ". l[i]=max. [Datorii] Domnul Tudor s-a împrumutat de n ori de la o bancă cu diferite sume de bani.j++) if ((max<l[j])&&(a[j]>a[i])) max=l[j]. printf("%d ".i<=n.i.i--){ max=0. } i++. while (max>1){ if ((a[i]>a[poz]) &&(l[i]==max-1)) { poz=i.i>0. max=max-1.i++) l[i]=0.poz=i. for (j=i+1.2. Indicaţie: Tabloul L se construieşte astfe L[1]=1 şi L[i]=1+max{L[j] / j<i şi a[j]<a[i]} pentru i de la 2 la n.i++) if (l[i]>max) {max=l[i].

max:=max+a[i].&n).poz. i=poz+2.end.poz=1. for(i=1.scanf("%d".j<=n.j++) if (max<l[j]) max=l[j].i.i++) scanf("%d".&a[i]).l[1]).max. l[i]:=max end. repeat write(a[poz].poz:=1.write('sirul: '). l[i]=max. for (i=n.' ').a[poz]).poz:=1.poz=i. i:=poz+2. 110 for i:=1 to n do read(a[i]). for i:=n downto 1 do begin max:=0.h> void main(){ int n.i<=n. max=max+a[i]. max:=l[1]. max:=l[1].i++) if (l[i]>max) {max=l[i]. poz:=i.j.a[100]. max=l[1]. while (i<n ) and (l[i]<>max-a[poz]) do i:=i+1. for (i=1. until max=0 . } max=l[1].i--){ max=0. poz:=i end. for j:=i+2 to n do if (max<l[j]) then max:=l[j].poz=1.l[100].i<=n. max:=max-a[poz]. for (j=i+2. printf("n="). while (max>0){ printf("%d ".i>0.} printf("suma maxima %d\n". for i:=1 to n do if l[i]>max then begin max:=l[i]. Implementare C: #include<stdio.l[1]). writeln('suma maxima este: '.

} R3. v:=j end. c:array[1. d:=a[t]. n:=length(a).4. for i:=1 to m do if a[1]=b[i] then c[1. Exemplu: n=4. var a.1]:=0. end. writeln(d)..max. [Partiţii] Să se determine numărul de moduri în care se poate descompune un număr natural în suma de numere. writeln('secventa maxima are lungimea :'. begin write('primul sir:'). Exerciţiu: Să se implementeze în C aplicaţia de mai sus.2.j].write('sirul doi:').m.i]:=1 else c[1. for i:=1 to n do for j:=1 to m do if max<c[i.1.readln(a).n.. numărul de moduri = 5 Rezolvare: Se construieşte tabloul a unde a[n][0] reprezintă numărul de moduri în care se poate descompune: 111 .50.j.3.} while ((i<n) && (l[i]!=max-a[poz])) i++ . dec(t).j] then begin max:=c[i.50] of integer.j-1]+1 else c[i.d:string.t. poz=i. for i:=1 to n do if a[i]=b[1] then c[i.v:integer. max=max-a[poz].m:=length(b).j]:=0. R3.i]:=0. Rezolvare: Implementarea Pascal (varianta mersului “înapoi”): Se construieşte tabloul c care reţine lungimea maximă a celui mai lung subşir comun a celor două şiruri până la i respectiv j.2.j]:=c[i-1. max:=0.b.max). d:=a[t]+d end. t:=i. [Subşiruri comune] Dându-se două şiruri comune să se determine cel mai lung subşir comun.readln(b). while max>1 do begin dec(max). for i:=2 to n do for j:=2 to m do if a[i]=b[j] then c[i. i.1]:=1 else c[i.

l[1.i] pentru i de la 1 la k. R3.1]:=l[i-1. deplasarea făcându-se numai în direcţiile S şi E. a[1][0]=1.m. a. } } printf("nr de moduri=%d".l<=k-1. for( i=2. for(k=1. else { a[i][k]=a[i-k][k].l:array[1. for i:=2 to n do for j:=2 to m do 112 .k<=i.l++) a[i][k]=a[i][k]+a[i-k][l].q:integer.1].n]=1.m. Implementare C: #include <stdio.1]:=a[1.j..n..j]).i. for i:=2 to m do l[1. a[n. for i:=1 to n do for j:=1 to m do read(a[i.j.1].a[n][0]). for i:=2 to n do l[i.p.k.a[n. printf("n=").1.k++){ if(k==i) a[i][k]=1.i<=n.2. astfel încât suma elementelor de pe traseu să fie maximă.i]:=l[1. a[n.i++){ a[i][0]=0. [Drum] Dându-se un tablou bidimensional cu elemente numere naturale. begin read(m.5. Să se determine un traseu de la poziţia 1. } Exerciţiu: Să se implementeze în Pascal aplicaţia de mai sus.h> void main(){ int n.i].a[1][1]=1.1]+a[i.n).10]of integer.1 la poziţia n.a[100][100].0] pentru n≤2k. for(int l=1.scanf("%d".k]=Σa[n-k.i-1]+a[1.10.k]=a[n-k. Rezolvare: Implementarea Pascal este: var i. else if(i<2*k) a[i][k]=a[i-k][0].&n).p. } a[i][0]=a[i][0]+a[i][k].max.

3. while (p<>1) and (q<>1) do begin if l[p-1.2.. 4.if l[i-1. write(a[1. Exerciţiu: Să se implementeze aplicaţia de mai sus în C. write(a[p. Se doreş113 .ln.j].[ Tipărirea uniformă] Textul de intrare este o succesiune de n cuvinte de lungimi l1. writeln(l[n.j]=max{a[i.j]. a[i. end.q] = l[p.j]:=l[i.1] este suma maximă cerută.m]).1]).j]>l[i. Indicaţie Există o corespondenţă între triangularizarea unui poligon şi parantezarea unei expresii cum ar fi produsul unui şir de matrici.q]-a[p.q].' ').j] else l[i.j-1] then l[i.Aj.j+1]} (varianta mersului “înainte”). Să se calculeze cea mai mare dintre sumele numerelor ce apar pe drumurile ce pleacă din vârf şi ajung la bază şi să se reconstituie drumul de sumă maximă. Indicaţie: Se construieşte tabloul bidimensional L... end. Probleme propuse 1. [Triangularizarea optimă a poligoanelor] Se dă un poligon convex şi o funcţie de pondere p definită pe triunghiurile formate de laturile şi diagonalele poligonului.. Să se găsească o triangulare care minimizează suma ponderilor triunghiurilor din triangularizare.' ').p:=n. c[1.j-1]+a[i.j]+ c[i+1..j] reprezintă numărul minim de înmulţiri pentru a efectua produsul AiAi+1.j) sau (i-1. l2.j) se poate ajunge numai din (i-1... write(a[n. Exemplu: N=3 6 3 8 8 4 1 suma maximă este 18 şi drumul 6 8 4 Indicaţie: Se construieşte tabloul c astfel c[i.q] then p:=p-1 else q:=q-1. Asociativitatea înmulţirii a două matrice ne oferă mai multe posibilităţi de a calcula produsul şi care au un număr diferit de operaţii. Să se determine o posibilitate de asociere a înmulţirii matricelor astfel încât numărul de operaţii să fie minim.j]+ c[i+1. [Triunghi] Se consideră un triunghi de numere. 2. 3.m]. [Înmulţirea optimă a unui şir de matrice] Se dau n matrice. max:=l[n. lungimea fiind măsurată în caractere.j]+a[i.q:=m. 3.m].j]:=l[i-1. În punctul (i.j-1). unde l[i.

gn cm (numere naturale).te tipărirea uniformă a paragrafului pe un anumit număr de linii. g2. Se dă n. Fiecare cămăruţă conţine o anumită cantitate de hrană. astfel încât raftul să fie umplut complet (suma grosimilor cărţilor cumpărate să fie egală cu lungimea raftului) şi numărul cărţilor achiziţionate să fie maxim. Seria dispune de n titluri 1. 6. . …. Stabiliţi care este cantitatea maximă de hrană pe care o poate mânca şi traseul pe care îl poate urma pentru a culege această cantitate maximă. mâncând cât mai multă hrană. 2. împărţită în mxn cămăruţe egale de formă pătrată. [Planificarea unei recepţii] Corporaţia AMC are o structură ierarhică. 2002 114 . mănâncă toată hrana din cămăruţă atunci când intră şi nu intră niciodată într-o cameră fără hrană. [Problema patronului] Un patron a cumpărat un calculator şi doreşte să înveţe să lucreze cu el. m şi cantitatea de hrană existentă în fiecare cămeruţă (numere între 1 şi 100). Olimpiada judeţeană de informatică... Informaticianul Tom trebuie să alcătuiască lista invitaţilor astfel încât suma coeficienţilor de convieţuire a invitaţilor să se maximizeze şi preşedintele să participe la propia petrecere..j] reprezintă numărul maxim de cărţi dintre primele i (în ordinea dată la intrare) cu lungimea totală j sau. 0 dacă nu există nici o submulţime a mulţimii primelor i cărţi cu lungimea totală j. mai puţin ultima. El poate trece dintr-o cameră în una alăturată (două camere sunt alăturate dacă au un perete comun). în raport cu toate liniile. Raftul are lungimea L cm (L număr natural). cu i ≤j iar între cuvinte se lasă exact un spaţiu. Olimpiada Naţională de Informatică 1996 Indicaţie: Se construieşte tabloul bidimensional a unde a[i. fiecare linie având cel mult m caractere astfel: dacă o linie conţine cuvintele de la cuvântul i la cuvântul j. 7. Fiecare angajat are un coeficient de convieţuire (număr real). Pentru aceasta va umple un raft de cărţi din colecţia “Informatica în lecţii de 9 minute şi 60 secunde”. Şoricelul trebuie să pornească din colţul (1. Să se selecteze titlurile pe care le poate cumpăra patronul.n având grosimile g1. [Mouse] Un experiment urmăreşte comportarea unui şoricel pus într-o cutie dreptunghiulară. relaţiile de subordonare formează un arbore în care rădăcina este preşedintele. 5. Să se minimizeze suma cuburilor numărului de spaţii suplimentare de la sfârşitul liniilor. Preşedintele doreşte să organizeze o petrecere astfel încât nici un angajat să nu se întâlnească cu seful său direct.1) al cutiei şi să ajungă în colţul opus.

să se găsească o combinaţie de semne + şi .. x(2). Dacă am obţine secvenţele pentru n = 0. Datele se citesc dintr-un fişier text ce conţine pe fiecare linie câte un număr ce reprezintă valorile lui n pentru care se doresc reprezentări ca mai sus. 2 şi 3. Acestea sunt: 0 secvenţa vidă 1+ 2 . x(i) se află în <-1.Exemplu: 24 1263 3412 Ieşire: 7 21 1 1 --> 2 1 --> 2 2 --> 1 2 --> 1 3 --> 1 4 -->2 4 8. 1>) şi un număr k natural nenul astfel încât: n = x(1)*12+x(2)*22+. Pentru unele numere k este foarte mare şi programul nu ar intra în timp. am rezolva problema.+ (dată în exemplu) 3 .(pentru -1).. se găsesc într-o listă numerele care se pot obţine cu k semne. apoi + . . O altă soluţie ar fi folosirea observaţiei: (n+3)2-(n+2)2-(n+1)2+n2=(n+3+n+2)*1-(n+1+n)*1=2n+5-2n-1=4 Prin adăugarea secvenţei + .. Datele de ieşire vor fi introduse într-un fişier text pe câte o linie combinaţia de semne corespunzătoare. Exemplu: Intrare: 2 4 8 5 Ieşire: ---+ --+ --++--+ ++--+ Indicaţie: Pentru k începând de la 1.. [Semne] Pentru n număr natural...+ se ajunge de la un numar n la n+4. 1.(adică un vector x = (x(1). x(k))..+ 115 . lista pentru k se obţine din cea pentru k-1..+x(k)*k2..

din algoritm se va alege opţiunea care pare a fi cea mai potrivită pe baza unui criteriu de optim local.9. Un astfel de algoritm determină soluţia optimă în urma unei succesiuni de alegeri. iar pe următoarele n linii apar perechile de oraşe prietene (primul pe malul de nord. Se cere să se determine pentru fiecare pereche de vârfuri ( i.3. Prezentarea metodei Algoritmii de tip Greedy sunt folosiţi la probleme de optimizare şi sunt în general simpli şi eficienţi. iar al doilea pe malul de sud). 10. Se impune însă restricţia ca să nu existe linii navale care să se intersecteze. nu există două oraşe pe un mal având acelaşi priten pe celălalt mal. j) şi să se tipărească lungimea drumului minim de la i la j. [Şah] a) Dându-se două poziţii pe o tablă de şah de dimensiune pătratică nxn. Indicaţie: Se construieşte un tablou a cu valori logice. (vezi problema rezolvată 1). 116 . să se determine cel mai scurt drum dintre acestea utilizând mutările calului. Să se determine numărul maxim de linii navale care pot fi înfiinţate. [Submulţimi de sumă dată] Să se determine pentru un vector dat dacă un număr k se poate scrie ca sumă de numere din vector.3.1. cu respectarea condiţiei de mai sus. La fiecare moment decizional. un element din vector se poate folosi o dată. Metoda Greedy 3. 11. b) Determinaţi numărul minim de cai care pot fi amplasaţi pe o tablă de şah de dimensiune nxm astfel încât să nu se atace. [Linii navale] Pe malul de nord şi cel de sud al unui fluviu există n oraşe. Pe prima linie a fişierului de intrare apare numărul n de perechi de oraşe prietene. Indicaţie: Se ordonează posibilele linii navale după primul argument şi se determină cel mai lung subşir crescător format din coordonatele celui de-al doilea argument. [Drumuri minime] Se consideră un graf orientat. 12. fiecare oraş fiind specificat prin distanţa sa (cel mult egală cu 6000) faţă de kilometrul 0 al fluviului. în ideea că la final se va obţine o soluţie optimă globală. Fiecare oraş are un unic oraş prieten pe celălalt mal. unde a[i] este true dacă i se poate scrie ca sumă de elemente din vectorul dat şi false în caz contrar. 3. fiecare arc având un cost ataşat. Intenţia este ca oraşele prietene să se lege printr-o linie navală.

• O funcţie obiectiv care trebuie minimizată sau maximizată. iar soluţia este o submulţime sau o permutare a datelor de intrare în aşa fel încât să fie îndeplinite anumite condiţii de optim. nu neaparat optimă. dar nu se asigură (pentru toate problemele) optimalitatea globală. Există şi probleme pentru care o astfel de metodă nu conduce la soluţie. O problemă care se va rezolva folosind o strategie Greedy este dată de: • O mulţime finită de “candidaţi” care reprezintă datele de intrare. Proprietatea de structură optimală spune că soluţia optimală a problemei conţine soluţiile optimale ale subproblemelor. Problemele care se pot rezolva folosind algoritmi de tip Greedy trebuie să verifice două proprietăţi: proprietatea alegerii Greedy şi substructura optimală. • O funcţie de selecţie care alege la orice moment cel mai potrivit candidat dintre elementele nefolosite încă. Proprietatea alegerii Greedy spune că se poate ajunge la o soluţie de optim global dacă la fiecare pas de decizie se selectează un element care îndeplineşte criteriul de optim local. Dacă un element este inclus în soluţie el va rămâne în această mulţime. a problemei. • O funcţie care verifică dacă o submulţime a datelor de intrare este o soluţie parţială a problemei. În contiunare este prezentată forma generală a metodei. 117 . Dacă un element a fost selectat. • O funcţie care verifică dacă o anumită mulţime de elemente constituie o soluţie posibilă.În general. În acest fel se poate ajunge rapid la o soluţie. deşi aceasta există. datele de intrare pentru un algoritm Greedy se prezintă sub forma unei mulţimi finite. numită funcţie obiectiv. nu se face nici o revenire asupra unei decizii luate. Selectarea unui element la un moment dat poate depinde de elementele alese până la acel moment dar nu depinde de cele care urmează să fie alese ulterior. Un algoritm Greedy nu furnizează decât o singură soluţie. dar nu poate face parte din soluţie atunci acest element nu va mai fi luat în calcul la alegerile următoare. Condiţiile de optim cer determinarea unei soluţii care maximizează sau minimizează o funcţie dată.

Prim). Trebuie să alegem din n obiecte pentru care se cunoaşte greutatea gi şi profitul pi care se obţine prin transportul obiectului i cu rucsacul.3.aux.sol[MAX].h> #define MAX 25 void main(){ int p[MAX].&g[i]). printf("Greutatea maxima G = "). Rezolvare: Programul în C este: #include <stdio. %d:\n". Probleme rezolvate R3. int n. printf("Greutatea = ").3. } 118 . gr.&G).nr[MAX]. int g[MAX].a. [Problema continuă a rucsacului] Avem la dispoziţie un rucsac cu care se poate transporta o greutate maximă G. &n).i+1). la determinarea drumurilor de cost minim de la un vârf la celelalte vârfuri ale unui graf (Dijkstra).&p[i]). i++){ printf("Obiectul nr. scanf("%d". for (i=0.scanf("%f". iar greutatea totală a acestora să nu depăşească G ştiind că putem lua orice parte dintr-un obiect. sol[i] = 0.function greedy(C) {C este mulţimea datelor de intrare } S←∅ {S este multimea care va conţine soluţia} while not Soluţie(S) and C ≠ ∅ do begin x ← select(C) C ← C \ {x} if Posibil(S ∪ {x}) then S ← S ∪ {x} end if Solutie(S) then return S else return write(‘nu exista soluţie’) Această metodă îşi găseşte multe aplicaţii în teoria grafurilor la determinarea unui arbore parţial de cost minim (Kruskal. printf("Numarul de obiecte: "). nr[i] = i. compresia datelor (arbori Huffman) ş. i<n. Să se determine obiectele care trebuiesc alese pentru transport astfel încât profitul obţinut să fie maxim.1.2.0. scanf("%d". scanf("%d".profit. 3. printf("Profitul = ").j. float G.i.

g[i]=g[j].i++) if(sol[i] > 0){ printf("Obiect %d . profit). begin { citire date } 119 .3..i<n.%5. f).i<n-1. într-o zi trebuie planificate n activităţi. nr[j]=aux. sol:array[1. pentru fiecare activitate se cunoaşte intervalul în care se desfăşoară [s.j<n. /*afisare zezultate */ profit = 0.. nr[i]=nr[j].0.2f".1. aux=g[i]. profit += sol[i] * p[i].max] of 0.j.i++) for (j=i+1. i<n && g[i]<gr.aux:integer.2. Rezolvare:Programul Pascal este: program Activitati.2f%%\n".0. for (i=0. p[j]=aux.f:array[1. p[i]=p[j].i. //100% gr -= g[i]. uses crt. } /*alegere */ gr = G. } printf("Profit = %5. var n. } if (i < n) sol[i] = gr/g[i].j++) if(p[i]/g[i] < p[j]/g[j]){ aux=p[i]. for (i=0. Se cere să se planifice un număr maxim de activităţi astfel încât să nu se suprapună. } R3. s. i++){ sol[i] = 1. const max=100. nsol. finish:integer. aux=nr[i].[Planificarea activităţilor] Într-o sală. nr[i]+1. g[j]=aux./* ordonare descrescatoare dupa raportul p/g */ for (i=0. sol[i] *100)..max] of integer.

sol[i]:=0. write('Start = '). j := 1. readln(f[i]). c1.' . for i:=1 to n do begin writeln('Activitatea nr. end.3. j := j + 1.i.':'). R3. readln(s[i]). s[i].… ck-1 unde c∈N*. '.write('Nr de activitati = '). finish := f[i]. s[j]:=aux. readln(n). end. f[i]:=f[j].': '. '. ' .f[i]). end. aux:=f[i]. for i := 1 to n do if (s[i] >= finish ) then begin sol[i]:=1. să se scrie un program care să determine o modalitate de schimb a unei sume S folosind un număr minim de monede (numărul de monede din fiecare tip fiind nelimitat). {ordonare după termenul final} for i := 1 to n-1 do for j := i + 1 to n do if ( f[i] > f[j]) then begin aux:=s[i]. write('Finish = '). [Schimbarea banilor] Presupunem că a avem la dispoziţie k tipuri de monede cu valorile c0. {afisare rezultate} writeln('Solutie:').3. f[j]:=aux. for i := 1 to n do if sol[i]=1 then begin writeln('Activitatea nr. end. {calcul} finish := 0. end.j. s[i]:=s[j]. Rezolvare: Programul C este: 120 .

k:=1. scanf("%d". să se afişeze pe ecran primele n numere frumoase.3.min(n3. [Numere frumoase] Numerele frumoase sunt acele numere care au în descompunerea lor numai factori primi de 2.h> void main(){ int i.j. for(i=0. f[1]:=1. n3:=3. getch(). j<i. begin write('n = '). scanf("%d".b:integer):integer. x).S. i++){ sol[i] = S / x..#include<stdio. Fiind dat un număr natural n<1000. n2:=2. i<k. n5:=5.max] of longint.n3. l:=l+1.n:integer. S>0. i:=1.xmax. Rezolvare: Programul Pascal este: program nrFrumoase. 121 . l:=1.n5)). begin if a <= b then min:=a else min:=b end. scanf("%d". x /= c. for(j=0. printf("S = "). t:=1.k. sol[j].&S).h> #include<conio. while(l<=n) do begin t:=min(n2.j. x = xmax. j++.c.l. for(i=1. } R3. j:=1. f[l]:=t.k. int sol[100].x/=c) if(sol[j]>0) printf("%d monede cu valoarea %d\n". n2 := 2*f[i] end. f:array[1.n2.&k). i. int x. i++) xmax*=c. if t = n2 then begin inc(i). printf("c = "). function min(a. n3 := 3*f[j] end.&c).4. } /*afisare */ x = xmax. S %= x. if t = n3 then begin inc(j). /*calcul */ xmax=1. var t. 3 şi 5. /*citire date */ printf("k = "). const max = 1000. readln(n).n5:integer.

Zboara(k. să se scrie un program care să determine o secvenţă de zboruri pentru a ajunge la configuraţia finală. } int Copac(int c){ int i=0. return i. liber):\n").k). } void main(){ int i. liber):\n"). \ initial[s].h> #define MAX 10 int initial[MAX]. int final[MAX]. initial[d] = initial[s]. scanf("%d".end.&final[i]). [Copaci şi ciori] Pe n copaci aşezaţi în cerc se află n-1 ciori.&initial[i]). } } 122 .i++) {printf("initial[%d] = ". k. for(i=0.i<n. while(initial[i]!=0) i++.d+1). if t = n5 then begin inc(k). } k = Copac(final[i]). while(initial[i] != c) i++.3.int d){ printf("Cioara %d zboara de pe copacul %d pe %d !\n".5.i<n.i++) if (final[i] && initial[i] != final[i]){ if(initial[i]) { k = CopacLiber(). R3. readln. maxim una pe fiecare copac. scanf("%d". Zboara(i. int n. printf("n = ").} for(i=0. for i:=1 to n do write(f[i]. } void Zboara(int s.i+1).} printf("Introduceti configuratia finala (0 pt.&n). Dându-se o configuraţie iniţială şi una finală a ciorilor şi ştiind că la un moment dat o singură cioară poate zbura de pe copacul ei pe cel liber. printf("Introduceti configuratia initiala (0 pt. return i.i<n.' '). Rezolvare: Programul C este: #include <stdio. s+1.i).scanf("%d". initial[s] = 0.i+1). n5 := 5*f[k] end end. for(i=0.i++) {printf("final[%d] = ". int CopacLiber(){ int i=0.

traseu[1]:=k.. j] < min then begin min := harta[k.min.1]). writeln(traseu[1]:3)..6.j]. Cunoscând legăturile dintre oricare două oraşe se cere să se afişeze cel mai scurt traseu posibil pe care poate să-l parcurgă comisvoiajorul ştiind că nu trebuie să treacă de două ori prin acelaşi oraş.'. readln(k). v:array[1. for j:=1 to n do if v[j] = 0 then if harta[k. readln(harta[i. i.harta[k. k:=pos end. lungime).j.i. inc(lungime. end. v[pos]:=1.1..max.j]). traseu:array[1. writeln('lungimea = '.max] of integer. 123 . j.1.min). '. var harta:array[1. for i:=1 to n do write(traseu[i]:3).3.n. [Problema comis-voiajorului] Un comis-voiajor trebuie să viziteze un număr de n oraşe şi să revină în oraşul de plecare. end. v[k]:=1. for i:=1 to n-1 do for j:=i+1 to n do begin write('distanta['. for i:=2 to n do begin min:=maxint. lungime:=0. traseu[i]:=pos. begin write('n = ')..lungime. inc(lungime. write('Orasul de pornire = ').pos:integer. readln(n).max] of 0. const max = 25..R3.i]:=harta[i. harta[j. Rezolvare: Programul Pascal este: program comis.k.'] = '). pos := j end. readln.max] of integer. j].

2. Ln. Să se determine o submulţime {x1. Perechile de bazine ce vor fi unite sunt date într-o listă. Un instructor de schi trebuie să distribuie n perechi de schiuri la n elevi începători. 5. Într-un depozit al monetăriei statului sosesc n saci cu monezi. …. 9. Se cere modul de amplasare al fiecărui canal. Fiecare bazin poate fi unit prin câte un canal cu mai multe bazine. Se cunoaşte numărul de monezi din fiecare sac şi se doreşte mutarea monezilor dintr-un sac în altul în aşa fel încât în fiecare sac să apară acelaşi număr de monezi. …. Să se determine configuraţia unei reţele telefonice astfel încât toate oraşele să fie conectate la reţea şi costul reţelei să fie minim. Un canal poate trece doar prin interiorul sau exteriorul cercului format de bazine. Ştiind că fiecare lucrare este executată într-o unitate de timp şi că nu se pot executa mai multe lucrări simultan. x2. Scrieţi un program care rezolvă problema efectuând un număr minim de mutări. Probleme propuse 1. cunoscându-se pentru fiecare lucrare i termenul de finalizare ti şi penalizarea pi plătită în cazul în care lucrarea nu este predată la termen. ♦ pe fiecare linie numerele sunt aşezate în ordine crescătoare. k≤n. 6. Se dau numerele întregi nenule a1. Fie n şiruri ordonate crescător S1. Să se detmine o mulţime de cardinal minim de intervale de lungime 1 a căror reuniune să includă mulţimea X. xm} a mulţimii {a1.3. …. [Amplasarea canalelor] În jurul unui oraş avem N bazine cu apă ce trebuiesc unite între ele prin canale. să se planifice ordinea de execuţie a lucrărilor astfel încât penalizarea totală să fie minimă. …. ….3. 3. a2.xn} o mulţime de numere reale. x2. naturale. …. an şi b1. Sn cu lungimile L1. 7. an} care să maximizeze expresia E = b1x1 + b2x2 + … + bmxm. S2. Să se interclaseze cele n şiruri obţinându-se un singur şir crescător de lungime L1 + L2 + … + Ln cu un număr minim de comparaţii între elementele şirurilor. [Problema planificării optime a lucrărilor] Se presupune că avem de executat un număr de n lucrări. Să se construiască un tablou n×n care îndeplineşte simultan condiţiile: ♦ conţine toate numerele de la 1 la n2 o singură dată. 8. Se cunosc poziţiile oraşelor unei ţări date prin coordonatele lor. a2. Fie X = {x1. de la stânga la dreapta.3. 4. b2. …. ♦ suma elementelor de pe coloana k să fie minimă. Descrieţi un algoritm care să facă distribuirea în aşa 124 . bm cu n ≥ m. L2. Se dau n şi k.

4. x2 ∈ S 2. …. numite condiţii interne. 12. 11..xn cu x1 ∈ S1. Mulţimea S = S1 × … × S1 se numeşte spaţiul soluţiilor. …. …. Fiind dată o hartă cu n ţări. Descrieţi un algoritm euristic care să schimbe o sumă S dată folosind un număr minim de monete având valorile v1. Pentru fiecare problemă concretă sunt precizate relaţiile dintre componentele vectorului care memorează soluţia. 10. Metoda backtracking 3. 14. care pot coincide.4. vn.. scurtându-se astfel timpul de calcul. xn ∈ S n. cu exceptia ultimului este cunoscut succesorul). Vectorul x este privit ca o stivă. iar mulţimile S1. ….fel încât suma diferenţelor absolute dintre înălţimea elevului şi lungimea schiurilor să fie minimă. Cu ajutorul unei funcţii succesor xk ia valoarea primului element din Sk. Se dă un polinom P(X) cu coeficienţi întregi. După ce xk a primit o valoare. v2. nu se trece direct la atribuirea unei valori lui xk+1 ci se verifică mai întâi anumite condiţii de continuare referitoare la x1. lui xk nu i se atribuie o valoare decât după ce x1. …. Sn. un poligon convex care să aibă ca vârfuri aceste puncte.Prezentarea metodei Această tehnică se foloseşte la rezolvarea problemelor a căror soluţie se poate reprezenta sub forma unui vector S = x1x2.1. Să se construiască. iar elementele produsului cartezian care satisfac şi condiţiile interne se numesc soluţii rezultat. Descrieţi un algoritm euristic care să determine o modalitate prin care un cal aflat în colţul stânga-sus să străbată întreaga tablă de şah fără a trece de două ori prin aceeaşi poziţie. xk-1 au primit valori. Metoda evită generarea tuturor combinaţiilor completând pe rând componentele vectorului soluţie cu valori ce îndeplinesc condiţiile de continuare. La început xk este iniţializat la o valoare (cu ajutorul unei funcţii init) al cărei succesor este primul element din Sk. Să se afle toate rădăcinile raţionale ale polinomului. Se dau n puncte în plan prin coordonatele lor numere întregi. descrieţi un algoritm euristic care să determine o modalitate de colorare a hărţii astfel încât două ţări care se învecinează să fie colorate diferit. S2. xk cu ajutorul unei funcţii valid de tip logic. 125 . 3. Dacă aceste condiţii sunt satisfăcute se verifică dacă s-a obţinut o soluţie caz în care se trece la afişarea acesteia. 13. sunt mulţimi finite ordonate liniar (pentru orice element. dacă este posibil.

k) then Back(k+1) end. init(k. st) end else k := k – 1. Algoritmul se termină în momentul în care au fost luate în calcul toate elementele mulţimii S1. Rezolvarea problemelor prin această metodă necesită un timp mare de execuţie. …. while succesor(x.k) do begin x[k]:=i. st. k). if as then valid(ev. until (not as) or (as and ev). while k > 0 do begin repeat succesor(as. var i:integer. st. if valid(x. begin if solutie(k) then tipar(x) else begin init(k. st). nu vom ajunge la o soluţie. se micşorează k cu o unitate şi se încearca o nouă alegere pentru xk (k >0) din restul elementelor lui Sk încă nealese folosind funcţia succesor. xn. end end.Neîndeplinirea condiţiilor de continuare exprimă faptul că oricum am alege xk+1. end. dacă Sk a fost epuizat. În acest caz se face o nouă alegere pentru xk sau.x). Metoda backtracking poate fi descrisă prin următoarea procedură (în varianta iterativă): k := 1. init(k. 126 . Metoda admite şi o variantă recursivă în care stiva nu este gestionată explicit de programator. sau dacă nu se cunoaşte un alt algoritm mai rapid. motiv pentru care metoda este recomandată numai în cazurile în care spaţiul soluţiilor este destul de redus. if as if solutie(k) then tipar else begin k := k + 1. Ca urmare se trece la atribuirea unei valori lui xk+1 doar dacă sunt îndeplinite condiţiile de continuare. În continuare este dată forma generală a procedurii backtracking în variantă recursivă (care se va apela cu Back(1)): procedure Back(k). k).

' '). var st: stack. 127 .3. writeln end. begin if st[k] < n then begin st[k] := st[k] + 1. end. var i:integer. begin for i:=1 to n do write(st[i]. ….st) end else k:=k-1 end. begin solutie:=(k=n) end. Rezolvare: program permutari. begin write ( ' n = ' )..st. end. as.st). readln(n) .k). [Permutări] Se dă un număr n ∈ N. var st: stack. procedure tipar. k:integer. for i:=1 to k-1 do if st[k] = st[i] then ev:=false end. function solutie(k:integer) :boolean.25] of integer. 2. k) . se cere să se genereze toate permutările mulţimii {1. k:integer). init(k.4. as := true end else as:=false. var st: stack). n:integer. st: stack. while (k>0) do begin repeat succesor (as. ev: boolean. k:=1.2. procedure valid(var ev:boolean. uses crt. st. begin st[k]:=0 end. if as then valid(ev.n}. init(k. procedure succesor(var as:boolean. k:integer).4. if as then if solutie(k) then tipar else begin k:=k+1. Probleme rezolvate R3.1. begin ev:=true. procedure init(k:integer. until (not as) or (as and ev) . var i:integer. type stack = array[1.

function Prim(nr:integer):boolean. procedure Tipar.. for i:=2 to n do if Prim(i) then begin inc(p).' '). end else inc(i).k. x :array[1. inc(k). k:=1. while i*i <= nr do if nr mod i = 0 then begin Prim:=false. end. break. x[k]:=0.R3.p.i. i:=2. var i:integer.Prime[x[k]]). var i:integer.4. p:=0. if (x[k] <= p) and (S + Prime[x[k]] <= n) then if S + Prime[x[k]] = n then Tipar else begin inc(S. Dec(S. n. 128 . [Descompunere ca sumă de numere prime] Să se descompună un număr natural n în toate modurile posibile ca sumă de numere prime. Prime[p]:=i end. begin for i:=1 to k do write(Prime[x[i]]. while k>0 do begin inc(x[k]).Prime[x[k]]). Rezolvare: program desc_prime.100] of integer. x[k] := x[k-1]-1 end else begin dec(k). begin Prim:=true. readln(n). writeln end.S:integer. S:=0. var Prime.2. end end end. begin write('n = ').

3. dame(0). [Problema damelor] Pe o tablă de şah trebuie aşezate opt dame astfel încât să nu existe două dame pe aceeaşi linie. [Problema colorării hărţilor] Fiind dată o hartă cu n ţări. j++) printf("%d ".&n). scanf("%d". i < n. st[j]). printf("n = ").j. valid = 1. } void dame(int k){ int i. else for(i = st[k]+1. 129 . for(j = 0. Să se determine toate soluţiile. i++) st[i]=0. } void main(){ int i. i++) { st[k] = i. for(j = 0. i <= n. } st[k] = 0. Problema se generalizează imediat pentru n dame pe o tablă cu n linii şi n coloane. if (valid ==1) dame(k+1). for(i = 0. getch(). Rezolvare : #include <stdio.4.h> #include <conio.R3. int n. if (k==n) tipar().h> #include <math. stack st. se cer toate soluţiile de colorare a hărţii utilizănd un număr minim de culori. j++) if ((st[j]==st[k])||(abs(st[k]-st[j])==k-j)) valid = 0. valid.h> typedef int stack[25]. coloană sau diagonală.4. void tipar(){ int j. } R3. astfel încât două tări cu frontieră comună să fie colorate diferit.4. j < n. j < k. printf("\n"). Menţionăm că este demonstrat faptul că sunt suficiente 4 culori pentru a colora orice hartă.

begin for i:=1 to n do write(st[i]. end. function solutie(k:integer) :boolean. a[j.k). procedure tipar..st). procedure succesor(var as:boolean. end.Rezolvare: program Culori. if as then if solutie(k) then tipar else begin k:=k+1.' ').k]=1) then ev:= false. ev: boolean. var st: stack. readln(a[i.j]).']= ').25. init(k.st.1. uses crt.st) end else k:=k-1.k. begin st[k]:=0 end. type stack = array[1.var st: stack). for i:=1 to k-1 do if (st[k]=st[i]) and (a[i. readln(n). i. k:=1. k) .n:integer.25] of integer. while (k>0) do begin repeat succesor (as. init(k. procedure init(k:integer. as := true end else as:=false.j.25] of integer. as. 130 . k:integer). end. if as then valid(ev. var i:integer. st: stack. begin solutie:=(k=n) end. var i:integer. for i:=1 to n do for j:=1 to i-1 do begin write('a['. st. procedure valid(var ev:boolean.. k:integer). begin ev:=true. begin if st[k] < 4 then begin st[k] := st[k] + 1. writeln end.j] end.i]:=a[i.j.. a:array[1.'. begin write (' n = ').'. end. until (not as) or (as and ev) . var st: stack.i.

0.-2. if (tab[lin][col]) return. void tipar(){ int i. i < n. i < n. tab[lin][col]=k. [Săritura calului] Se consideră o tablă de şah n x n şi un cal plasat în colţul din stânga sus. i++){ lin2 = lin + linT[i].+1}.&n). } printf("\n").-1.col2. i++){ printf("\n"). cal(0.+1. Rezolvare: #include <stdio. for(j = 0. j < n. printf("\n%d solutii".+2. printf("n = "). } void main(){ int i.t).col2. col2 = col + colT[i]. j++) tab[i][j]=0. if (lin2>=0 && lin2<n && col2>=0 && col2<n) cal(lin2. Se cere să se afişeze toate posibilităţile de mutare a calului astfel încât să treacă o singură dată prin fiecare pătrat al tablei.j. j < n. i < 8. } 131 . int col. int colT[8] = {+2. tab[i][j]). scanf("%d".0).4.lin2. k++.+2.j. i++) for(j = 0.+2.h> #include <conio. tabla tab.5. for(i = 0. int linT[8] = {-1.h> typedef int tabla[25][25]. } void cal(int lin. getch().R3. int k){ int i.+1. } tab[lin][col] = 0.k). else for (int i = 0.-1. j++) printf("%3d". for(i = 0.-2.-2.-1. int n.+1.-2}. if (k==n*n) tipar().

4. 10. Fie două numere naturale n şi k cu n ≥ k. Un întreprinzător ce dispune de un capital C trebuie să leagă dintre n oferte la care trebuie avansate fonfurile fi şi care aduc profiturile pi pe acelea pe care le poate onora cu capitalul de care dispune şi care îi aduc profitul total maxim. …. …. Se dau mulţimile A1 = {1. A2. Se dă o sumă S şi n tipuri de monede având valorile v1. Să se genereze toate steagurile ce se pot forma cu trei culori diferite având la mijloc alb sau negru. să se determine toate modalităţile de amplasare a n ture pe această tablă în aşa fel încât să nu se atace între ele. v2. verde. 2. …. 9. p1}. p2}. 2. să se genereze toate aranjamentele (funcţiile injective) de elemente din mulţimea {1. …. 12. 6. Se cer toate modalităţile de plată a sumei S utilizând aceste monede.n}. Se consideră mulţimea {1. 132 . 5. …. Se cer toate partiţiile acestei mulţimi. Cunoscând legăturile dintre oraşe se cere să se afişeze toate drumurile posibile pe care poate să le parcurgă comis-voiajorul ştiind că nu trebuie să treacă de două ori prin acelaşi oraş. …. 3. …. Să se descompună un număr natural n în toate modurile posibile ca sumă de numere naturale. 2. Într-un grup de persoane fiecare persoană se cunoaşte pe sine şi cunoaşte eventual şi alte persoane din grup. 2. 8. A2 = {1.3. roşu. n}. albastru. 2.3. 4. galben. Avem la dispoziţie 6 culori: alb. Un comis-voiajor trebuie să viziteze un număr de n oraşe şi să revină în oraşul de plecare. se cere să se genereze toate submulţimile (combinările) de k elemente din mulţimea {1. Să se determine toate modurile în care cele N persoane se pot repartiza în echipe astfel încât orice persoană din grup să fie cunoscută de cel puţin un membru al fiecărei echipe. 2. Să se determine toate delegaţiile de n persoane din care p femei care se pot forma din t persoane din care v femei. An. pn} se cere să se genereze produsul cartezian al mulţimilor A1. negru. vn lei. 11. …. Se dau numerele naturale n şi k. n} luate câte k. 2. 7. Probleme propuse 1. Considerându-se o tablă de şah de dimensiuni n × n. …. An = {1.

14. astfel încât oricare dintre cele 5 numere să coincidă în m poziţii şi să nu existe nici o pozitie care să conţină aceeaşi cifră în toate cele 5 numere. 20. o avere formată din monede având ca valori numere întregi pozitive. 4. în mod egal. 133 . O condiţie din testament cere ca fraţii să împartă monezile în două părţi având valori egale pentru a intra în posesia lor. 7 sau 8 dă ca rezultat tot un număr de nouă cifre distincte (fără 0). Această proprietate nu funcţionează pentru numerele 3. 18. b] în care sunt cuprinse cele n numere (după transformarea în baza 10) să fie de lungime minimă. Să se elaboreze toate chestionarele având între a şi b întrebări distincte.13. Se dau x1. 17. Pe malul unui râu se găsesc c canibali şi m misionari. 16. xn numere naturale cu cel mult 9 cifre şi n ≤ 100. Întrebările sunt date prin număr şi punctaj. Dacă pe unul dintre maluri se vor afla mai mulţi canibali decât misionari aceştia din urmă vor fi mâncaţi de canibali. astfel încât suma numerelor aflate pe muchiile unei feţe să fie aceeaşi pentru toate feţele. Să se gasească baza bi pentru fiecare număr xi astfel încât intervalul [a. Pentru elaborarea unui test de aptitudini avem un set de n întrebări. 15. Există totuşi multe numere de nouă cifre distincte (fără 0) care înmulţite cu 3 au aceeaşi proprietate. Fiecare număr xi este reprezentat în baza bi (2 ≤ bi ≤ 10) care nu este cunoscută. 2n + 1 persoane participă la discuţii (masă rotundă) care durează n zile. Se cere un program care să afişeze toate modalităţile de trecere a râului în care misionarii să nu fie mâncaţi. fiecare fiind cotată cu un număr de puncte. Să se găsească variantele de aşezare la masă astfel ca o persoană să nu aibă în două zile diferite acelaşi vecin. Să se genereze o secvenţă binară de lungime 2n+n+1 astfel încât orice două secvente consecutive de n biti să fie diferite. 21. 19. 6 sau 9. Să se listeze toate aceste numere în care ultima cifră este 9. fiecare chestionar totalizând între p şi q puncte. altfel suma va fi donată unei biserici. x2. Ei urmează să treacă râul cu o barcă cu două locuri. Să se dispună pe cele 12 muchii ale unui cub toate numerele de la 1 la 12. Să se determine 5 numere de câte n cifre fiecare cifră putând fi 1 sau 2. Cei doi fii ai unei familii moştenesc prin testament. Scrieţi un program care să îi ajute pe cei doi fraţi să intre în posesia moştenirii. …. Numărul 123456789 înmulţit cu 2.

Se dă o matrice binară în care elementele cu valoarea 1 delimitează o suprafaţă marcată cu elemente de zero. Fiecare punct alb se va uni cu un singur punct negru asttfel încăt segmentele formate să nu se intersecteze. să se genereze toate trasele pe care le poate urma mingea pentru a părăsi terenul. 23. Un cal şi un rege se află pe o tablă de şah. j) şi s(i. Se dau n puncte albe şi n puncte negre în plan prin perechi (i. să se afişeze traseul.22. Dându-se coordonatele unui punct în cadrul matricei să se “coloreze” suprafaţa în interiorul căreia cade punctul. precum şi poziţia regelui sunt considerate "nearse". prin care calul să poată ajunge la rege şi să revină la poziţia iniţială. iar orice mişcare a calului face ca respectivul câmp să devină "ars". poziţiile lor fiind cunoscute. Ştiind că mingea se poate deplasa într-unul din cele maxim 8 careuri vecine doar dacă acesta are o cotă strict mai mică. 24. Să se afle dacă există o succesiune de mutări permise (cu restricţiile de mai sus). Dacă se dau două oraşe A şi B. 27. Să se selecteze 4 puncte ce reprezintă colţurile pătratului care cuprinde numărul maxim de puncte din cele n puncte date. staţiile de schimbare a trenurilor şi timpii de aşteptare în aceste staţii astfel încât durata totală a călătoriei să fie minimă. 134 . Fie o matrice n x m cu valori de 0 şi 1. 25. Se cere un program care să calculeze numărul de obiecte din fotografie. fiecare careu având o anumită înălţime. Poziţia iniţială a calului.j) să se găsească toate ieşirile din matrice mergând doar pe elemente cu valoarea 1. Unele câmpuri ale tablei sunt "arse".j) de numere întregi.j) de numere întregi. Calul nu poate călca pe câmpuri "arse". Toate oraşele unei ţări sunt legate la o reţea de linii feroviare. 28. Dându-se o poziţie iniţială (i. Se dau n puncte în plan prin perechi (i. 29. Două oraşe i şi j pot fi legate prin cel mult o legătură directă prin care circulă un singur tren pe zi între orele p(i. Fotografia prezintă unul sau mai multe obiecte. Să se găsească o soluţie ştiind ca oricare 3 puncte sunt necoliniare. O fotografie alb-negru este dată printr-o matrice cu valori 0 şi 1. Punctele fiecărui obiect sunt marcate cu 1. Configuraţia unui teren este specificată printr-o grilă gen tablă de şah de dimensiune n×n. j). 26. Într-un careu precizat al grilei se plasează o minge.

în alte cazuri se cere configuraţia finală ştiind că trebuie să verifice anumite condiţii de optim. Piesele se vor folosi la pavarea fără fisuri a unei zone rectangulare de dimensiuni ka × pa. Se consideră un număr nelimitat de piese dreptunghiulare de dimensiuni a × 2a. Din bară trebuiesc tăiate bucăţi de lungimea reperelor date.1. Se consideră o bară de lungime n şi k repere de lungimi l1. Diferenţa dintre cele două metode constă în faptul că metoda backtracking la fiecare etapă selectează un singur succesor după care se face verificarea condiţiilor de continuare. astfel încât să avem cel puţin câte o bucată de lungime li cu i = 1. Se dă un număr natural par n. Alegerea optimă a unui element din această listă pentru expandare se face cu ajutorul unei funcţii f = g + h în care g este o funcţie care măsoară lungimea drumului parcurs de la configuraţia iniţială până la nodul curent. 33. Problemele care pot fi abordate prin această metodă pot fi modelate într-un mod asemănător celui folosit la metoda backtracking. Se alege apoi un element din listă după un criteriu ce depinde de problemă şi se reia procesul de expandare. 31.5. Se pleacă de la o configuraţie iniţială şi se reţine şirul de operaţii prin care aceasta este transformată într-o configuraţie finală dacă aceasta este dată. iar h este o funcţie (euristică) care estimează efortul necesar pană se ajunge la soluţie şi este specifică fiecărei probleme. Alegerea funcţiei h este foarte importantă din punct de vedere a vitezei de execuţie a programului. lk. Metoda Branch and Bound 3.30. Să se afişeze toate şirurile de n paranteze care se închid corect. 32. iar metoda branch and bound generează la fiecare pas toate configuraţiile posibile (toţi succesorii) care rezultă din cea curentă şi le stochează într-o listă.5.k şi pierderile să fie nule. l2.…. Să se găsească în matrice prefixul de lunginme maximă al cuvântului dat. Prezentarea metodei Metoda branch and bound foloseste la rezolvarea problemelor la care domeniul în care se caută soluţia este foarte mare şi nu se cunoaşte un alt algoritm care să conducă mai rapid la rezultat. Se cer toate soluţiile (reprezentare grafică). 135 . 3. Se dă un cuvânt si o matrice de caractere de dimensiune m x n..

3. 5. D. pentru fiecare succesor din această listă se execută: 3. iar dacă acest nod se găseşte în close. Algoritmul se poate implementa folosind o singură listă. t. C. 2. se verifică dacă valoarea lui g este mai mică decât cea a configuraţiei găsite în listă: 3. se selectează din lista open nodul t cu f minim. se execută următoarele: 1. 3. se testează dacă acest succesor aparţine listei open sau close şi în caz afirmativ. înregistrarea corespunzătoare configuraţiei iniţiale este încărcată în open cu g=0 şi f=h. este introdus în lista open. dacă ciclul se încheie deoarece lista open este vidă înseamnă că problema nu are soluţie. dacă s-a selectat pentru expandare nodul corespunzător configuraţiei finale atunci se trasează folosind o procedură recursivă drumul de la configuraţia iniţială la cea finală utilizând legătura 'tată'. configuraţia la care s-a ajuns. Observaţie. este trecut în open.2. în caz că acest nod nu se găseşte în open sau close. Algoritmul este următorul: A.Se lucrează cu două liste: lista open în care se reţin configuraţiile neexpandate încă şi lista close care le memorează pe cele expandate. adresa înregistrării următoare în lista succesorilor. nodul găsit este direcţionat către actualul părinte (prin fixarea legăturii tată) şi se ataşează noul g. iar diferenţierea dintre nodurile expandate şi cele neexpandate se va face după un câmp special. Apare însă dezavantajul că operaţiile de 136 .1.2. adresa nodului 'tată'. 4. 3. 3. valorile funcţiilor g si h. Soluţia se construieşte folosind un arbore care se parcurge pe baza legăturii tată.1. în caz afirmativ. obţinut ca sumă între valoarea lui g a configuraţiei t şi costul expandării (de obicei 1). adresa înregistrării următoare în lista open sau close. se expandează acest nod obţinând o listă liniară simplu înlănţuită cu succesorii săi.2. se ataşează noul g.2. 2. atât timp cât nu s-a selectat spre expandare nodul corespunzător configuraţiei finale şi lista open este nevidă. B. Nodurile sunt înregistrări care cuprind următoarele informaţii: 1.

profit... 137 ..masatotala:integer. Nodul corespunzător fiului drept se obţine din nodul tată la care se adaugă obiectul curent.5. în prealabil. iar cel corespunzător fiului stâng se obţine din nodul tată însă fără adăugarea obiectului analizat. uses crt.1. end.max] of 0. iar opţiunea pentru una din cele două ramuri se face pe baza unei funcţii H care estimează profitul. PNod= ^Nod. program RucsacBB. La fiecare iteraţie se decide includerea sau nu a obiectului curent în rucsac şi se expandează configuraţia curentă în două configuraţii corespunzătoare celor doi subarbori. Algoritmul face.2.3. xp = 1 dacă obiectul p este luat în rucsac. Acest dezavantaj se poate elimina folosind o structură specială numită tabelă hash. 3. var n: integer. const max = 25. Probleme rezolvate R.căutare se fac într-o listă mai lungă. obiect: array[1.max] of TObiect. nr:integer end.drept. solutie:array[1. p_estimat.stang:PNod. Soluţia se va da sub forma unui vector definit astfel: xk=0 dacă obiectul k nu este luat în rucsac. În unele cazuri se poate folosi un arbore binar. tata. profit:integer. specificându-se masele obiectelor şi profiturile ce se obţin prin transportul lor cu rucsacul. Nod = record nivel. Se cere un program care să determine obiectele alese astfel încât să se obţină un profit maxim.masa:integer. Se porneşte de la configuraţia iniţială în care nici obiect nu a fost încă ales. [Problema discretă a rucsacului] Se dă un rucsac de capacitate M şi un număr de n obiecte. Se parcurge iterativ lista de obiecte. profitmax.1. o ordonare descrescătoare a obiectelor după raportul profit/masă. G.luat:integer.5. Rezolvare: În rezolvarea acestei probleme nu vom folosi două liste ci un arbore binar. type TObiect = record masa. Analiza continuă numai pe una din cele două ramuri ale arborelui binar.

drept^.profit/obiect[j]. nodc^.procedure Sort. begin p := pn^.tata:= nil.m:integer.profit.masa <= G then begin p := p + obiect[i]. H := p end else H:=-1. until k=n.profit + obiect[k].masa:=nodc^. stang^. begin k:=0. new(stang). var i. stang^.stang:=stang.luat:=0. nodc^. procedure Branch. stang^.masa:=nodc^. nodc^. end. if stang^.profit. new(drept). drept^.p_estimat:=H(drept). m := m + obiect[i].masa.nivel:=k.masa < obiect[j].masa + obiect[k]. obiect[i]:=obiect[j].luat:=1. nodc^.drept:PNod. drept^. nodc^. m := pn^.j:integer. nodc^.profit/obiect[i]. obiect[j]:=aux. nodc^. end. if m <= G then begin for i:= k + 1 to n do if m + obiect[i].profit:=nodc^.nivel. drept^. stang^.profit. p. stang^.p_estimat then nodc:=stang else nodc:=drept.k:integer. nodc.nivel:=k. begin for i:=1 to n-1 do for j:=i+1 to n do if (obiect[i].profit:=nodc^. end.drept:=drept.masa) then begin aux:= obiect[i]. aux:TObiect.p_estimat:= H(stang). function H(pn:PNod):integer. drept^. repeat inc(k).p_estimat > drept^. new(nodc).tata:=nodc. 138 .stang. stang^. drept^.profit.tata:=nodc. var i. k := pn^.profit:=0.nivel:=k.luat:=0.masa end.masa:=0.masa.masa. var k:integer.

Se cere de asemenea ca acest sir să fie optim. writeln('Solutie:').tata<>nil do begin solutie[nodc^.nr.nivel]:=nodc^. fiecare căsuţă conţine un număr între 1 si 15 si o căsută conţine zero (este liberă).nr := i. R3. writeln('Masa totala = '. [Jocul Perspico] Se consideră o tablă cu 4 x 4 căsuţe. end . readln. Branch. obiect[i]. profitmax).2. readln(obiect[i].h> #define MAX 4 #define maxop 4 139 end. Sort. se cere să se precizeze şirul de mutări prin care se poate ajunge de la o configuraţie iniţială dată la o configuraţie finală. readln(obiect[i].profit. nodc:=nodc^. la stânga sau jos. writeln. masatotala := nodc^.h> #include<stdlib. write('Profitul['. profitmax := nodc^. for i:= 1 to n do begin write('Masa['. la dreapta.var i:integer.luat. masatotala). end.i . for i:= 1 to n do if solutie[i]=1 then write(obiect[i].5. while nodc^.'] = ').h> #include<conio. Ştiind că 0 îşi poate schimba poziţia cu orice numâr natural aflat deasupra. write('Numarul obiectelor = ').'] = ').masa.' ').masa). în sensul că trebuie să se ajungă la configuraţia finalâ într-un număr minim de mutări. Rezolvare: #include<stdio. readln(G).i . end. begin {main} write('Capacitatea rucsacului = ').tata. writeln('Profitul obtinut = '. în raport cu poziţiâ în care se află numărul 0. readln(n).profit).

} void RemoveAll(PNod *list){ PNod p. k < maxop. return pnod. *list = (*list)->down. if(i >= 0 && i < MAX && j >= 0 && j < MAX){ newNod = New(pnod). PNod newNod = NULL.typedef struct Nod{ char conf[MAX][MAX]. if (pnod==NULL){ printf("\nNot enough memory !\n"). }Nod. int h. PNod New(PNod p){ PNod pnod = (PNod) malloc( sizeof(Nod) ). i < MAX. ii. PNod list = NULL. struct Nod *down. jj. g. } } PNod Expand(PNod pnod){ int i.-1}. 1. while(*list){ p = *list. static int col[maxop] = { 0. j = jj + col[k]. k. j < MAX. exit(0).newNod). PNod pnod){ pnod->down = *list. *PNod. } 140 . for(i=0. 0. static int lin[maxop] = {-1.jj=j. newNod->conf[ii][jj] = newNod->conf[i][j]. Insert(&list.free(p). k++){ i = ii + lin[k]. } } return list. * up. } void Insert(PNod * list. newNod->conf[i][j] = 0. 0. i++) for(j=0. 0}. j. *list = pnod. for(k = 0. j++) if (pnod->conf[i][j]==0) ii=i. } *pnod = *p. 1.

} PNod Search(PNod list. pnod->conf[i][j]).. j. PNod fin){ int i. j < MAX. s < MAX. printf(" |"). } printf("\nApasati orice tasta .int Equals(PNod n1. s. r. return list.} list=list->down. k. getch(). i < MAX. return 1.} spy->down = temp->down. j++) for(r = 0. for (i = 0. for(i = 0. PNod n2){ int i. j.pnod)) list = list->down.j. j < MAX. i < MAX. min = f. PNod pmin = NULL. i < MAX. if (p==NULL || p == *list){ *list = (*list)->down. PrintNod(pnod). PNod pnod){ while (list && !Equals(list. for(j = 0. j++) if (n1->conf[i][j] != n2->conf[i][j]) return 0. return temp. while (list){ f = list->h + list->g. r < MAX.”).. } void PrintNod(PNod pnod){ int i. PNod p){ PNod temp = *list. j < MAX. s++) if (t->conf[i][j] == fin->conf[r][s]) t->h += abs(r-i) + abs(s-j). r++) for(s = 0. temp = temp->down. } void Print(PNod pnod){ if (pnod->up) Print(pnod->up). i++){ printf("\n|").} 141 . i++) for(j = 0. if ( f < min ){pmin = list. if (n1->h != n2->h) return 0. return temp. min = 32000.} return pmin.} PNod Choice(PNod list){ int f. spy = *list. t->h = 0. i++) for (j = 0. for(i = 0.} while(temp != p){ spy = temp. } PNod Extract(PNod * list. } void ComputeH(PNod t. j++) printf("%3d".

Nod *fin){ PNod Open = NULL. 9.10.0. 0}. Insert(&Close. 7. int ok = 0. 6. 0. 10. initial->g = 0. Pnod final = New(fin). 13. } else if( found = Search(Close. temp -> g = theOne->g + 1. } else{ temp->up = theOne. 13. RemoveAll(Open).} free(temp). 5. 8. Insert(&Open.NULL}. break. ComputeH(temp. } 142 . 4.14.12. PNod initial = New(in). temp) ){ if(temp->g < found->g){ found->g = temp->g.} } } if (ok){ printf("\nSolutie:\n").} free(temp).&fin). PNod TempList = NULL. while(TempList){ temp = Extract(&TempList. temp) ){ if(temp->g < found->g){ found-> g = temp->g. 3.final). 0. PNod Close = NULL. 3. 4.final).theOne). found).0. 2. } void main(){ Nod in = {{ 5. 15. 6. NULL.void Branch(Nod *in.NULL}. found). Insert(&Open. found.11. NULL. PNod theOne. Print(theOne). 0. RemoveAll(Close). getch(). found->up = theOne. temp. ComputeH(initial. 7. 14. if( found = Search(Open. final)){ok = 1. while(Open){ theOne = Choice(Open). 11. 1.} else printf("Nu am avem solutii !"). Insert(&Open. Branch(&in. Extract(&Close. 8.theOne). if (Equals(theOne. 12}.initial).} TempList = Expand(theOne). 2.temp). found->up = theOne. 9. clrscr(). Nod fin ={{ 1. Extract(&Open. final->h = 0.NULL).15.

O piesă se poate muta doar sărind peste o altă piesă într-un loc liber. ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ ◊ Configuraţia iniţială Configuraţia finală 3. Poziţia din centru este liberă.5. [Diamante] Se dă o tablă sub formă de cruce pe care sunt aşejate 32 de piese de diamant (◊) aşa cum se poate observa în figura de mai jos. [Buldozerul] Un teren de formă dreptunghiulară de dimensiuni m×n este împărţit în pătrate de dimensiuni egale (ca la şah). Să se găsească un loc de unde poate porni buldozerul şi ordinea de nivelare a pătratelor (în cazul în care există o soluţie) ştiind că acesta: • se deplasează doar pe direcţiile N. Un buldozer plasat într-un pătrat neted trebuie să niveleze tot terenul. Unele pătrate conţin grămezi de pamânt iar altele sunt netede. [Generalizare] Să se rezolve problema Perspico pentru o tablă de dimensiuni n x n cu numere de la 1 la n2-2 şi cu două zerouri (locuri libere). 2.3. Probleme propuse 1. numai pe orizontală sau pe verticală iar piesa peste care se sare trebuie luată. 143 . [Operaţii] Se dă un tablou m×n (1 ≤ m+n ≤15) cu elemente numere întregi.3. Se numeşte "operaţie" în acest tablou înmulţirea unei linii sau coloane cu -1. • nu se poate deplasa peste un loc neted. 4. V. E. Se cere să se gasească un şir de mutări astfel încât (să luăm cât mai multe piese de diamant) pornind de la configuraţia iniţială să se ajungă la o configuraţie finală care să conţină numai o singură piesă şi aceasta să se afle în centru. Să se determine cea mai mică secvenţă de operaţii care aduce tabloul la o formă în care toate sumele de linii sau coloane dau numere nenegative. S.

Problema constă în a aduce o configuraţie iniţială dată. antrenând cu el cele 13 bile din interiorul său.trece dintr-un loc neted peste pătratul cu pământ de lângă el în alt pătrat neted netezind astfel pătratul peste care a trecut. dar nu poate staţiona pe o poziţie ocupată de un cal sau de un obstacol. 5. Fiecare inel se poate roti în sensul acelor de ceasornic cel puţin o poziţie şi cel mult 12. un şir de mutări ale cailor astfel încât să se ajungă la o configuraţie finală dată. la configuraţia (finală) din figura următoare printr-un număr minim de rotiri. Jocul constă în a schimba între ele locurile ocupate de piesele 'O’ şi 'X' într-un număr minim de mutări. 7. Inelele au două bile în comun. dacă există. O piesă poate fi mutată numai pe orizontală şi pe verticală întrun loc liber învecinat. [Obstacole şi cai] Pe o tablă de şah n × n se găsesc p cai şi k obstacole amplasate într-o configuraţie iniţială dată. Să se determine. A 1 2 3 4 5 6 7 B O O O C O O O D O O X X X X X X X X E F G • 144 . [Inele] Fie două inele în care sunt aşezate echidistant 13 bile. 11 roşii şi două gri (ca în figura de mai jos). [Joc] Se dă o tablă de joc cu 31 de pătrate care conţine opt piese de ‘O’ şi opt piese de ‘X’ ca în figura de mai jos. 6. Deci în total vor fi 24 de bile din care 11 negre. Calul poate sări peste un obstacol sau peste un alt cal. sau prin săritură peste o altă piesă alăturată dacă se ajunge într-un loc liber. Mutarea calului este cea cunoscută de la şah.

Tehnici de programare. Acest material este disponibil in sectiunea Biblioteca virtuala. Se presupune cunoscut limbajul de programare C. L. Radu.2009 Probleme propuse 1. 2. Algoritmi si limbaje de programare. Averian. G. Editura FRM. Bibliografie 1. Editura FRM. (Capitolul 5). G. A. Colectia 2008 2. liste. arbori si definitii privind grafurile (introduce in cadrul cursurilor din anul I). Rapeanu. Probleme rezolvabile folosind metoda backtracking 3. . 2000.Tehnici avansate de programare .). L. Albeanu (coord. Probleme diverse Se presupun cunoscute structurile de date: tablouri. Albeanu. 2003 (capitolele 2 si 3).

a. q. Q d. p b. r c. p. Q. Q P P Q -> -> -> -> urm urm urm urm -> == -> == urm == P Q urm == Q P -> urm -> urm . a. p. r. Q. R. P c. c. R 3. R. P b. R. q. a. q. q. r. Q. p d. r 2. P. P.TEHNICI AVANSATE DE PROGRAMARE Exemple de subiecte – colectia 2008 1. d. b.

c. b. P P Q Q -> -> -> -> urm urm urm urm -> -> -> -> urm urm urm urm == == -> == Q -> urm Q urm == P -> urm P -> urm 5. P Q Q P -> -> -> -> URM URM URM URM = Q = P -> URM = P -> URM = Q 6. a. d.4. d. a. c. c. a. b. .

fiecare element retine in campul urm adresa urmatorului nod din lista. dupa executarea secventei de program: {p = prim. 6. Adresa carui nod va fi memorata in variabila p. free(p). 5. 8. free(p). while(p) {t=p. 7. iar in campul inf un numar intreg. 3.} d. Adresa primului element al listei este retinuta in variabila p. in urma executarii secventei de instructiuni (p indica. while(p) {t = p. 9. 9. initial. stabiliti care dintre urmatoarele secvente elibereaza intreaga zona de memorie ocupata de elementele listei. p -> urm = q. } } a. 6 b.} in lista vor fi in ordine numerele: a. 6. p->urm -> urm = q -> urm. a.} c. numerele: 5. 3. 3 c.} b. 9. while(p) {t = p. Intr-o lista liniara simplu inlantuita.b. d. 9. p = p -> urm. 5. 9 d. 5. Daca in lista sunt memorate. free(t). t=t->urm. Intr-o lista simplu inlantuita alocata dinamic fiecare element retine in campul nr un numar intreg si in campul urm adresa urmatorului element din lista. penultimul nod al listei . nodul cu numarul 5): { q = p -> urm -> urm. 3. in aceasta ordine. p = p->urm. 6 O lista liniara simplu inlantuita formata dintr-un numar impar de cel putin 5 noduri are adresa primului nod memorata in variabila prim. free(t). while(q->urm) { q = q -> urm -> urm. 9. In campul urm al fiecarui nod al listei se memoreaza adresa urmatorului element din lista. q->urm = p -> urm. 5. p = p->urm. 3. q = prim. Stiind ca variabila p contine adresa primului element din lista si variabila t este de acelasi tip cu variabila p. si 6 (6 fiind ultimul element).

Se stie ca lista are cel putin 3 noduri. p->next=p->next->next. ultimul nod al listei d. 11. a. Adresa primului element al listei este memorata in variabila prim. Care este efectul executarii urmatoarei secvente de program { p = prim. c.b. fiecare element retine in campul next adresa urmatorului nod din lista. Intr-o lista liniara. Intr-o lista simplu inlantuita. d. while (p->next->next->next) p = p->next. } b. while ( q-> next) {p = p->next. do p = p->next. iar in campul info un numar intreg. Adresa primului element al listei este memorata in variabila prim. fiecare element retine in campul next adresa urmatorului nod din lista. nodul al treilea din lista 10. { p = prim. } c. simplu inlantuita. Lista contine cel putin 3 noduri.} p -> next = q. prim -> next = prim->next -> next. Care dintre urmatoarele secvente de instructiuni elimina corect penultimul element al listei? a. nodul aflat in mijlocul listei c. p->next=p->next->next. while(p->next->next->next). while (p->next->next) p = p->next. p->next=p->next->next. } Eliminarea nodului din mijlocul listei Eliminarea din lista a ultimului nod. alocata dinamic. Eliminarea din lista a penultimului nod Eliminarea celui de-al doilea nod al listei . } d. q = q-> next. iar in campul info in numar intreg. q = p->next -> next. b. { p = prim. { p = prim. alocata dinamic.

} t = t->urm. p->adru = q -> adru. free (p->adru). fiecare element retine in campul nr un numar intreg si in campul urm adresa urmatorului element din lista. t -> nr. 8. iar in campul urm adresa elementului urmator din lista. q = p->adru. fiecare valoare fiind afisata exact odata. care este ordinea numerelor din lista? a. t = t->urm. . t = t->urm. q = p-> adru. t = p. 8. 3. 8 14. free(q). free(q). d. Fiecare element al unei liste liniare simplu inlantuite alocata dinamic retine in campul adru adresa elementului urmator din lista. 5. do{ printf(“%d “. while(t -> urm != p) { printf(“%d “. . t -> nr. }while(t != p). while(t != p) { printf(“%d “. Stiind ca q -> nr == 3. care dintre urmatoarele secvente dee instructiuni sterge al doilea element al listei? a. b.} b. stabiliti care dintre urmatoarele secvente afiseaza toate valorile memorate in nodurile listei. iar lista are cel putin doua elemente. 5 d. do{ printf(“%d “. p -> adru = p->adru -> adru. c. }while(t != p). r -> nr == 8. free(p->adru). t = p. Stiind ca variabila p retine adresa unui element din lista si variabila t este de acelasi tip cu p.} t = t->urm. t = p->urm. q -> urm != NULL. 3. Intr-o lista circulara simplu inlantuita alocata dinamic cu cel putin un element. Daca p retine adresa primului element. t = p. p ->adru = q->adru. t -> nr.} d. 5. O lista liniara simplu inlantuita alocata dinamic. in care fiecare element memoreaza in campul nr un numar intreg. p -> urm == NULL si r -> urm == q. q si r. 3 c. p -> nr == 5. contine exact trei elemente ale caror adrese sunt memorate in variabilele p. t -> nr. 5 b. c. 8. 3. a.12 13 .

15. 16.

Intr-o lista dublu inlantuita care incepe cu elementul memorat la adresa p si contine cel putin

4 elemente, fiecare element retine in campul urm adresa elementului urmator, in campul pre adresa elementului precedent, iar in campul inf o valoare intreaga. Care dintre urmatoarele variante tipareste valoarea celui de-al treilea element al listei? a. printf(“%d “, p->urm -> urm -> pre -> inf); b. printf(“%d “, p->urm -> urm -> urm -> pre -> inf); c. printf(“%d “, p->urm -> urm -> urm); d. printf(“%d “, p->urm -> urm);

Variabila p retine adresa unui element oarecare al unei liste circulare nevide alocata dinamic,

in care fiecare element memoreaza in campul nr un numar intreg, iar in campul urm adresa elementului urmator. Care dintre urmatoarele variante tipareste toate elementele listei? a. q = p; do{ printf(“%d”, q -> nr); q = q -> urm; } while (q != p); b. q = p; while (q -> urm != p){ printf(“%d”, q -> nr); q = q -> urm; } c. q = p; while (q != p){ printf(“%d”, q -> nr); q = q -> urm; } d. q = p->urm; while (q != p){ printf(“%d”, q -> nr); q = q -> urm; }

17.

Se considera o coada in care initial au fost introduse, in aceasta ordine, elementele 1 si 2.

Daca se noteaza cu AD(x) operatia prin care se adauga informatia x in coada, si cu EL() operatia prin care se elimina un element din coada, care este rezultatul executarii secventei: EL(); Ad(3); EL(); AD(4); AD(5);? a. 1, 4, 5 b. 5, 4, 2 c. 3, 4, 5 d. 5, 4, 3

18 19
.

Se considera o stiva in care initial au fost introduse, in aceasta ordine, valorile 1 si 2. Daca se

noteaza cu PUSH(x). operatia prin care se insereaza valoarea x in varful stivei si POP() operatia prin care se extrage elementul din varful stivei, care este continutul stivei in urma secventei de operatii: POP(); PUSH(3); POP(); PUSH(4); PUSH(5); a. 5 b. 5 c. 2 d. 1 4 4 3 4 3 1 5 5

In lista circulara simplu inlantuita ce contine numerele 1, 2, 3, 2, 3 in aceasta ordine, iar p

este adresa nodului ce contine primul numar 2 (fiecare nod are un camp nr ce contine numarul intreg si un camp urm care indica adresa elementului urmator din lista). Prin executarea secventei while (p -> nr > 0) {p -> nr = p -> nr -1; p = p -> urm;} continutul listei, citit de la adresa de plecare va fi: a. 0, 1, 0, 2,0 b. 1, 2, 1, 2, 0 c. 0, 1, 1, 2, 0 d. 0, 1, 0, 1, 0

20. 21.
a. 5 b. 2

Se considera ca variabilele p si q memoreaza adresa primului, respectiv ultimului element al

unei liste liniare nevide dublu inlantuite. Elementele listei retin in campul urm adresa elementului urmator, iar in campul prec adresa elementului anterior. Stabiliti care este numarul de noduri din lista daca p -> urm > urm si q -> prec -> prec indica acelasi nod al listei. a. 4 c. 3 b. 5 d. 2

Se considera lista circulara simplu inlantuita ce contine celulele cu numerele 1, 2, 3, 4 (in

aceasta ordine). Fiecare element memoreaza in campul nr un numar intreg, iar in campul urm adresa elementului urmator din lista. Variabila prim indica nodul ce contine numarul 1. Cate treceri sunt necesare pentru ca toate elementele din lista sa ajunga egale. Definim prin trecere prelucrarea data de secventa urmatoare: p = prim; do {if(p->nr > prim->nr) p->nr = p->nr -1; p = p -> urm;} while (p != prim); c. 3 d. 4

22 23

.

Intr-o lista circulara simplu inlantuita, p este adresa unui nod din lista si campul next

memoreaza pentru fiecare nod adresa nodului urmator din lista. Pentru a numara elementele listei vom scrie secventa (variabila q este de acelasi tip cu variabila p): a. q = p; k = 1; while(q -> next != p) {k++; q = q -> next;} b. q = p; k = 1; do{ q = q -> next; k++; } while(q ==p); c. q = p; k = 1; while(q!=p) {k++; q = q->next;} d. k=0; do{p=p->next; k++;} while (p!=NULL);

.

Se considera o stiva alocata dinamic care are cel putin 10 elemente. Variabila vf memoreaza

adresa de inceput a stivei si orice element al stivei memoreaza in campul info un numar intreg, iar in campul next adresa nodului urmator. Se considera seceventa de program: while (vf && vf -> info %2 == 0) { aux = vf; vf = aux-> next; free (aux); } Daca in urma executarii secventei de program, variabila vf are valoarea NULL, atunci: a. Primul element memorat in stiva este par, celelalte fiind numere impare. b. In stiva nu s-a memorat nici un numar impar. c. Ultimul element memorat in stiva este par, celelalte elemente fiind numere impare. d. In stiva nu s-a memorat nici un numar par.

24 25

.

Se considera o lista circulara cu 8 elemente numerotate cu 1, 2, 3, 4, 5, 6, 7, 8. Mai intai se

elimina elementul numerotat cu 3, apoi se elimina fiecare al treilea element al parcurgeri, numararea continuandu-se cu succesorul elementului eliminat, pana cand lista va mai contine un singur element. Care va fi numarul de ordine al elementului ramas? a. 2 c. 3 b. 7 d. 4

.

Se considera o lista circulara dublu inlantuita ale carei noduri retin in campul st adresa

nodului anterior, iar in campul dr adresa nodului urmator din lista. Lista are cel putin doua elemente. Stiind ca p retine adresa unui nod din lista, care este numarul de noduri din lista astfel incat relatia p->st->st == p->dr sa fie adevarata?

unde. 4 26 . respectiv adresa nodului urmator din lista. numerele: 7. 5. In campurile st si dr sunt retinute adresa nodului precedent. 3. 4. 6 b. q -> dr -> st = man -> st. 4. man -> st -> dr = q -> dr. 4 . 6. 2. 5. 6. man -> st -> dr = q -> dr. 4. O variabila ce retine adresa unui element este de tip nod. 6 c. Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar natural). 7.a. 8 c. 2 d. 3. 2. } a. 3. 8 27 . 7. 5. 6. O variabila ce retine adresa unui element este de tip nod. free(q). } a. Care va fi continutul listei la o parcurgere de la st la dr dupa apelul functiei sub(). respectiv adresa nodului urmator din lista. q -> dr -> st = man -> st. 7. 7. 6. numerele: 3. 5 b. functia sub este: void sub(){ nod *man = sf. 2. 5. 7. 6. 5. 6. 6. while(man->inf > sf -> inf /2) man = man ->st. in aceasta ordine.Variabilele globale p si sf retin adresele primului si respectiv ultimului element din lista. nod *q = man. 6. free(q). 7. nod *q = man. Care va fi continutul listei la o parcurgere de la st la dr dupa apelul functiei sub(). 5. 4. 4. 7. 3 c. 2. 7. 6 d. 4. in aceasta ordine. 5. while(man->inf > sf -> inf ) man = man ->st. 7. 6. Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar natural). In campurile st si dr sunt retinute adresa nodului precedent. 4. 5. 6. 8. 8 d.Variabilele globale p si sf retin adresele primului si respectiv ultimului element din lista. 5. functia sub este: void sub(){ nod *man = sf. 6. unde. 8 b.

9. Daca cel de-al doilea element. Atunci lista are a. } a. 7 29 30 31 . man -> st -> dr = q -> dr. q = p. q = q -> adr. do {nr ++. 2. 8. a[6] c. Se considera o stiva implementata prin intermediul vectorului a cu elementele a[0] = 0. while(man->inf > sf -> inf ) man = man ->st. while(q != p) {nr++. nr = 0. 7. cel putin 3 elemente b. a[4] = 40. O variabila ce retine adresa unui element este de tip nod. a[1] = 10. a[5] = 50. 9. 9. 8. q = q -> adr. nr = 0. 7. un numar impar de elemente c. 9. a[1] d. functia sub este: void sub(){ nod *man = sf. 2. In campurile st si dr sunt retinute adresa nodului precedent. free(q). Daca p si q sunt adresele a doua elemente distincte din lista astfel incat sunt satisfacute conditiile p == q -> adr si q == p -> adr. 2 b. fiecare element retine in campul adr adresa elementului urmator din lista. incepand de la baza stivei este 10. Daca p este o variabila care retine adresa primului element din lista. nod *q = man. Care va fi continutul listei la o parcurgere de la st la dr dupa apelul functiei sub(). Intr-o lista simplu inlantuita circulara. 8. numerele: 9. 4 c. 4 d. . exact 1 element . q = p. de tip int. 7. a[3] = 30.28 . care dintre urmatoarele secvente de instructiuni calculeaza in variabila nr. in aceasta ordine. 2. numarul de elemente al listei? a.} b. 2. exact 2 elemente d. a[2] = 20. 3. 3. a[0] .} while (q != p). Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar natural). unde. respectiv adresa nodului urmator din lista. fiecare nod retine in campul adr adresa elementului urmator din lista.Variabilele globale p si sf retin adresele primului si respectiv ultimului element din lista. 4. 7. Intr-o lista circulara simplu inlantuita. 8. atunci primul element care iese din stiva este: a. cu cel putin un element. q -> dr -> st = man -> st. a[5] b. 3. iar q este o variabila care poate sa retina adresa unui element din lista. 3.

p -> adr -> adr == NULL d. d. . while (p != q){ nr ++. 121 b. p = p -> adr. int b){return a%b. Intr-o lista circulara simplu inlantuita fiecare element retine in campul adr adresa elementului urmator din lista. 112 d. a.} int f(int a.j). Se considera urmatoarea functie recursiva apelata numai pentru numere naturale nenule: int f(int a.} while (q != p). q = p. c. j++) {printf(“%d”. int b){return a/b.} 32 33 a. else if (n == 1) return 4.} int f(int a. do {nr ++. int b){return a*b. q = p -> adr. Daca p reprezinta adresa unui element din lista atunci stabiliti care dintre urmatoarele expresii are valoarea 1 daca si numai daca lista contine exact doua noduri. } Care dintre urmatoarele functii este echivalenta cu functia data? int f(int a.} int f(int a. else return f(a-b. Se considera definitia: long f(int n){ if (n == 0) return 1.c. 1121 . nr = 0. nr = 0. p -> adr != NULL . d. b. Se considera definitia void f(int n){ int j. if (n>0) for (j=1. j<=n.} 34 35 . p -> adr == p c. q = p.} } Ce se afiseaza ca urmare a apelului f(2)? a. int b){return a-b+1. 1122 c. b). f(n-1). p -> adr -> adr == p b. int b){ if (a<b) return a. .

for (i=1. 40 d. a. -4 d. else return f(x. } Stabiliti ce valoasre returneaza apelul f(7).y-1). int k){ if (n == k || k == 1) return 1. 1 b. 45 . 4 36.3). i++) s+=f(n-k.10)? c. } } Pentru care dintre declaratiile urmatoare. if (v[i] == i+1) star(i+2). apelul star(0) produce 7 asteriscuri (stelute)? .y-1)+f(x-1. 3 b. 55 38 .i). a. } Ce valoare returneaza apelul f(8. 2 d. else star(i+1). c. i. i<=k. 50 b. Se considera definitia: long f(int x. -3 c.else return f(n-1) .f(n-2). long s=0. In functia recursiva de mai jos se considera ca tabloul unidimensional v este declarat global. return s. 4 37 a. if (n < k) return 0. int y){ if (x == y || x == 0) return 1. 1 Se considera definitia long f(int n. } Stabiliti ce valoare returneaza apelul f(6. void star(int i){ if(i<10) { printf(“*”).

6. ex(x/10).} } a. 7. else divi(i-1).. 2. n%(i-1)=0 si i b. b si c in definitia functiei G astfel incat in urma apelului G(0) sa se afiseze toate elementele produsului cartezian MxMxM? void G(int k){ int i. 012 b. void divi(long i){ if ( .a. 3. 2. 5. M este multimea tuturor cifrelor nenule. 9. c = 9 d. 120 . 5. 4. c = 2 . 4. 4. stabiliti ce se afiseaza la apelul ex(120)? void ex(int x){ if (x != 0){ printf(“%d”. i++) { p[k] = i. int v[] = {10. a = 1. 39 40 41 a. int v[] = {3. d.). Pentru definitia alaturata a functiei ex(). == 0) printf(“%ld”. la apelul divi(n). 9. x %10). b = 9. 2}. 2. 3. subprogramul urmator afiseaza cel mai mare divizor al lui n. 1. 4. Pentru o valoare naturala mai mare decat 1 memorata in variabila globala n. i<=b. 6. else G(k+1). 3. 4. 6. for (i = a. a = 1. iar functia tipar afiseaza valorile elementelot p[0]. mai mic decat n. c = 3 b. 2. a = 1. 9. 5. n%i si i-1 . b = 3. if (k == c) tipar(). Stiind ca p este un vector (tablou unidimensional) cu 3 componente intregi (tabloul este declarat global).. 6. 3. c. n% (i-1) si i-1 d. b = 10. p[1] si p[2]. 8. 10}. 8. 1. 21 . 7. } } c.. a = 0. n % i si i c. 1}. 3. 10}. 2. c = 3 c. . 021 d. b = 9. cu ce trebuie inlocuite simbolurile a. b. } Cu ce expresii trebuie completate punctele de suspensie? a. int v[] = {1. 7. int v[] = {1..

Atunci f(n) = c.9 f(n-2). Solutia relatiei de recurenta f(n) = 6 f(n-1) . (3n+3)7n a. unde f(0) = 2 c. (9n+9)7n d. 3n+1-n3n d. 230 b.7f(n-1) = 9(5n). 45 46 . n > 0. d. f(0) = 3. 231 43 b. 219 d. 3n-1-n3n .42. c. . f(0) = 8. 44 a. f(0) = 3. 3n-n3n-1 b. (9n+3)7n b. 3n+1-n3n-1 a. Se considera relatia de recurenta f(n) . f(0) = 1. a. n>0. . f(1) = 2 este f(n) = c. Solutia f(n) a relatiei de recurenta f(n) .7f(n-1) = 9(7n). Atunci f(n) = a. n>0. este c. n≥0. Se considera relatia de recurenbta neomogena de ordinul intai f(n) . 220 Gasiti elementul f(20) din sirul definit prin relatia (f(n))2 = 8(f(n-1))2. d.f(n-1) = 9n2. b. (3n+9)7n .

10 b. Un algoritm de tip backtracking genereaza in ordine lexicografica. se incearca alegerea unei noi valori pentru componenta xk-1. Aplicand metoda backtracking pentru a genera toate permutarile celor n elemente ale unei multimi. 01100 d. xn. 00110. toate sirurile de 5 cifre 0 si 1 cu proprietatea ca nu exista mai mult de doua cifre de 0 consecutive.. Numarul tuturor solutiilor generate va fi egal cu : a. d. o solutie se memoreaza sub forma unui tablou unidimensional x1. f(0)=1.. 01001. se incheie algoritmul. . 00101. Solutia relatiei de recurenta f(n) = 2f(n-1) . d. 32 d. oricare ar fi valoarea k. x2. . n>1. 5 c. b. 01110 c.4f(n-2). se incearca alegerea unei noi valori pentru componenta x1. 31 . iar pentru componenta xk (1 <k<n)au fost testate toate valorile posibile si nu a fost gasita niciuna convenabila. 48 49 50 . se incearca alegerea unei valori pentru componenta xk+1. f(1) = 3 este f(n) = c. b. Care este cea de-a opta solutie? a. Primele sase solutii generate sunt: 00100. 01010.. 01011 b. c... atunci: a.. x2.47 a. xk-1. . . Daca sunt deja generate valori pentru componentele x1. 01101 Un algoritm backtracking genereaza toate sirurile alcatuite din cate 5 cifre binare (0 si 1).

12}. Se considera multimea {1. {1. 15079. care dintre numerele de mai jos trebuie. {7. atunci. 12} . Se genereaza prin metoda backtracking toate submultimile sale formate din exact 3 elemente: primele patru solutii generate sunt. {1.. 16. 7. 12} b.3}. . 16. 19057. 7. {1}. 5) 2086. Care dintre solutii trebuie eliminate din sirul urmator astfel incat cele ramase sa apara in sir in ordinea generarii lor: {1.Selectati numarul care precede si numarul care urmeaza secventei de numere generate: 19075. in ordine: {1. 6) 2406 a. 5. 7.3}. 5. se utilizeaza un algoritm backtracking astfel incat se afiseaza in ordine.51 52 53 54 . atat 3) cat si 5) c. 71059 c. submultimile {}. formate din 4 cifre pare distincte. pentru n=3. 9} in care cifra din mijloc este 0. atat 3) cat si 4) d. 0. 51079. 5. 16. Daca pentru generarea tuturor submultimilor unei multimi A = {1. {2}. numai 4) .. 12}.. solutia a 7-a va fi: a. 2. {1. Se considera algoritmul care genereaza in ordine strict crescatoare toate numerele formate cu 5 cifre distincte alese din multimea {1. {1. {5. {4} . 16}. utilizand exact acelasi algoritm pentr n = 4. 5. {3}. 3) 2088. 2) 2084. {1. 16. 71095 . in ordine strict crescatoare. 5. 15097. 19057. 16} d. {7. 51097 a. {5. 2}. 5}. 5. 12}. Daca se utilizeaza metoda backtracking pentru a genera toate numerele naturale. 7. 12} c. 4) 2468. 16. 57019 b. numai 3) b. {7.3} b. 59071 d. n} cu 1 ≤ n ≤ 10. 2. 3}. {1. 12} a. 12}. {2. {7. 16}. in sirul submultimilor generate. 7. eliminate astfel incat cele ramase sa reprezinte o succesiune de numere corect generate? 1) 2068. {1.

3). 4. 3. 3. 2. 4). 5. ultimul termen 6 si diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2. in ordine crescatoare.2). 4).3). 11. e. c. 3. Care este numarul perechilor obtinute prin utilizarea aceluiasi algoritm la generarea produsului cartezian {1. 20. 6 . 4. (2. 2. Folosind aceeasi metoda generam toate sirurile strict crescatoare de numere naturale nenule mai mic sau egale cu 6. fiecare litera putand fi orice element din multimea {a. Generarea tuturor cuvintelor de 4 litere.3} este obtinut cu ajutorul unui algoritm backtracking care genereaza perechile (1. 210 . 6) se genereaza solutia (2. (3. penultima solutie generata este (2. v. etc. 201 d. 3. 81 b. 6) d. 6) se genereaza solutia (1.2. 1 si 2 putem genera.3} d. 3. 3. se realizeaza cu ajutorul unui algoritm echivalent cu algoritmul de generare a: a. 4). 4. Folosind acest algoritm generati numerele cu cifrele 0. 200. 120 b. Produsul cartezia {1. . 4. (1. numerele care au suma cifrelor egala cu 2 astfel: 2. (2. 2. ultimul termen 4 si cu diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2. produsului cartezian c. {1. Avand la dispozitie cifrele 0. (2. permutarilor .4} 55 56 57 58 . 4}x{2. Care va fi al saptelea numar din aceasta generare? a.2. 110. (2. 1002 c. 3.c. 1 si 2 care au suma cifrelor egala cu 3. partitiilor unei multimi b. imediat dupa solutia (1. 4}? a. 6) b. 2. (1. Se genereaza toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu 4.2). 5. care dintre afirmatiile urmatoare este adevarata: a. 10 d. 3. m.2) si (3. s}. 12 c. 3. combinarilor d.3}x{2.4). 6) c. 101. avand primul termen 1 sau 2. 4). in total sunt generate 13 solutii.3). avand primul termen 1 sau 2. (1. {1. obtinandu-se solutiile (1. imediat dupa solutia (1. 5.

1. 1. (3. (3. 2). Pentru a determina toate modalitatile de a scrie numarul 8 ca suma de numere naturale nenule distincte (abstractie facand de ordinea termenilor) se foloseste metoda backtracking obtinandu-se. atunci cel de-al treilea element generat este: a. (2. 1. 4). 3+5. Se considera multimile A = {1. d) . unde A = {a}. Se considera multimile A = {1. 1. 1. y) c. c) b. 1. 2). x) d. 3). toate solutiile 1+2+5. 1+7. 116. c = {x. c. y}. folosind metoda backtracking. 107. c. 6 . 2). Cate solutii de forma 1+ . 1. (a. 2. B ={a. (x. (3. in ordine astfel: (1. 2). in ordine. (x. 143 . B = {1}. (2. (2. 125. (1. 5 b. y. 3). se determina solutiile pentru scrierea numarului 10. 2. 4). 4}. 4 d. (1. (1. z) . Elementele produsului cartezian AxBxC se genereaza. 3). 3.. 3 c. 3). (2. 33. 4). z) b. (a. y. d}. (3. 3). (2. 1+3+4. 1. exista? a. 3. 125. Astfel pentru valorile k = 2 si s = 6 se genereaza numerele: 15. 1. Daca prin acelasi algoritm se genereaza produsul cartezian al multimilor AxBxC unde A = {x. 2+6. 42. 134. 134 d. 1. 1. 116. 4). z}. (3. 530 c. 2). 710. Care vor fi primele 4 numere ce se vor genera pentru k = 3 si s=8? a. 1. 1. 51. x. 3}. y. Folosind un algoritm de generare putem obtine numere naturale de k cifre care au suma cifrelor egala cu un numar natural s introdus de la tastatura. 1. x. 1. b. Aplicand exact acelasi procedeu. 3). 2). 341. (3. (1. C = {2. 4). C = {2. atunci cel de-al patrulea element generat este: a.59 60 61 62 . unde s si k sunt numere naturale nenule. 431 b. 620. B = {1}. Daca prin acelasi algoritm se genereaza produsul cartezian al multimilor AxBxC. b) c. 3}.. b. 1. B = {x}. 60. 4). 1. C = {b. (2. 233. b) d. (x. 1. 125. 800. in ordinea (1. Elementele produsului cartezian AxBxC se genereaza. b}. (x. (a. (a. c. 4}. 24.

cuvintele se genereaza in urmatoarea ordine: aa. 421. 5. 36 b. 5335. 40 d. Utilizand metoda backtracking se genereaza toate numerele palindrom formate din 4 cifre. 213. 431. 7. ee. 4. combinarilor d. 324. 3333. precizati care este numarul generat imedia dupa 4325. 231. 4321 . 412. c. permutarilor c. qa. feef b.63 64 65 66 . 432. f}. 5}. a. 3113. ea. fafe d. fiecare element avand cifre din multimea {1. 321. ce. 2. 3. e. 234. Fiecare numar contine cifre din multimea {1. ae. eq. 314. aranjamentelor . b413. Sa se precizeze cate numere pare se vor genera. 4. 1331. 423. 2. c. care este penultimul cuvant generat? a. 3. 9}. 124. q}. 4521 b. 8. Elementele sunt generate in urmatoarea ordine: 111. 312. 132. fiecare element putand fi oricare numar din multimea {1. 2. b. 5555. in aceasta ordine: 123. 6. astfel incat sa nu existe doua consoane alaturate in cuvant. Daca se utilizeaza exact aceeasi metoda pentru a genera cuvinte formate din 4 litere ale multimii {a. ca. d. qe. 2. 5}. 1551. se realizeaza cu ajutorul unui algoritm echivalent cu algoritmul de generare a: a. 4351 c. 3}. Daca utilizam acelasi algoritm pentru a genera toate numerele de 4 cifre. 3. produsului cartezian b. 99 c. 3. 214. 72 . 5115. 3553. 134. fiecare numar fiind format din cifre distincte din multimea {1. Cifrele fiecarui numar sunt din multimea {12. a. ec. astfel incat sa nu existe doua consoane alaturate. Utilizand metoda backtracking se genereaza toate numerele formate doar din trei cifre astfel incat fiecare numar sa aiba cifrele distincte. fefe . Generarea tuturor sirurilor formate din trei elemente. Daca se utilizeaza exact aceeasi metoda pentru a genera toate numerele palindrom formate din 4 cifre. 4}. ac. In utilizarea metodei backtracking pentru a genera toate cuvintele alcatuite din doua litere ale multimii {a. fefa c. aq. 5123 d. e. acest algoritm genereaza numerele.

.. 2. 6. 281 b. Precizati care dintre urmatoarele numere reprezinta o solutie a algoritmului? a. 2. Se genereaza toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu 4. 1) b. 7. 1) . b. 6. 1. 2. 5. 1. ultimul termen 4 si cu diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2. 4). 4. 3. 3.. Daca utilizam acest algoritm pentru a genera elementele produsului cartezian a 3 multimi: M = {1. care dintre afirmatiile urmatoare este adevarata: a. 8. 7. penultima solutie generata este (2. 4. 3.. (3. 455 . 8. 3. 5. 2. c2. fiecare solutie se exprima sub forma unui vector c = (c1. 2. (1. 3. 3. N = {1. 6. Utilizand metoda backtracking se genereaza toate numerele de cate 3 cifre astfel incat fiecare numar generat are cifrele distincte si suma lor este un numar par. 3}. 4. . A2. 235 c.67 68 69 70 . avand primul termen 1 sau 2. 2. 4. 5). generam toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu 5. 8. . 4} atunci care din urmatoarele secvente nu reprezinta o solutie acestui algoritm. 4. (2. 5) sa se determine solutia generata de algoritm imediat dupa solutia (8. c8) unde c1 reprezinta coloana pe care se afla dama de pe linia i. 5). a. (1. Stiind ca primele doua solutii generate sunt (1. 3) d. 4). imediat dupa solutia (2. (1. 5. 2} si P = {1. 986 d. 3. 5). 4. (7. 2. Folosind aceeasi metoda.. 3. 2. (2. 3. 7. 7. d. 6) . 5) d. 3. 3. 7. Utilizand metoda backtracking se genereaza elementele produsului cartezian a n multimi A1. 2. 1. 2. 4). 5. 4. c. 1. pentru produsul cartezian PxNxM? a. 1. (3. 2. 7) c. 3. (8. . 6. 6). 4). 4). in total sunt generate 5 solutii. 3. Utilizand metoda backtracking se genereaza in ordine lexicografica toate posibilitatile de aranjare a 8 dame pe tabla de sah astfel incat aceastea sa nu se atace. 5) se genereaza solutia (2. (8. 2. (4. An. 2. 6) b. obtinandu-se solutiile (1. 5. 3. 4). 5) se genereaza solutia (2. (8.. 3. (1. 1. 3) c. 4. imediat dupa solutia (1.

in aceasta ordine. 1 ≤ i ≤ n. O singura statie de servire (procesor. ticae b. 123323. numerele 122333. Stiind ca primele 2 solutii sunt aceit si aceti.. teica c. d. . Se considera graful ponderat din imaginea alaturata. pompa de benzina etc) trebuie sa satisfaca cererile a n clienti. Sunt 6 numere generate prin aceasta metoda care au prima cifra si a doua cifra 2. Imediat dupa numarul 332312 se genereaza 332321 b.333221.. selectam intotdeauna clientul cu timpul minim de servire din multimea de clienti ramasa . cifra 2 de cate doua ori si cifra 3 de trei ori. tieac d.. Penultimul numar generat este 333122.71 72 73 74 . c. . . Sunt 8 numere generate prin aceasta metoda care au prima cifra 1 si ultima cifra 2. Se obtin. Timpul de servire necesar fiecarui client este cunoscut in prealabil: pentru clientul i este necesar un timp ti. care din urmatoarele propozitii este adevarata? a. 123233. care este cuvantul generat inaintea cuvantului tiaec? a. Se genereaza in ordine crescatoare numerele de cate sase cifre care contin cifra 1 o singura data. Daca dorim sa minimizam timpul total de asteptare atunci a. selectam intotdeauna clientul cu timpul maxim de servire din multimea de clienti ramasa b. Utilizand metoda backtracking se genereaza in ordine lexicografica toate anagramele cuvantului caiet. tiace .

1. 2).Ordinea de selectare a muchiilor in vederea obtinerii unui arbore partial de cost minim. (2. iar prin 0 . Se doreste planificarea optimala (penalizarea totala sa fie minima) a 7 lucrari. 6). 25) 5: [10. 0. 6kg si 4kg. (6. (1. (1. (1. (2. Stiind ca i s-au propus 8 spectacole si pentru fiecare spectacol i-a fost anuntat intervalul in care se va desfasura: 1: [10. 7). 2. 8 76 77 . 5. (1.neselectarea acestuia): a. 1. Se considera datele de intrare: i t[i] p[i] 1 4 50 2 3 40 3 2 60 4 3 20 . (5. (5. (3. 5). 5). Managerul artistic al unui festival trebuie sa selecteze o multime cat mai ampla de spectacole care pot fi jucate in singura sala pe care o are la dispozitie. este: a. Stiind ca obiectele se incarca integral in sac si ca se poate alege cel mult un obiect din fiecare tip. 3. 1) b. 4) 75 . 1) d. 5. 7 d. 8) 8: [20. 5). 1. 3). atunci solutia optima este (se noteaza prin 1 . 4). (1. 2. Se considera ca trebuie transportate cu ajutorul unui rucsac de capacitate 10kg. Pentru fiecare kg transportat castigul obtinut este 1 LEU. 4). 2. 2). 5). 6. (4. 3). (6. 0) . (2.selectarea obiectului. 7) b. (3. 9) 4: [21. 15) 7: [7. 6). fiecare lucrare i fiind data prin termenul de predare t[i] si penalizarea p[i] care se plateste in cazul in care lucrarea nu este finalizata la timp. (4. 12) 6: [12. 8 c. 4) 3: [7. 1. 7). 4) c. (4. (0. Se presupune ca pentru executarea unei lucrari este necesara o unitate de timp si ca nu se pot executa doua lucrari in acelasi timp. (1. (1. obiecte cu greutatile 8kg. 4. 15) 2: [2. 7). 8 b. (1. 3. prin utilizarea strategiei Greedy de tip Kruskal. 1. 6. 0) c. (2. 27) Care spectacole trebuie selectate pentru a permite spectatorilor sa vizioneze un numar cat mai mare de spectacole? a.

7). 7. Fie tabloul unidimensional a in care elementele sunt. 2. se aplica metoda cautarii binare. 5. 21. 4. Se considera doua tablouri unidimensionale A si B: A = (1. numai secventei ii) b. 5. quicksort c. respectiv B = (2. 4. 10). 9 ii) 8. 8. 5. 10. 5. 4. 3 c. 7) . (1. numai secventei iii) d. 4. 7. fara alte prelucrari prealabile a. 9. 9. 5. (1. 2. 21. 6. 4. 10) d. interclasare b. cautare binara d. Pentru a verifica daca numarul x = 4 se afla printre elementele tabloului. 3. 9.5 4 70 6 2 10 7 1 130 Care este penalizarea totala minima ce se poate obtine? a. 5. atat secventei i) cat si secventei ii) . 3. 10. 3 . 20 d. 5 b. 7. 3. 7. Pentru cautarea unei valori intre elementele unui tablou ordonat descrescator vom utiliza utiliza un algoritm eficient de tip: a. 3. In urma interclasarii lor in ordine crescatoare se obtine tabloul cu elementele: a. 3. 2. 7. 2. 6. 7. 6. 5 d. 16. Care este succesiunea corecta de elemente cu care se compara x? a. 16. 3. 9 Algoritmul de cautare binara se poate aplica direct. numai secventei i) c. 5. Nu se poate realiza interclasarea b. 3. 6. 10. 5. (1. 9. in ordine 1. 70 78 79 80 81 . 1. backtracking . 4. 10 b. 1 iii) 2. 3. 3. 8. 6. 10) c. 5. Fie secventele de numere: i) 1. 130 c.

In cazul unei cautari cu succes se fac c. d. Fie S(n) numarul de comparatii necesar sortarii a n siruri de caractere prin metoda insertiei binare. Pentru rezolvarea problemei Turnurilor din Hanoi se poate utiliza: numai metoda backtracking numai metoda Divide et Impera numai metoda Gready numai metoda eliminarii stivei Atat metoda Divide et Impera cat si metoda eliminarii stivei 84 85 b. Se presupune ca n siruri de caractere sunt sortate prin metoda sortarii rapide (quicksort). Presupunand ca procesul de divizare se bazeaza pe metoda injumatatirii la fiecare pas. cel mult k comparatii d. 86 . O(n ln n) . exact k comparatii . n comparatii a. d. Atunci S(n) este a. c. atunci timpul cerut de algoritm este: a.82 83 a. . O(n log2n) b. b. Se considera metoda sortarii prin interclasare a n siruri de caractere in ordine lexicografica crescatoare. . c. Atunci T(n) = . k-1 comparatii b. e. Notam prin T(n) numarul mediu de comparatii pentru ordonarea lexicografica crescatoare a celor n siruri. O(n) c. O(n2) d. Se considera algoritmul cautarii binare si 2k-1≤ n ≤ 2k.

7. 3.. 1. 2.. . 9. 3. q) cu q-p ≤ ε. 6. unde prin 0 s-a notat lipsa descendentului corespunzator. . 1 . int (*f)(const void *. DR[i] - descendent drept) este ST = (2. 1. cu divizare binara.a. (1. 0. (p. unde ε este dimensiunea subproblemei ce se poate rezolva direct. (p. O2. 7. 1. q) cu q = p+1 d.. 5. Oq se reprezinta prin perechea (p. n) b. 2. 4. f este functie de comparare definita de c. 0.. Metoda Divide et impera. size_t dim. 8. 4. 7. 9. 0). Atunci prin parcurgerea in inordine. 6. 6.descendent stang. 9. 3. 3. 4. O(n ln n) d. pentru rezolvarea unei probleme relativ la obiectele O1. 7 d. 0. 0) si DR = (8. O(n) b. (n+1. 7. 0. 5. 0. 9 b. 6. 0. 3. Atunci: a. Daca fiecare secventa Op. q). 6. atunci varfurile terminale ale arborelui sunt etichetate cu: a. ∞) c. 0. 2. 5. O(n log2n) 87 88 89 .. Op+1. Se considera functia C din biblioteca standard: void * bsearch(const void *x. s este adresa elementului ce va fi cautat utilizator b. const void *s. 5. 9 c. n este numarul de componente ale sirului in care se face cautarea . 2. 8. 8. 4. 8. size_t n. 4. se poarte reprezenta sub forma unui arbore binar. const void *))... nodurile arborelui sunt vizitate astfel: a. O(n2) c. 5. . On. x este tabloul in care se cauta d. Se considera arborele binar a carui reprezentare standard (ST[i] . 0.

yx. {3. numere cu cifrele în ordine strict crescătoare.c.8}. eddb c.5}.x. aaf. 8 b.5}. ultimele trei submulţimi. yw. 4 d. 20 ii) Care este ultimul cuvânt generat? a. eded iii) Care este penultimul cuvânt generat? a. Care sunt. abbc.z.6.y} astfel încât niciun cuvânt să nu înceapă cu litera x şi niciun cuvânt să nu conţină litera w lângă litera z. {3. vi) Se utilizează metoda backtracking pentru a genera toate cuvintele formate din două litere distincte din muţimea {w.b. abac.x. cuvintele cu exact 3 litere din mulţimea {a.2. 3. abba.6. Cuvintele vor fi generate în ordinea wx. edcb v) Se generează. “ i) Câte dintre cuvintele generate încep cu litera b şi se termină cu litera e? a. {3. 9 b. în ordine: 123. zy. [Cuvinte] Urmatorul enunt este comun pentru intrebarile i). {3. în ordinea obţinerii.6}.y. 3 c. 127. abbd. 237. [Combinari] i) Folosind modelul combinărilor se generează numerele naturale cu câte trei cifre distincte din mulţimea {1. edeb d. “Utilizând metoda backtracking se generează în ordine lexicografică cuvintele de câte patru litere din mulţimea A={a. eeee c. edcb b. utilizând metoda bactracking. edcb iv) Care este antepenultimul cuvânt generat? a.6.5. {3.t} astfel încât niciun cuvânt să nu înceapă cu litera x şi niciun cuvânt să nu conţină litera w lângă litera z. generate după această regulă? . cuvinte care nu conţin două vocale alăturate.d. abbb. Primele şase submulţimi generate sunt. 2. 6 ii) Utilizând metoda backtracking se generează toate submuţimile mulţimii {3. 12 d. edde d. Dacă se utilizează exact aceeaşi tehnică pentru a genera numerele naturale cu patru cifre distincte din mulţimea {1. câte dintre numerele generate au prima cifră 2 şi ultima cifră 7? a. abbe. 137.3.6. aac.f. Dacă primele patru cuvinte generate sunt.2.x.Metoda backtracking (modele de subiecte) 1. Care este a treia şi a patra soluţie generată? 2. în ordine: abab.2}. abad. 7}.7.e}. edec b. edde b.5}.2}. scrieţi ultimele trei cuvinte care încep cu litera a.z.iv).c.g}. în ordine. aaa. edde d. aax.4. yz. 15 c. în ordinea în care vor fi generate. zx.2.6. obţinându-se. wy. Folosind aceeaşi metodă se generează toate cuvintele de două litere distincte din mulţimea {w. eded c. Primele opt cuvinte generate sunt. în ordine: {3}.

124. Folosind aceeaşi metodă. 4} care îndeplinesc aceeaşi condiţie. în ordine: 123. 212. numerele: 243. 103. 167 d. câte dintre numerele generate au prima cifră 1 şi ultima cifră 5? a. 105. 129.3. 127. 109. 123. 3. 234.4}. Folosind aceeaşi metodă se generează numere de patru cifre din mulţimea {1. 149 ii) Utilizând metoda backtracking sunt generate numerele de 3 cifre care au cifrele în ordine crescătoare. în ordine. 3. Care va fi al 4-lea număr generat ? a. 321 şi 323. 145. 3121 d. 312. numere cu cifrele în ordine strict crescătoare. [Numere cu trei cifre] i) Utilizând metoda backtracking sunt generate numerele de 3 cifre. Care va fi al 5-lea număr generat? a. Astfel. Astfel se obţin în ordine. 2 c. 2121 b. 123. care este cel de al 8-lea număr generat? a.2. se generează numerele pare formate din patru cifre distincte din mulţimea {1. 153 care este cel de-al patrulea număr generat? a. iar cifrele aflate pe poziţii consecutive sunt de paritate diferită. se generează numerele pare formate din patru cifre distincte din mulţimea {2.3. 147 iii) Utilizând metoda backtracking. în care cifrele alăturate au valori consecutive.2. obţinându-se. în această ordine. 5. 173 c. 157 b. 2323 .2. Ştiind că primele şase soluţii generate sunt. toate numerele formate din exact trei cifre.2. 123. 125. 149 c. 2123 c. 357 v) Folosind cifrele {1.3. 2. 3452 b. în această ordine.3} se generează. Folosind aceeaşi metodă. 1432 c.iii) Folosind modelul combinărilor se generează numerele naturale cu câte trei cifre distincte din mulţimea {1. toate numerele pare formate din trei cifre distincte. 1423 vi) Folosind cifrele {2. Ştiind că primele cinci soluţii generate sunt.4.4}. 3524 c. 147 c. în acestă ordine: 135. numerele: 121. în ordinea crescătoare a valorii. în ordinea crescătoare a valorii.3. 125. 127. în ordinea crescătoare a valorii. iar cifrele aflate pe poziţii consecutive sunt de paritate diferită. 2134 b. Dacă se utilizează exact aceeaşi tehnică pentru a genera numerele naturale cu câte patru cifre distincte din mulţimea {1. 2534 d. în această ordine.5}. 123. 145 b.5}.4. Ştiind că primele trei soluţii generate sunt. care este a zecea soluţie generată? a. sunt generate toate numerele de 3 cifre. 134. Care va fi al 5-lea număr generat? a. 3 3. 6 d.3.2. numerele: 132. 2314 d. 3542 vii) Folosind cifrele {1. 7}.3} se generează. 230 d. 315 d. se obţin în ordine. 4 b. 232. toate numerele impare formate din trei cifre distincte. având toate cifrele distincte şi cu proprietatea că cifrele aflate pe poziţii consecutive sunt de paritate diferită. Astfel se obţin. 125. astfel încât cifrele sunt în ordine crescătoare.4} se generează. 169 b. 423. 137. 107. câte dintre toate numerele generate au suma cifrelor egală cu 6? iv) Utilizând metoda backtracking se generează numerele formate din câte 3 cifre distincte din mulţimea {1. Dacă primele trei numere generate sunt.

cifrele fiind în ordine strict crescătoare. numerele .viii) Folosind cifrele {2. primele 5 soluţii generate sunt 10325. precizaţi care sunt ultimele 3 soluţii generate. 10347. 3425 b. cu cifre distincte. 4}. precizaţi care sunt următoarele 3 soluţii generate. 2413 b. în ordinea generării. 2431 d. ______________________ iv) Un algoritm generează în ordine crescătoare. 22. 100 c. Ştiind că primele 5 soluţii generate sunt 56789. în ordine. 80.3} se generează. câte dintre numerele generate au prima cifră 4? ___________ ii) Un algoritm generează în ordine crescătoare toate numerele de n cifre. 10327. care nu au două cifre pare alăturate. 3245 ix) Folosind cifrele {1. ______________________ v) Un algoritm generează în ordine descrescătoare. toate numerele pare formate din trei cifre distincte. 82. toate numerele impare formate din trei cifre distincte. 213. 324. care nu au două cifre pare alăturate. în ordinea crescătoare a valorii. numerele: 234. toate numerele de n cifre (n<9). câte numere au fost generate de catre program? __________ b) Pentru n egal cu 5. 8} se utilizează un algoritm backtracking care. primele 5 soluţii generate sunt 33333. se generează numerele impare formate din patru cifre distincte din mulţimea {1. în ordinea crescătoare a valorii. Dacă pentru n=5. 342. Dacă n=4 şi se utilizează acelaşi algoritm. 231. fiecare dintre ele având cifrele în ordine strict crescătoare. se generează numerele impare formate din patru cifre distincte din mulţimea {2. 2. pentru n=2. în ordine. 6 d. pentru n=2. 33355. 3. precizaţi care sunt următoarele 3 soluţii generate. 45789. 1423 c. 2543 c. [Numere de orice lungime] i) Folosind tehnica backtracking. 321. 45679. 45678. în ordinea obţinerii lor. a) Dacă n este egal cu 5.5}. 10345. 432. primele 5 soluţii generate sunt 56789.4} se generează. 88. Folosind aceeaşi metodă. 28. în ordine. 601 b. Care va fi al 5-lea număr generat? a. în ordinea generării. folosind doar cifrele 3. 8} se utilizează un algoritm backtracking care. în ordinea obţinerii lor. precizaţi care sunt ultimele 3 soluţii generate. 45689. 33353. numerele 20. 10 vii) Pentru generarea numerelor cu n cifre formate cu elementele mulţimii {0. 45679. 4. Dacă pentru n=5. numerele: 123.4. 33337. în ordine. ______________ vi) Pentru generarea numerelor cu n cifre formate cu elementele mulţimii {0. 45789. 33335. cu cifrele în ordine strict crescătoare. Astfel se obţin. Care va fi al 5-lea număr generat ? a. 10329. 4235 d. 2.3.2. 46789. ati scris un program care generează toate numerele de câte n cifre (0<n≤9). in timpul pregatirii examenului. Dacă pentru n=5. generează. generează. Astfel se obţin.3. precizaţi câte numere generate sunt divizibile cu 100? a. Folosind aceeaşi metodă. toate numerele de n cifre (n<9). 5 şi 7. ____________________ iii) Un algoritm generează în ordine descrescătoare toate numerele de 5 cifre. 36789. 3241 4.

65987 şi 67988 xi) Se generează în ordine crescătoare toate numerele de exact 4 cifre care se pot forma cu elementele mulţimii {0. 13452 ix) Se generează în ordine crescătoare. 4080 d. 8979 b. numerele naturale de exact 5 cifre din mulţimea {1. 1. 1057. Să se precizeze numărul generat imediat înaintea şi numărul generat imediat după secvenţa următoare : 67589. 1463. 1035.6. 8976 xiii) Se generează în ordine crescătoare toate numerele de 4 cifre. 84. 4}.3. 80. 1243. care se pot forma cu cifrele 2.4. 3444. 4000. Primele 8 soluţii generate sunt. Fiecare dintre numerele generate are cifrele distincte două câte două. 4000 d. 1010. 65978 şi 67988 c. 2. 4004 c. 3. toate numerele naturale de 5 cifre distincte. 12354. Care dintre următoarele numere se va genera imediat după numărul 8975? a.67598.67895. 4. 9207 d. cu cifre distincte. 1064.8 şi 9. 44. 32654 şi 34655 c. 8957 d. în ordine crescătoare. 1046. 1793. 4444 c. Primele opt soluţii generate sunt. în ordine: 1023. 34562: a. 4040 b. 3444. Primele 11 soluţii generate sunt. 1203. 9357 c. 5}. 13245 d. 1012. Care este numărul generat imediat după 12543? a. 1011. care se pot forma cu cifrele 5. 34265. 3. 1042. 2. 4444. 4000. 1002. care este numărul generat imediat după numărul 4008 ? a.40. 48. Care sunt primele trei numere ce se vor genera imediat după numărul 3443? a. 8004 viii) Un program generează. 1003. 12435. 1004. Primele 3 numere astfel generate sunt: 12345. astfel încât diferenţa în valoare absolută dintre ultimele două cifre ale fiecărui număr generat este egală cu 2. a. respectiv a doua şi a treia cifră este egală cu 2. 88. 32645 şi 34625 b. 1068. 1643. 15342 b. cu cifre distincte. Să se precizeze numărul generat imediat înaintea şi numărul generat imediat după secvenţa următoare : 34256. 1573. 4001. 4002 b. 9247 b. 32654 şi 34625 d.5 şi 6. 4001 xii) Se generează în ordine crescătoare toate numerele de 4 cifre. Care dintre următoarele numere se va genera imediat înaintea numărului 9317? a. 1053. toate numerele naturale de 5 cifre distincte. 1753. 12534 c. 4443. 1863. 1001. 65978 şi 67958 d. 9013 c.7. astfel încât diferenţa în valoare absolută dintre prima şi ultima.67859. 34526. Dacă n=4 şi se utilizează acelaşi algoritm. 1683. în ordine: 1024. 65987 şi 67958 b. în ordine: 1000. 9024 . 32645 şi 34655 x) Se generează în ordine crescătoare. 1423. 3444.

3+7. 00111. în ordine lexicografică. în ordine crescătoare lexicografic. Astfel. 01100 c. în ordinea obţinerii lor. 00011. în ordine descrescătoare lexicografic. Soluţiile se generează în ordinea: . 60. Astfel. Folosind acelaşi algoritm. Folosind exact aceeaşi metodă.1}. 01. în ordinea generării lor? ______ ii) Folosind un algoritm de generare putem obţine numere naturale de k cifre care au suma cifrelor egală cu un număr natural s. 00010. 2 şi 3 care au suma cifrelor egală cu 4.1}. 101. toate şirurile de 5 cifre 0 şi 1 cu proprietatea că nu există mai mult de două cifre 0 pe poziţii consecutive. 1022 c.xiv) Având la dispoziţie cifrele 0. 01. pentru valorile k=2 şi s=6 se generează. Care va fi al treilea număr generat pentru k=4 şi s=5? a. Care va fi al 7-lea număr din această generare? a. 110. pentru n=2. 2201 d. 01010100 d. 01010. 2+2+3+3. primele 6 soluţii sunt 2. Ştiind că pentru n=5. sumele distincte: 2+2+2+2+2. 200. 01011. toate şirurile alcătuite din câte n cifre binare (0 şi 1). 51. toate combinaţiile de n cifre care aparţin mulţimii {0. 1 şi 2 se pot genera. 01011 d. Astfel. 10100111 c. numere care au suma cifrelor egală cu 2. 00110. 20. 11. în ordine lexicografică. 01001. primele 4 soluţii generate sunt 00000. 5+5. Termenii descompunerii sunt în ordine strict crescătoare. 11. Care sunt primele trei soluţii. în această ordine. 00001. [Secvente de suma data] i) Pentru a scrie valoarea 10 ca sumă de numere prime se foloseşte metoda backtracking şi se generează. 10. 10. 1. se scrie valoarea 9 ca sumă de numere prime. [Siruri de biti] i) Un algoritm de tip backtracking generează. 011011011 d. Dacă se rulează acest program şi se citeşte pentru n valoarea 9. 011100100 b. 01010111 b. Primele 7 soluţii generate sunt: 00100. 10100100 6. 301 c. în ordine crescătoare. _____________________ iii) Un program citeşte o valoare naturală nenulă pentru n şi apoi generează şi afişează. Astfel. combinaţiile sunt afişate în următoarea ordine: 11. 220 d. 01101 ii) Un algoritm generează. în ordine. 1031 iii) Utilizăm metoda backtracking pentru generarea tuturor modalităţilor de a scrie numărul 9 ca sumă a cel puţin două numere naturale nenule distincte. 103 5. 00. 011011100 c. 011100000 iv) Un program citeşte o valoare naturală nenulă pentru n şi apoi generează şi afişează. se generează numere cu cifrele 0. 1301 b. toate combinaţiile formate din n cifre care aparţin mulţimii {0. 42. precizaţi care sunt ultimele 3 soluţii generate. imediat după combinaţia 011011011 va fi afişată combinaţia: a. 2+3+5. numerele: 15. 24. 33. 01110 b. Care este a 8-a soluţie generată de acest algoritm? a. Dacă se rulează acest program şi se citeşte pentru n valoarea 8. pentru n=2. 130 b. 00101. combinaţiile sunt afişate în următoarea ordine: 00. imediat după combinaţia 10101000 va fi afişată combinaţia: a.

Ordinea de scriere a termenilor dintr-o descompunere este semnificativă. Dacă utilizăm acelaşi algoritm pentru a genera toate numerele de 4 cifre care au suma cifrelor egală cu 7. 53421 b.5}. 54213. 2+3+4. 3 b. x[k-1]} b. Soluţiile se generează în ordinea: 1+2+6. 130.n} prin metoda backtracking. 2 b. 4 c. Folosind aceeaşi metodă pentru n=10. 2+2+2. x[k]∉{x[1]. Primele patru permutări generate sunt: 54321. 2+4 şi 3+3. 2+3+4. vor fi generate? a. 54231.1+2+6. 1+1+1+1+2. Se aplică exact aceeaşi metodă pentru scrierea lui 9.…. Se aplică exact aceeaşi metodă pentru scrierea lui 9. 1+2... Termenii fiecărei sume sunt în ordine crescătoare. Termenii fiecărei sume sunt în ordine strict crescătoare. 4+5 d. 2+4 şi 3+3. 121.3. precizaţi care este numărul generat imediat după 1222. 112. 5 v) Utilizăm metoda backtracking pentru generarea tuturor modalităţilor de a scrie numărul 6 ca sumă a cel puţin două numere naturale nenule. Termenii fiecărei sume sunt în ordine crescătoare. 211. 400. 1+1+1+3. a. 3+6 c. 1+1+4+1+1+1+1 b. 1+1+4+4 7. 5 vii) Utilizând metoda backtracking. 3. în ordine. 3+6 şi 4+5. …. în tabloul unidimensional x este plasat un element x[k] (1≤k≤n). 1+1+4. 202. 1+3+5. Soluţiile se generează în ordinea: 1+1+1+1+1+1. 1+1+1+1+2. Scrieţi. 6 d. …. 54123 .2. 1+8.4. în ordinea generării. 1+1+1+3. Câte soluţii vor fi generate? a. 1+5. x[k]≠x[k-1] c. care este soluţia generată imediat după 1+1+3+5? a. 2+1. Acesta este considerat valid dacă este îndeplinită condiţia: a. x[k]≠x[k-1] şi x[k]≠x[k+1] ii) Se utilizează un algoritm pentru a genera în ordine lexicografică inversă toate permutările mulţimii {1. x[n]} d. 1+5. 54312. 301. 2+2+2. Soluţiile se generează în ordinea: 1+1+1+1+1+1. în această ordine: 103. 2+7. 3 c. 1223 c. pentru n=3 se obţin. soluţiile: 1+1+1. 1+1+4. 220. 3+3+3 b. 54321 c. Se aplică exact aceeaşi metodă pentru scrierea lui 8. 54132 d. iv) Utilizăm metoda backtracking pentru generarea tuturor modalităţilor de a scrie numărul 9 ca sumă a cel puţin două numere naturale nenule distincte. A cincea permutare este: a. 1+2+7 d. 1+3+5.. x[k]∉{x[1]. 1231 b. 310. 1321 ix) Utilizând metoda backtracking pentru afişarea tuturor modalităţilor de descompunere a unui număr natural ca o sumă de numere naturale nenule. 4 d. Se aplică exact aceeaşi metodă pentru scrierea lui 12. 1213 d. x[2].2. Câte soluţii de forma 2+. 2+7. 1+8. 1+1+7+1 c. Care este penultima soluţie? a. 2+7 vi) Utilizăm metoda backtracking pentru generarea tuturor modalităţilor de a scrie numărul 6 ca sumă a cel puţin două numere naturale nenule. toate soluţiile de forma 2+.. [Permutari] i) In timpul procesului de generare a permutărilor mulţimii {1. se generează numerele naturale formate din exact 3 cifre şi care au suma cifrelor egală cu 4. 3+6 şi 4+5. x[2].

iii) Utilizând metoda backtracking se generează toate permutările mulţimii {1,2,3,4}. Dacă primele trei permutări generate sunt, în acestă ordine: 1234, 1243, 1324 precizaţi care este permutarea generată imediat după 3412. a. 3421 b. 3413 c. 4123 d. 3214 iv) Utilizând metoda backtracking se generează permutările cuvântului info. Dacă primele trei soluţii generate sunt: fino, fion, fnio care este cea de-a cincea soluţie? a. foin b. fnoi c. foni d. ifon v) Dacă se utilizează metoda backtracking pentru a genera toate permutările de 4 obiecte şi primele 5 permutări generate sunt, în această ordine, 4 3 2 1, 4 3 1 2, 4 2 3 1, 4 2 1 3, 4 1 3 2, atunci a 6-a permutare este: a. 3 2 1 4 b. 3 4 2 1 c. 1 4 3 2 d. 4 1 2 3 8. [Recunoasterea mecanismelor enumerative] i) Algoritmul de generare a tuturor numerelor de 5 cifre nenule, fiecare având cifrele ordonate strict crescător, este echivalent cu algoritmul de generare a: a. submulţimilor unei mulţimi cu 5 elemente b. produsului cartezian a unor mulţimi decifre c. aranjamentelor de 9 elemente luate câte 5 d. combinărilor de 9 elemente luate câte 5 ii) Generarea tuturor cuvintelor de trei litere mici, nu neapărat distincte, ale alfabetului englez, se poate realiza cu ajutorul unui algoritm echivalent cu cel de generare a: a. produsului cartezian b. combinărilor c. aranjamentelor d. permutărilor iii) Pentru generarea tuturor mulţimilor de câte 5 cifre, având la dispoziţie cifrele de la 1 la 9, se poate utilza un algoritm echivalent cu algoritmul de generare a: a. permutărilor de 5 elemente b. submulţimilor mulţimii {1,2,3,4,5,6,7,8,9} c. combinărilor de 9 elemente luate câte 5 d. aranjamentelor de 9 elemente luate câte 5 iv) Pentru a genera toate numerele naturale cu exact 4 cifre şi care au cifrele în ordine strict descrescătoare, se poate utiliza un algoritm echivalent cu cel pentru generarea: a. aranjamentelor de 4 obiecte luate câte 10 b. combinărilor de 10 obiecte luate câte 4 c. permutărilor a 10 obiecte d. permutărilor a 4 obiecte v) Generarea matricelor pătratice de ordinul n, cu elemente 0 şi 1, cu proprietatea că pe fiecare linie şi pe fiecare coloană există un singur element egal cu 1, se poate realiza utilizând metoda backtracking. Algoritmul utilizat este echivalent cu algoritmul de generare a: a. combinărilor

b. permutărilor c. aranjamentelor d. produsului cartezian vi) Pentru rezolvarea cărei probleme dintre cele enumerate mai jos se poate utiliza metoda backtracking ? a. determinarea reuniunii a 3 mulţimi b. determinarea tuturor divizorilor unui număr din 3 cifre c. determinarea tuturor elementelor mai mici decât 30000 din şirul lui Fibonacci d. având 3 culori (”roşu”, ”galben”, ”albastru”), determinarea tuturor variantelor în care se pot genera toate steagurile cu 3 culori având la mijloc culoarea ”galben” vii) La un concurs sportiv sunt 5 echipe, iar în fiecare echipă sunt câte 10 elevi. Problema determinării tuturor grupelor de câte 5 elevi, câte unul din fiecare echipă, este similară cu generarea tuturor: a. elementelor produsului cartezian AxAxAxAxA, unde A={1,2,…,10} b. submulţimilor cu 5 elemente ale mulţimii {1,2,…,10} c. permutărilor mulţimii {1,2,3,4,5} d. partiţiilor mulţimii {1,2,…,10} viii) Problema generării tuturor codurilor formate din exact 4 cifre nenule, cu toate cifrele distincte două câte două, este similară cu generarea tuturor: a. aranjamentelor de 9 elemente luate câte 4 b. permutărilor elementelor unei mulţimi cu 4 elemente c. elementelor produsului cartezian AxAxAxA unde A este o mulţime cu 9 elemente d. submulţimilor cu 4 elemente ale mulţimii {1,2,3,4,5,6,7,8,9} ix) Cu studentii unei grupe 28 de studenti se doreşte formarea unei echipă de 4 persoane. Ordinea studentilor în cadrul echipei nu are importanţă. Algoritmul de generare a tuturor posibilităţilor de a forma o asfel de echipă este similar cu algoritmul de generare a tuturor: a. aranjamentelor de 28 de elemente luate câte 4 b. combinărilor de 28 de elemente luate câte 4 c. partiţiilor unei mulţimi d. elementelor produsului cartezian AxAxAxA, A fiind o mulţime cu 28 de elemente x) La examenul de licenta, un absolvent primeşte un test format dintr-un subiect de tip I, unul de tip II şi unul de tip III. Stiind că pentru fiecare tip de subiect sunt elaborate exact 50 de variante, algoritmul de generare a tuturor posibilităţilor de a forma un test este similar cu algoritmul de generare a: a. elementelor produsului cartezian b. aranjamentelor c. permutărilor d. submulţimilor xi) Trei studenti vor să înfiinţeze o echipa pentru a participa la un concurs de informatica formată dintr-un programator PHP, un specialist multimedia şi un specialist in baze de date. Toţi trei ştiu să cânte atât la PHP, cât şi la multimedia, şi se pricep cu toţii şi la baze de date. Algoritmul de generare a tuturor posibilităţilor de a forma echipa este similar cu algoritmul de generare a:

a. aranjamentelor b. permutărilor c. elementelor produsului cartezian d. submulţimilor 9. [Siruri de caractere] i) Generând şirurile de maximum 3 caractere distincte din mulţimea {A,B,C,D,E}, ordonate lexicografic, obţinem succesiv: A, AB, ABC, ABD,…. Ce şir va fi generat după BAE? a. BCA b. CAB c. BC d. BEA ii) Utilizând metoda backtracking se generează toate cuvintele de câte 3 litere din mulţimea {a,b,c}. Dacă primele patru cuvinte generate sunt, în acestă ordine: aaa, aab, aac, aba, care este cel de-al optulea cuvânt generat? a. acb b. acc c. aca d. bca iii) Se utilizează metoda backtracking pentru a genera toate cuvintele de câte patru litere distincte din mulţimea {d,a,n,s}. Ştiind că al doilea cuvânt generat este dans, iar al treilea este dsan, care va fi ultimul cuvânt obţinut? a. nsad b. snad c. snda d. dans iv) Se utilizează metoda backtracking pentru a genera toate cuvintele de câte trei litere distincte din mulţimea {i,n,f,o}. Ştiind că ultimele trei cuvinte generate sunt, în ordine, ion, inf şi ino, care este cel de-al doilea cuvânt obţinut? a. ofn b. ifo c. foi d. nif v) Se utilizează metoda backtracking pentru a genera toate cuvintele care conţin toate literele din mulţimea {i,n,f,o}, astfel încât fiecare literă să apară exact o dat într-un cuvânt. Ştiind că al doilea cuvânt generat este info iar al treilea este ionf, care este ultimul cuvânt obţinut? a. nifo b. ofni c. ofin d. foni vi) Se utilizează metoda backtracking pentru a genera toate cuvintele care conţin toate literele din mulţimea {i,n,f,o}, astfel încât fiecare literă să apară exact o dat într-un cuvânt şi literele n şi o să nu se afle pe poziţii vecine. Ştiind că primul cuvânt generat este info, iar al treilea este nifo care este cel de-al doilea cuvânt obţinut? a. iofn b. inof c. ionf d. niof 10 [Numarare …] i) Câte numere cu exact 3 cifre pot fi construite folosind doar cifre pare? a. 125 b. 100 c. 64 d. 128 ii) În câte dintre permutările elementelor mulţimii {‘I’,’N’,’F’,’O’} vocalele apar pe poziţii consecutive? a. 24 b. 6 c. 12 d. 4

’N’. . 0123210 c. pentru n=5. [Probleme diverse] i) Un program citeşte o valoare naturală nenulă impară pentru n şi apoi generează şi afişează în ordine crescătoare lexicografic toate combinaţiile formate din n cifre care îndeplinesc următoarele proprietăţi: . 15 vii) Prin metoda backtracking se generează toate anagramele (cuvintele obţinute prin permutarea literelor) unui cuvânt dat. Permutând cifrele lui x se obţin alte numere naturale. u)? a. în ordine. 0121010 ii) Pentru generarea numerelor cu n cifre formate cu elementele mulţimii {0. printer cifrele sale se găseşte şi cifra 0. se generează în ordine lexicografică toate anagramele cuvântului caiet ( cuvinte formate din aceleaşi litere.conţin doar valori pozitive sau nule. 0121210 b. au exact 8 cifre? ______ iv) Utilizând metoda backtracking. 5 vi) Se utilizează metoda backtracking pentru a genera toate submulţimile cu p elemente ale unei mulţimi cu m elemente. e.3. 24 c.’O’} vocala ‘I’ apare pe prima poziţie? a.3}{2}. Ştiind că se aplică această metodă pentru cuvântul pescar.2.4} stabiliţi câte dintre soluţiile generate vor fi alcătuite din exact trei submulţimi. prin metoda backtracking. 1 b.3}. imediat după combinaţia 0101210 va fi afişată combinaţia: a.2. {1. prima soluţie e alcătuită din exact trei submulţimi. Câte cuvinte vor fi generate? a. în ordine. următoarele: 01010.28. inclusiv x. 2080 d. generează. 5 d.încep şi se termină cu 0. 12 c. Dacă se foloseşte aceeaşi metodă pentru a genera partiţiile mulţimii {1. 96 b. Astfel. Dacă se executa acest program şi se citeşte pentru n valoarea 7. care este numărul generat imediat după numărul 2008 ? a.80. 2002 b. 200 d. combinaţiile afişate sunt. 60 b. 24 c. Dacă m=7 şi p=4 atunci numărul de submulţimi generate este: a.2. i . toate partiţiile mulţimii A={1.3}.modulul diferenţei între oricare două cifre alăturate dintr-o combinaţie este 1.2}{3}.3} obţinându-se următoarele soluţii: {1}{2}{3}. . 8002 . a. 120 v) Se generează. 60 b. Câte dintre numerele obţinute.’F’.88. 01210.22. 12 11. Dacă n=4 şi se utilizează acelaşi algoritm. Se observă că dintre acestea. 8} se utilizează un algoritm backtracking care. 0111210 d. {1.82. pentru n=2. 48 d. precizaţi câte cuvinte se vor genera astfel încât prima şi ultima literă din fiecare cuvânt generat să fie vocală (sunt considerate vocale caracterele a. 2. 6 d. 6 d. {1. 12 viii) În câte dintre permutările elementelor mulţimii {‘I’. distincte două câte două. eventual în altă ordine). {1}{2. numerele 20. 3 b. o. 100 c.iii) Se consideră un număr natural nenul x având exact 8 cifre. 2020 c. 35 c.

4}. eventual în altă ordine). 110. în această ordine. 18. 123323. 7}. 4}. 6}. {3. Câte numere generate prin această metodă au prima cifră 1 şi ultima cifră 2? ________________ vii) Se generează în ordine strict crescătoare toate numerele de câte şase cifre care conţin: cifra 1 o singură dată. 123233. numere care au suma cifrelor egală cu 2 astfel încât primele 6 numere generate sunt. {2. 46. Folosind aceeaşi metodă pentru a genera mulţimile distincte ale căror elemente sunt numere naturale nenule şi care au proprietatea că suma elementelor fiecărei mulţimi este egală cu 9. 6}. {1. Se obţin. 130 iv) Completarea unui bilet de LOTO presupune colorarea a 6 numere dintre cele 49. 36. cifra 2 de două ori şi cifra 3 de trei ori.1}. cifra 2 de două ori şi cifra 3 de trei ori. Ce număr se generează imediat după 332312? viii) Utilizând metoda backtracking se generează în ordine lexicografică toate anagramele cuvântului caiet ( cuvinte formate din aceleaşi litere. vi) Se generează în ordine strict crescătoare numerele de câte şase cifre care conţin: cifra 1 o singură dată. 103 b. 5}. Câte bilete de 6 numere se pot completa folosind doar aceste valori. M4={4. cu proprietatea că pe fiecare linie şi pe fiecare coloană există o singură valoare 1. M2={3. 20. catei b. 6! c. 4}. numerele: 122333. 42. Folosind acelaşi algoritm se generează numere cu cifrele 0. …. …. mulţimile: {1. catie ix) Utilizând metoda backtracking se generează toate matricele pătratice de ordinul 4 ale căror elemente aparţin mulţimii {0. 2. M3={2.iii) Având la dispoziţie cifrele 0. Se obţin. 11. 220 d. 301 c. numerele: 122333. Care va fi al 7-lea număr din această generare ? a. în ordine crescătoare. în această ordine: 2. actei d. 3. 1. 333221. în această ordine. sunt generate. 101. în această ordine. {7}. în această ordine: 1000 0100 0010 0001 . 123323. Care este a şasea soluţie? a. Astfel. stabiliţi în ce ordine sunt generate următoarele mulţimi: M1={2. actie c. 200. 20. 48. înscrise pe bilet. ştiind că numărul 42 va fi colorat pe fiecare bilet? a. 333221. 21 b. 1 şi 2 putem genera. 56 v) Se generează prin metoda backtracking mulţimile distincte ale căror elemente sunt numere naturale nenule şi care au proprietatea că suma elementelor fiecărei mulţimi este egală cu 7. 38. 2 şi 3 care au suma cifrelor egală cu 4. Primele 3 soluţii generate sunt. 5}. O situaţie statistică pe o anumită perioadă de timp arată că cele mai frecvente numere care au fost extrase la LOTO sunt: 2. 42 d. 123233.

1) d.2. 3) c. raute cuvintele imediat următoare sunt: a. Dacă primele două soluţii sunt: (1. 3. rauet şi rtaeu b. 3. 4. 2) xi) Se generează. 1. rtaeu şi rtaue . 5. (4.5. (2. (2. Pentru anagramele cuvântului rateu. 3.2. 1.5. 5. toate modalităţile de aşezare a numerelor naturale de la 1 la 5 astfel încât oricare două numere consecutive să nu se afle pe poziţii alăturate. prin metoda backtracking.2. astfel încât oricare 2 numere consecutive să nu se afle pe poziţii alăturate. 1.4) şi (1.3. 4. 3. 1) d.4) şi (1.1000 0100 0001 0010 1000 0010 0100 0001 Care este penultima soluţie? a. 3. 1. 5. 0001 0100 0010 1000 d. 5) b. 3. 4.4. 5. 4.5. Dacă primele două soluţii sunt: (1.3). 3. 1) c.3. (4. raeut. după şirul raetu. toate modalităţile de aşezare a numerelor naturale de la 1 la 5. (4. 0010 1000 0100 0001 x) Se generează. 2. 5) b.2. 1. (2. (4. 2. 1) xii) Construim anagramele unui cuvânt c1c2c3c4 prin generarea în ordine lexicografică a permutărilor indicilor literelor cuvântului şi obţinem c1c2c3c4 c1c2c4c3 c1c3c2c4 … c4c3c1c2 c4c3c2c1. prin metoda backtracking. 0001 0010 1000 0100 b. 3. care este prima soluţie generată care începe cu 2? a. 5. (2.3).4. care este prima soluţie generată în care primul număr este 4? a.5. 0100 1000 0010 0001 c.

c.2. Ordinea copiilor în echipă este importantă deoarece aceasta va fi ordinea de intrare a studentilor în concurs (de exemplu echipa Alin.3. (1. rauet şi rtaue d. 4 xv) Un program construieşte şi afişează elementele produsului cartezian AxBxC pentru mulţimile A={1. astfel încât din ele să facă parte simultan Alin şi Bogdan? _______________ xiv) În vederea participării la un concurs de programare. şi trei fete. 30 c. Care dintre următoarele triplete NU va fi afişat? a. Bogdan.2. (1. în urma căreia primii 6 au obţinut punctaje egale. trebuie să formeze o echipă de 3 studenti.2. Elena şi Felicia. C={1.2.2}. (2. Câte echipe se pot forma.2.2) c.3) d. 15 d. (3.3. Alin. Alin. Echipa trebuie să fie mixtă (adică să conţină cel puţin o fată şi cel puţin un băiat). studentii din anii 2 si 3 au dat o probă de selecţie. care să participe la un concurs de prezentare software. Delia).4}. Delia este diferită de echipa Bogdan. B={1. 24 b.1) b. Delia.3}. şi că ordinea acestora în cadrul echipei nu contează? a. rtaeu şi ratue xiii) Trei baieti.2) . Bogdan şi Ciprian. aleşi dintre cei 6. În câte moduri poate fi formată echipa selecţionată ştiind că poate avea doar 4 membri.

dar puse in alta ordine. Blocurile din retea sunt numerotate cu numere intregi de la 1 la n. pe prima dintre ele fiind asezate n discuri de dimensiuni diferite.. Sa se genereze toate solutiile. coloana sau diagonala atunci apartin aceluiasi obiect. 7. celelalte discuri. 10. Intr-o statiune de odihna s-au intilnit n sahisti. Sa se determine daca ele sint anagrame. Sa se scrie un program care genereaza o secventa de mutari prin care discurile sint mutate de pe tija 1 pe tija 2. unde si reprezinta suma de bani din sacul i (i= 1. programare dinamica) 1. pe primul nivel vor fi n case. Se considera fondul alb. …. [Permutari] Sa se genereze permutarile multimii {1. luind intotdeauna un disc care nu are deasupra sa alte discuri si avind grija ca niciodata sa nu fie asezat un disc mai mare peste unul mai mic. 5. Se dau n tipuri de monezi. pe urmatorul n-1 case. fiecare continind o anumita suma. Se considera o stiva de case de bani sub forma de piramida. Pentru casele din stratul de baza nu exista nicio conditie. peste el. 3. Pentru fiecare partida se precizeaza cei doi jucatori. Folosind principiul ca “prietenul prietenului meuimi este prieten” sa se determine grupurile cu numar maxim de persoane intre care se pot stabili relatii de prietenie directe sau indirecte. Sa se distribuie acesti saci. centrala fiind . [Recursivitate] Se considera o fotografie specificata printr-o matrice patratica care contine ‘0’ si ‘1’ (0 – pentru puncte albe si 1 – pentru puncte negre). Sa se formeze un cel mai lung sir in care fiecare cuvint incepe cu litera cu care se termina predecesorul sau (mai putin primul cuvint care poate fi oricare). Sa se genereze cel mai scurt sir format din 0 si 1 de lungime 2n+n-1. au format o grupare de tip turneu (in care fiecare a jucat cu fiecare). …. Sa se numere cite obiecte distincte apar in fotografie. 8. Sa se determine un grup cit mai mare de jucatori. 2. in ordine descrescatoare a dimensiunii. 2. Ca date de intrare se utilizeaza: n (numarul de cutii din stratul de baza) si s1. Deci. n(n+1)/2). obiectele negre. Sa se plateasca o suma data s. astfel incit oricare ar fi doua secvente de lungime n ale acestui sir. 12. mai putin cele din etajul de baza care se vor sprijini direct pe podea. pina la ultimul nivel unde va fi o singura casa de bani. apoi n-2. care au jucat p partied de sah. greedy. s2. fiecare intr-o casa. 2. 9. Se considera trei tije. 2. 6. Intr-un grup de n personae se precizeaza perechi de personae care se considera prietene. acestea sa fie diferite. Reteaua de distribuire a apei calde pentru o centrala termica zonala este formata dintr-un sistem de conducte care leaga centrala de blocuri si blocurile intre ele. Sa se plaseze pe o tabla de sah (cu n randuri si n coloane) n dame astfel incit san u se atace reciproc. iar daca punctele negre sint vecine pe linie.Probleme diverse (recursivitate. cu n fixat. …. codificati prin numare naturale de la 1 la n. Se vor considera algoritmi iterative si recursive. adica sint formate din aceleasi litere. Se considera ca exista un numar sufficient de monezi din fiecare tip. …. care prin jocurile pe care le-au desfasurat. n}. folosind un numar minim de monezi din tipurile date. Astfel. …. 13. astfel incit in fiecare casa sa fie exact atitia bani cit in cele doua cutii pe care se sprijina la un loc. Sa se genereze toate partitiile multimii {1. Se dau n(n+1)/2 saci cu bani. fiecare casa se va sprijini pe doua case de bani din etajul anterior. Discurile pot fi mutate de pe o tija pe alta. Se da o lista cu n cuvinte. si. astfel incit cel mai mare este jos. 11. divide et impera. n} cu n fixat. 4. Se dau doua siruri de caractere. Se considera un numar natural n (3<n<15).

Daca in tara exista n localitati si timpul necesar pentru a ajunge dintr-o localitate in alta (in cazul in care se poate ajunge direct) se cere sa se determine timpul minim in care studentul poate sa ajunga din X in Y. Fiind date valorile (a. b) -> (a-b. a[n-1] si b[0].j). 226] 30. Problema colorarii hartilor [1. Sa presupunem. (a. 24. Executarea lucrarilor cu termen final [1. Fiind o fire curioasa. b) -> (a+b. sa se afle costul minim pentru a ajunge dint-un oras in oricare altul. 190] . Sa se gaseasca un cel mai lung subsir comun al acestora. b[1]. de dimensiune standard 8x8. 17. b[m-1]. El poate urca una sau doua trepte la un moment. ca un graf neorientat este format din n varfuri si m arce. Se da un sir de numere a[0]. pe care se afla diverse piese de sah. 220] 27. Un cal se afla pe pozitia (i. astfel incat numarul de mutari sa fie minim. 221] 28. 16. …. a[1]. 26. Sa se determine perechile de numere desemnand punctele de distribuire intre care trebuie sa se monteze conducte astfel incat fiecare bloc sa fie alimentat cu apa calda (nu neaparat direct de la centrala) si lungimea totala a conductelor necesare sa fie minima. Se doreste taierea acesteia in bucati de dimensiuni prestabilite. pag. la fel si vecinii lui directi. daca acest lucru este posibil.etichetata cu 0. 216] 25. Prin atingerea unui bec acesta isi schimba starea (din stins in aprins si invers). pag. de dimensiuni date. 225] 29. n<40001). 219]. Se stie ca sunt folosite toate muchiile pentru a lega varfuri si ca doua varfuri pot fi legate direct prin cel mult o muchie. Problema comis-voiajorului [1. acest om isi pune problema in cate moduri poate urca aceasta scara. Considerand ca initial toate becurile sunt stinse. astfel incat sa ramana cat mai putin material care nu mai poate fi folosit (nu corespunde nici unei dimensiuni). a[1]. Un student doreste sa calatoreasca din localitatea X in localitatea Y. Se dau m astfel de dimensiuni in care putem taia bara. In fiecare nod al arborelui se afla cate un bec. 18. pag.in cu formatul: pe prima linie numarul de noduri. pag. Se doreste mutarea calului in pozitia (k. Inmultirea optimala a matricelor si rezolvarea recurentei f(n)=7f(n/2)+18(n/2)2 [1. Se cunosc distantele de la centrala la blocuri precum si distantele dintre blocuri. d). …. …. Fie un arbore cu n varfuri. a). Se dau doua siruri a[0]. Se considera o tabla de sah. 14. Problema consta in ataia asemenea bucati din bara. Sa se determine valoarea maxima a expresiei S = suma patratelor gradelor varfurilor. Un om doreste sa urce o scara cu N trepte (N dat initial). Fiind date n orase si costurile tuturor drumurilor directe care exista intre orase. Datele de intrare se citesc din fisierul craciun. 19. 23. sa se scrie un program care genereaza o secventa de “atingeri” prin care pomul este aprins complet. Prelucrarea expresiilor cu ajutorul structurilor arborescente [1. b) -> (b. sip e urmatoarele n-1 linii se afla muchiile arborelui. Generarea obiectelor combinatoriale [1. 20. (a. b). b). 15. unde gradul unui varf este reprezentat de numarul de muchii legate de acesta. pag. 22. b) asupra careia se pot efectua urmatoarele operatii: (a. a[n-1]. Sa se afle un cel mai lung subsir crescator.l) – daca acest lucru este posibil – folosind oricare dintre cele 8 mutari posibile ale calului in orice succesiune. 21. b) sa se determine numarul minim de operatii pe care trebuie sa le facem astfel incat sa se ajunga la perechea (c. pag. Se considera o pereche de numere de forma (a. cu n dat initial. Problema rucsacului [1. Se considera o bara de lungime n (n >0.

Sign up to vote on this title
UsefulNot useful