Sunteți pe pagina 1din 158

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 Programrii 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 - proiecie in amfiteatru, programe demonstrative; 2. Recomandarea, pentru studiul individual, a unor paragrafe din bibliografia indicat, n vederea aprofundrii sau extinderii cunotinelor cptate 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 _______________________

2. Structuri de date
O structur de date este o mulime de date organizate ntr-un anumit mod mpreun cu relaiile dintre acestea. n funcie de modul de alocare, structurile de date se clasific n: structuri de date statice : tabloul, nregistrarea, mulimea, fiierul. Structurile de date statice ocup o zon de memorie constant pe toat durata de executare a blocului n care apare declaraia i elementele ocup poziii fixe. Fiierele sunt structuri de date externe (vezi capitolul 1). structuri de date semistatice: stiva alocat static, coada alocat static. Structurile de date semistatice ocup o zon de memorie de dimensiune constat, alocat pe toat durata executrii blocului n care apare declaraia de structur, iar elementele ocup poziii variabile pe parcursul executrii programului. structuri de date dinamice: lista nlnuit, structuri arborescente. Structurile de date dinamice ocup o zon de memorie de dimensiune variabil, alocat dinamic. Alocarea dinamic permite gestionarea memoriei n timpul executrii programului. Ele sunt mult mai flexibile dect cele statice i din aceast cauz sunt extrem de avantajoase. Liste: O list este o colecie de elemente de informaie (noduri) aranjate ntr-o anumit ordine. Lungimea unei liste este numrul de noduri din list. Structura corespunztoare de date trebuie s ne permit s determinm eficient care este primul/ultimul nod n structur i care este predecesorul/succesorul (dac exist) unui nod dat. Limbajele Pascal sau C(++) ofer posibiliti de implementare a acestor structuri att static ct i dinamic. Operaiile curente care se fac n liste sunt: inserarea unui nod, tergerea (extragerea) unui nod, concatenarea unor liste, numrarea elementelor unei liste etc. Implementarea unei liste se poate face n principal n dou moduri: Implementarea secvenial, n locaii succesive de memorie, conform ordinii nodurilor n list. Avantajele acestei tehnici sunt accesul rapid la predecesorul/succesorul unui nod i gsirea rapid a primului/ultimului nod. Dezavantajele sunt inserarea/tergerea relativ complicat a unui nod i faptul c nu se folosete ntreaga memorie alocat listei. Implementarea nlnuit. Fiecare nod conine dou pri: informaia propriu-zis i adresa nodului succesor. Alocarea
31

memoriei fiecrui nod se poate face n mod dinamic, n timpul rulrii programului. Accesul la un nod necesit parcurgerea tuturor predecesorilor si, ceea ce poate lua ceva mai mult timp. Inserarea/tergerea unui nod este, n schimb, foarte rapid. Listele se pot clasifica dup numrul de legturi n: liste simple liste duble liste circulare O list simpl are o singur legtur, legtura ultimului element este adresa NIL/NULL. Pentru a accesa lista avem nevoie de o variabil care s pstreze adresa primului element (cap sau prim). O list dubl are dou legturi: legtura de tip urmtor i legtura de tip precedent sau anterior. O lista circular este o lista n care, dup ultimul nod, urmeaz primul, deci fiecare nod are succesor i predecesor. Listele se pot clasifica dup locul n care se fac operaiile de adugare/eliminare astfel: stive cozi 2.1. Liste simplu nlnuite ntre nodurile unei liste simplu nlnuite este definit o singur relaie de ordonare. Fiecare nod conine un pointer a crui valoare reprezint adresa nodului urmtor din list.
Limbajul Pascal

type lista

= ^nod nod=record inf:tip ; urm: lista; end;

Limbajul C(++) typedef struct nod { tip inf; struct nod *urm; }lista;

unde urm este adresa urmtorului nod (pointer ctre urmtorul nod), iar inf este un cmp de informaie util. Operaii asupra listei simplu nlnuite Crearea unei liste simplu nlnuite: 1. Se iniializeaz pointerul prim cu Nil/NULL, deoarece lista la nceput este goal; 2. Se rezerv zon de memorie n memoria heap pentru nodul curent;
32

3. Se ncarc nodul curent cu date; 4. Se determin adresa ultimului nod i se realizeaz legtura cu nodul creat; 5. Se reia cu pasul 2 dac se introduce un nod nou. Inserarea unui element x al crui cmp cheie a fost iniializat n faa unei liste nlnuite LISTA-INSEREAZA(p,x) 1: urm(x) p 2: dac p<>NIL atunci px Cutarea ntr-o list nlnuit p a elementului x se realizeaz prin subprogramul LISTA-CAUTA i returneaz pointerul la acest obiect. LISTA-CAUTA(p,x) 1. qp 2. ct timp q<>NIL i cheie(q)<>x execut qurm(q) 3. returneaz q Probleme rezolvate 1. Fiind dat o list simplu nlnuit cu elemente numere ntregi s se realizeze un program care s execute urmtoarele operaii: crearea, parcurgerea, adugarea unui nod la nceputul listei, adugarea unui nod la sfritul listei, tergerea unui nod de pe o poziie dat. Observaii:
Limbajul Pascal: Procedura NEW(pointer)- alocarea dinamic a memoriei pentru variabila dinamic pointer. Procedura DISPOSE(pointer)eliberarea memoriei ocupate de ctre variabila dinamic pointer. Limbajul C(++) Funcia MALLOC se folosete pentru a rezerva octei din memoria heap. Trebuie inclus fiierul antet: stdlib.h sau alloc.h

Rezolvare: Parcurgerea unei liste liniare simplu nlnuite se realizeaz cu un pointer care pleac de la capul listei i va referi pe rnd fiecare nod, prelucrnd informaiile din nod apoi se trece la urmtorul nod, prelucrm informaiile din nod etc.
33

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

{stergerea nodului de pe pozitia p} var q,w,t:lista;i:integer; begin if cap=nil then writeln('Lista vida !!! ') else if p=1 then begin {stergere la inceputul listei} q:=cap; cap:=cap^.urm; dispose(q); end else if (cap<> nil) then begin t:=cap; i:=1; while (t^.urm<> nil) and (i+1<p) do begin inc(i) ;t:=t^.urm end; if t^.urm=nil then write('nu exista suficiente pozitii') else begin w:=t^.urm; t^.urm:=t^.urm^.urm; dispose(w) end end end; begin read(x); while x<>0 do begin adaug_inc(cap,x); read(x); end; listare(cap); write('pozitia');read(p);sterge(cap,p); listare(cap); write('informatia adaugata la sfarsit');read(x);adaug(cap,x); listare(cap) end.

Implementare n C:
#include <stdio.h> #include<stdlib.h> #include<alloc.h> typedef struct nod { int inf; struct nod*urm; }lista; lista *prim; lista *creare(void); void parcurgere(lista *p); 35

lista* sterg_inc(lista *prim){ lista *p; p=prim; prim=prim->urm; free(p); return prim; } 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,*q; for (p=prim;p->urm!=NULL;p=p->urm) q=(lista*) malloc(sizeof(q)); scanf("%d",&q->inf); q->urm=NULL; p->urm=q; } void main(){ lista *prim; prim=creare(); parcurgere(prim); prim=sterg_inc(prim); printf("\n"); parcurgere(prim); adauga(prim); parcurgere(prim); } lista *creare(){ int n,i,inf; lista *prim,*p,*q; printf("nr. de elemente");scanf("%d",&n); printf("informatia primului nod"); scanf("%d",&inf); prim=(lista*)malloc(sizeof(prim)); prim->inf=inf;prim->urm=NULL; for(q=prim,i=2;i<=n;i++){ printf("inf . %d:",i);scanf("%d",&inf); p=(lista*)malloc(sizeof(p)); p->inf=inf;p->urm=NULL; q->urm=p; q=p; } return(prim); } void parcurgere(lista *p){ lista *q; for (q=p;q;q=q->urm) printf("%d ",q->inf); } 36

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

begin read(n); for i:=1 to n do begin read(x); creare(p,x) end; listare(p);writeln; p:=inversare(p); listare(p) end. 3. S se efectueze suma a dou polinoame rare (polinom cu foarte muli coeficieni egali cu zero) folosind liste simplu nlnuite. Rezolvare: Lista are ca informaie gradul i coeficientul fiecrui termen de coeficient nenul. Pentru a calcula suma este necesar s parcurgem listele celor dou polinoame i s adugm corespunztor n cea de-a treia list. Implementare Pascal: type lista=^nod; nod=record grad:1..5000; coef:integer; urm:lista end; var a,b,p,q,r:lista; i,n,m:integer; procedure creare(var p:lista); begin write('cati coeficienti nenuli are polinomul');readln(n); new(p);readln(p^.coef,p^.grad); p^.urm:=nil;b:=p; {b este adresa ultimului nod} for i:=2 to n do begin new(a); write('coef ',i,':');readln(a^.coef); write('grad ',i,':');readln(a^.grad); b^.urm:=a; b:=a; b^.urm:=nil end end; procedure listare(p:lista); var a:lista; begin a:=p; while a<>nil do begin write(a^.coef,'x^', a^.grad,' +'); a:=a^.urm end; writeln(#8,' '); end;
38

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

end; begin creare(p);creare(q);listare(p);listare(q); r:=nil; aduna(p,q,r); listare(r); readln; end. Exerciii: 1. S se implementeze n C aplicaia de mai sus. 2. S se scrie un subprogram pentru calcularea produsului a dou polinoame rare. 3. S se calculeze valoarea unui polinom ntr-un punct dat. Indicaie: 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 coeficienilor termenilor din pereche -se elimin nodurile din lista de termeni prin pstrarea fiecrui grad o singur dat astfel: dac exist dou noduri cu acelai grad unul din ele va fi eliminat, iar coeficientul celuilalt va avea valoarea sumei coeficienilor celor doi termeni. Valoarea unui polinom se va calcula prin parcurgerea listei i adugnd la valoare produsul dintre coeficient i valoarea dat la puterea gradului din nod. 4.Dndu-se dou liste simplu nlnuite cu elemente numere intregi distincte, s se afiseze diferena celor dou liste i elementele comune celor dou liste. Rezolvare: Diferena celor dou liste conine elementele primeia care nu sunt n cea de-a doua. Se parcurge prima list i pentru fiecare nod se verific dac este n cea de-a doua list, dac nu se afl atunci se adaug listei trei. Intersecia celor dou liste se determin parcurgnd
40

if a<>nil then c^.urm:=a; if b<>nil then c^.urm:=b;

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

procedure intersectie(cap1,cap2:lista; var cap3:lista); var q,q2,nou,q3:lista; x:integer; begin q:=cap1; while q<>nil do begin x:=q^.inf; gasit:=false; q2:=cap2; while q2<>nil do begin if q2^.inf=x then gasit:=true; q2:=q2^.urm; end; if gasit then if cap3=nil then begin new(cap3); cap3^.inf:=x; cap3^.urm:=nil end else begin new(nou); nou^.inf:=x ; nou^.urm:=nil; q3:=cap3; while q3^.urm<> nil do q3:=q3^.urm; q3^.urm:=nou end; q:=q^.urm end end; begin creare(cap1); creare(cap2); afisare(cap1); afisare(cap2); diferenta(cap1,cap2); writeln; diferenta(cap2, cap1); writeln('intersectie'); intersectie(cap1,cap2,cap3); afisare(cap3); end. Exerciiu: S se implementeze aplicaia de mai sus in C. 5. S se creeze o list simplu nlnuit, cu informaie numeric astfel nct la orice moment al inserrii lista s fie ordonat cresctor dup informaie. Rezolvare: Paii: -crearea unui nod nou -dac informaia care se adaug este mai mic dect informaia din capul listei atunci se insereaz n faa primului nod -altfel se parcurge lista pn la primul nod a crei informaie este mai mare dect informaia noului nod i se insereaz.
42

Implementare C: #include <stdio.h> #include <stdlib.h> #include <alloc.h> typedef struct nod { int inf; struct nod*urm;} lista; lista *prim; lista *creare(void); void parcurgere(lista *p); void main(){ lista *prim; prim=creare(); parcurgere(prim); } 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); }
43

Exerciiu: S se implementeze aplicaia de mai sus n Pascal. 6. S se scrie un program pentru interclasarea a dou liste ordonate simplu nlnuite. Rezolvare: Se va parcurge simultan cele dou liste urmnd ca introducerea unui nod n lista final s fie fcut din lista care are valoarea informaiei din nod mai mic. Implementare C: #include <stdio.h> #include <stdlib.h> #include <alloc.h> typedef struct nod {int inf; struct nod*urm;}lista; lista *inter(lista *prim1, lista*prim2){ lista *prim,*ultim; if (prim1->inf>prim2->inf){ prim=prim2;prim2=prim2->urm; } else { prim=prim1; prim1=prim1->urm; } ultim=prim; while(prim1&&prim2) if (prim1->inf>prim2->inf){ ultim->urm=prim2; ultim=prim2; prim2=prim2->urm; } else {ultim->urm=prim1; ultim=prim1; prim1=prim1->urm; } if (prim1) ultim->urm=prim1; else ultim->urm=prim2; return prim; } lista *creare(void); void parcurgere(lista *p);
44

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); } Exerciiu: S se implementeze aplicaia de mai sus n limbajul Pascal.
45

2.2. Liste dublu nlnuite 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;

Operaiile care se pot defini asupra listelor dublu nlnuite sunt aceleai ca i n cazul listelor simplu nlnuite: - crearea unei liste dublu nlnuite; - accesul la un element al unei liste dublu nlnuite; - inserarea unui nod ntr-o list dublu nlnuit; - tergerea unui nod dintr-o list dublu nlnuit; - tergerea unei liste dublu nlnuite. Probleme rezolvate 1. S se scrie un program care va conine un meniu cu principale operaii asupra listei dublu nlnuite. Implementarea Pascal a soluiei: 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

end end; procedure parcurgere(var cap:lista); var q:lista; begin q:=cap; while q<>nil do begin write(q^.inf, ' '); q:=q^.urm end; readln end; procedure parcurgere_inv(var cap:lista); var q:lista; begin q:=cap; while q^.urm<>nil do q:=q^.urm; while q<>nil do begin write(q^.inf, ' '); q:=q^.ant end; readln; end; begin while x<> 7 do begin writeln('1.creare'); writeln('2.adaugare'); writeln('3.inserare'); writeln('4.stergere'); writeln('5.parcurgere'); writeln('6.parcurgere_inv'); writeln('7.iesire'); readln(x); case x of 1:creare(cap); 2:adaugare(cap); 3:inserare(cap); 4:stergere(cap); 5:parcurgere(cap); 6:parcurgere_inv(cap); end end end.
48

if i=k then begin q:=p; p^.ant^.urm:=p^.urm; p^.urm^.ant:=p^.ant; dispose(q); end else begin write('nu exista'); readln end

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

2.3. Liste circulare Dup numrul de legturi, listele circulare se mpart n: liste simple i liste duble. Listele circulare simple sunt liste simple care au n plus propietatea c valoarea cmpului urmtor a ultimului nod este adresa capului listei. Listele circulare duble sunt liste duble care au propietatea c legtura urmtor a celui de-al doilea cap este primul cap i legtura anterior a primului cap este al doilea cap. Crearea i parcurgerea listei circulare simplu nlnuite n limbajul C: #include<stdio.h> #include<conio.h> #include<stdlib.h> typedef struct nod{ int inf; struct nod *urm;}lista; void main(){ lista *prim,*p,*q; int i,n; /*crearea listei circulare*/ printf("inf primului nod"); prim=(lista*)malloc(sizeof(lista)); scanf("%d",&prim->inf);prim->urm=NULL; p=prim; printf("nr de elemente");scanf("%d",&n); for (i=2;i<=n;i++){ q=(lista*)malloc(sizeof(lista)); printf("inf=");scanf("%d",&q->inf); p->urm=q;p=q; } p->urm=prim; /*parcurgerea listei*/ printf("%d ",prim->inf); for (q=prim->urm;q!=prim;q=q->urm) printf("%d ",q->inf); } Problem rezolvat: Se d un grup de n copii aezai n cerc, care sunt numrai din m n m. Copilul care a fost numrat cu valoarea m este eliminat. Dndu-se pasul de eliminare m se cere s se precizeze ordinea ieirii din cerc.
50

Rezolvare: Simularea eliminrii copiilor se realizeaz cu o list circular la care se realizeaz eliminarea nodului care are ca informaie numrul copilului scos din joc. Numrarea se va face parcurgnd m elemente de la poziia de unde s-a efectuat ultima tergere. Implementarea Pascal (Lista circular este simpl.) type lista=^nod; nod=record inf:integer; urm:lista end; var i,n,m,j:integer; prim,q,p:lista; procedure creare(var prim:lista;x:integer); begin new(prim); prim^.inf:=x; prim^.urm:=prim end; procedure adaugare(var prim:lista;x:integer); var q,p:lista; begin new(q); q:=prim; while q^.urm<>prim do q:=q^.urm; new(p); p^.inf:=x; q^.urm:=p;p^.urm:=prim; end; procedure listare(prim:lista); var q:lista; begin new(q);q:=prim; write(q^.inf,' '); while q^.urm<>prim do begin q:=q^.urm; write(q^.inf,' ') end; end; begin {program principal} read(n); creare(prim,1); for i:=2 to n do adaugare(prim,i); listare(prim); read(m); p:=prim; for i:=1 to n-1 do begin if i=1 then for j:=1 to m-2 do p:=p^.urm else for j:=1 to m-1 do p:=p^.urm; q:=p^.urm; write(q^.inf,' '); p^.urm:=q^.urm; dispose(q); end; writeln('castigator=',p^.inf); end.
51

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

52

2.4. Stive O stiv (stack) este o list liniar cu proprietatea c operaiile de inserare/extragere a nodurilor se fac n/din vrful listei. Ultimul nod inserat va fi i primul ters, stivele se mai numesc i liste LIFO (eng. Last In First Out) sau liste pushdown.

push pop
Cel mai natural mod de reprezentare pentru o stiv este implementarea secvenial ntr-un tablou S[1 .. n], unde n este numrul maxim de noduri. Primul nod va fi memorat n S[1], al doilea n S[2], iar ultimul n S[top], unde top este o variabil care conine adresa (indicele) ultimului nod inserat. Algoritmii de inserare i de tergere (extragere) a unui nod: function push(x, S[1 .. 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 .. 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, deci nu depind de mrimea stivei.
53

Problem rezolvat: Realizai un meniu n limbajul Pascal care s conin operaii asupra stivei.

type stiva=^nod; nod=record inf:integer; urm:stiva end; var cap:stiva; x:integer; procedure adauga(var cap:stiva); var nou:stiva; begin new(nou); writeln('Ce sa adaug? '); readln(nou^.inf); nou^.urm:=nil; if cap=nil then cap:=nou else begin nou^.urm:=cap; cap:=nou; end; end; procedure sterge(var cap:stiva); var q:stiva; begin if cap=nil then writeln('Stiva vida') else begin q:=cap; cap:=cap^.urm; dispose(q) end; end; procedure parcurgere(cap:stiva); var q:stiva; begin q:=cap; while q<> nil do begin writeln('|',q^.inf,'|'); q:=q^.urm end; writeln('___') end;
54

Rezolvare: Implementarea Pascal:

begin while x<> 4 do begin writeln('1.Adaugare'); writeln('2.Stergere'); writeln('3.Listare'); writeln('4.Iesire'); writeln('Dati optiunea'); readln(x); case x of 1:adauga(cap); 2:sterge(cap); 3:parcurgere(cap) end end end. Exerciiu: S se implementeze n limbajul C aplicaia de mai sus. Probleme propuse 1. S se scrie un program care citind numere ntregi din fiierul in.txt creeaz o stiv i o afieaz. S se transforme un numr din baza 10 n baza b folosind o stiv. 2. Pe o linie de cale ferat se gsesc, ntr-o ordine oarecare, n vagoane numerotate de al 1 la n. Linia continu cu alte k linii de manevr. Cunoscnd ordinea iniial a vagoanelor, s se obin la ieire vagoanele n ordine: 1,2 ,n; liniile de manevr sunt destul de lungi nct s ncap pe o singur linie toate cele n vagoane. Indicaie: Se dorete partiionarea vagoanelor n k submulimi care au vagoanele ordonate cresctor 2.5. Cozi O coad (eng. queue) este o list liniar n care inserrile se fac doar n capul listei, iar extragerile doar din coada listei. Cozile se numesc i liste FIFO (eng. First In First Out). O reprezentare secvenial pentru o coad se obine prin utilizarea unui tablou C[0 .. n-1], pe care l tratm ca i cum ar fi circular: dup locaia C[n-1] urmeaz locaia C[0]. Fie p variabila care conine indicele locaiei predecesoare primei locaii ocupate i fie u variabila care conine indicele locaiei ocupate ultima oar. Variabilele p i u au aceeai valoare atunci i numai
55

atunci cnd coada este vid. Iniial, avem p= u= 0. Inserarea i tergerea (extragerea) unui nod necesit timp constant. Operaii asupra cozii: function insert-queue(x, C[0 .. 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 .. 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 acelai cu testul de coad plin. Dac s-ar folosi toate cele n locaii, atunci nu am putea distinge situaia de coad plina i cea de coad vid, deoarece n ambele situaii am avea p = u. Se folosesc efectiv numai n-1 locaii din cele n ale tabloului C, deci se pot implementa astfel cozi cu cel mult n-1 noduri. Problem rezolvat: Relizarea unui meniu pentru implementarea static a cozii. Rezolvare: Cea mai simpl implementare a cozii static este folosirea unui tablou. Pentru gestionarea cozii este nevoie de dou elemente: p poziia primului element i u poziia de dup ultimul element din coad. Se va face o utilizare circular a spaiului alocat astfel: urmtoarea poziie este p mod n +1. Implementarea Pascal: TYPE coada=array[1..50] of integer; var c:coada; p,n,u,o,x:integer; procedure adaugare(var c:coada; var p,u:integer;x:integer); begin if p<>(u mod n)+1 then begin c[u]:=x; u:=u mod n +1 end else writeln('coada plina'); end;
56

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

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

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

Exerciiu: S se realizeze programul n Pascal corespunztor aplicaiei de mai sus. Probleme propuse: 1. Fiind dat o list simplu nlnuit avnd informaii numere ntregi s se elimine numerele negative. 2. S se realizeze interclasarea a n liste simplu nlnuite ordonate cresctor. 3. Fiind date dou liste simple cu informaii de tip ntreg, s se realizeze subprograme pentru urmtoarele operaii: intersecia, reuniunea, diferena i diferena simetric a elementelor celor dou liste. 4. S se scrie un program care citete cuvintele dintr-un fiier text in.txt, cuvintele sunt separate prin spaii i afieaz numrul de apariii al fiecrui cuvnt din fiier. Se vor folosi liste simplu nlnuite. 5. S se elimine dintr-o list simplu nlnuit toate nodurile care au o informaie dat. 6. S se realizeze operaii cu matrici rare folosind alocarea dinamica. 7. Fiind dat o list dubl, s se separe n dou liste elementele de pe poziii pare de elementele de pe poziii impare. 8. Fiind dat o list dubl cu informaii de tip ir de caractere, s se fac ordonarea elementelor listei. 9. Fiind dat o list dubl cu informaii de tip ntreg s se construiasc o list dubl numai cu elemente prime. 10. Pe o tij sunt n bile colorate cu cel mult k culori, fiecare bil avnd o etichet cu un numr de la 1 la n. S se mute bilele pe alte k tije, pe fiecare punnd numai bile din aceeai culoare. S se afieze bilele de pe fiecare din cele k tije, folosind structuri dinamice. Indicaie: Tija iniial reprezint o stiv, informaia dintr-un nod va fi compus din numrul bilei i numrul culorii. Se va parcurge stiva i se adaug n stiva corespunztoare culorii, apoi se terge din stiva iniial. Se va lucra cu un vector de stive pentru cele k tije. 11. S se implementeze subprograme pentru operaiile de baz cu liste circulare duble. 12. Fie un traseu circular ce cuprinde n orae. O main trebuie s parcurg toate oraele i s se ntoarc de unde a plecat. Parcurgerea se poate face n ambele sensuri. Se cere s se
60

determine un traseu posibil de parcurgere astfel nct s nu rmn n pan tiind c n fiecare ora exist o staie de benzin cu o cantitate de benzin suficient, iar maina consuma c litri la 100 de kilometri. 13. Fiind dat o list circular dubl, s se fac un subprogram de inserare a unui element pe o poziie dat. 14. S se realizeze un subprogram care terge elementele egale cu zero dintr-o list circular. 15. S se creeze o list de liste, s se parcurg i s se tearg. 16. S se scrie un program care citete cuvintele dintr-un text i afieaz numrul de apariii al fiecrui cuvnt din textul respectiv. 17. S se scrie un program care citete cuvintele dintr-un text i scrie numrul de apariie al fiecrui cuvnt, n ordinea alfabetic a cuvintelor respective. 18. ntr-o gar se consider un tren de marf ale crui vagoane sunt inventariate ntr-o list. Lista conine, pentru fiecare vagon, urmtoarele date: codul vagonului, codul coninutului vagonului, adresa expeditorului, adresa destinatarului. Deoarece n gar se inverseaz poziia vagoanelor, se cere listarea datelor despre vagoanele respective n noua lor ordine. Indicaie: se creeaz o stiv n care se pstreaz datele fiecrui vagon. Datele corespunztoare unui vagon constituie un element al stivei, adic un nod al listei simplu nlnuite. Dup ce datele au fost puse n stiv, ele se scot de acolo i se listeaz. 19. La o agenie CEC exist un singur ghieu care se deschide la ora 8 i se nchide la ora 16, dar publicul aflat la coad este deservit n continuare. Deoarece la ora nchiderii coada este destul de mare se ridic problema oportunitii deschiderii a nc unui ghieu la agenia respectiv. Se cunosc operaiile efectuate la agenie i timpul lor de execuie. n acest scop se realizeaz o simulare pe calculator a situaiei existente care s stabileasc o medie a orelor suplimentare efectuate zilnic pe o perioad de un an. Indicaie: Programul de simulare a problemei indicate construiete o coad de ateptare cu persoanele care sosesc la agenie n intervalul de timp indicat. Se va folosi funcia random pentru a determina operaia solicitat i apoi pentru a determina intervalul de timp ntre dou persoane care vin la agenie.

61

20. S se realizeze un program care implementeaz subprograme pentru crearea i exploatarea unei cozi duble. 21. Se d o matrice rar memorat ntr-o list. Se cere: a) s se afieze toate elementele diferite de zero de pe diagonala principal, secundar; b) s se afieze pe ecran matricea sub forma obinuit, fr reconstituirea ei n memorie. 2.6. Grafuri Noiuni introductive Un graf este o pereche G = <V, M>, unde V este o mulime de vrfuri, iar M = VxV este o mulime de muchii. O muchie de la vrful a la vrful b este notat cu perechea ordonat (a, b), dac graful este orientat, i cu mulimea {a, b}, dac graful este neorientat. Dou vrfuri unite printr-o muchie se numesc adiacente. Un drum este o succesiune de muchii de forma (a1, a2), (a2, a3), ..., (an-1, an) sau de forma {a1, a2}, {a2, a3}, ..., {an-1, an} dup cum graful este orientat sau neorientat. Lungimea drumului este egal cu numrul muchiilor care l constituie. Un drum simplu este un drum n care nici un vrf nu se repet. Un ciclu este un drum care este simplu, cu excepia primului i ultimului vrf, care coincid. Un graf aciclic este un graf fr cicluri. Un subgraf al lui G este un graf <V', M'>, unde V' V, iar M' este format din muchiile din M care unesc vrfuri din V'. Un graf parial este un graf <V, M">, unde M" M. Un graf neorientat este conex, dac ntre oricare dou vrfuri exist un drum. Pentru grafuri orientate, aceast noiune este ntrit: un graf orientat este tare conex, dac ntre oricare dou vrfuri i si j exist un drum de la i la j i un drum de la j la i. n cazul unui graf neconex, se pune problema determinarii componentelor sale conexe. O componenta conex este un subgraf conex maximal, adic un subgraf conex n care nici un vrf din subgraf nu este unit cu unul din afar printr-o muchie a grafului iniial. mprirea unui graf G = <V, M> n componentele sale conexe determina o partiie a lui V i una a lui M. Un arbore este un graf neorientat aciclic conex. Sau, echivalent, un arbore este un graf neorientat n care exist exact un drum ntre oricare dou vrfuri. Un graf parial care este arbore se numete arbore partial. Vrfurilor unui graf li se pot ataa informaii numite
62

uneori valori, iar muchiilor li se pot ataa informaii numite uneori lungimi sau costuri. Metode de reprezentare a grafurilor a) Matricea de adiacen Cea mai cunoscut metod de memorare a grafurilor neorientate este matricea de adiacen, definit n felul urmtor: 1, dac exist muchie (arc) de la vrful i la vrful j i 0, n caz contrar. n cazul grafurilor neorientate, aceast matrice este simetric, folosindu-se efectiv numai jumtate din spaiul matricei. n unele probleme este eficient ca cealalt jumtate a matricei s fie folosit pentru reinerea altor informaii. Matricea de adiacen este folosit n general pentru grafuri cu un numr mic de noduri, deoarece dimensiunea ei este limitat de dimensiunea stivei. 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 reinerea unei matrice cu 2 linii i m coloane, pe fiecare coloan fiind reinute dou extremiti ale unei muchii. Aceasta reprezentare este eficient atunci cnd avem de examinat toate muchiile grafului.
63

Listele de muchii sunt folosite n cazul algoritmilor care prelucreaz secvenial muchiile, cum ar fi de exemplu algoritmul Kruskal de aflare a arborelui parial de cost minim n cazul grafurilor rare (cu numr mic de muchii). c) Listele de vecini. Prin liste de vecini (adiacen) se realizeaz ataarea la fiecare vrf i a listei de vrfuri adiacente lui (pentru grafuri orientate, este necesar ca muchia s plece din i). ntr-un graf cu m muchii, suma lungimilor listelor de adiacen este 2m, dac graful este neorientat, respectiv m, dac graful este orientat. Dac numrul muchiilor n graf este mic, aceast reprezentare este preferabil din punct de vedere al memoriei necesare. Este posibil s examinm toi vecinii unui vrf dat, n medie, n mai puin de n operaii. Pe de alt parte, pentru a determina dac dou vrfuri i i j sunt adiacente, trebuie s analizm lista de adiacen a lui i (i, posibil, lista de adiacen a lui j), ceea ce este mai puin eficient dect consultarea unei valori logice n matricea de adiacen. Listele de vecini sunt cele mai recomandate n tratarea algoritmilor din teoria grafurilor din dou motive principale: 1. spatiul folosit este gestionat dinamic, putndu-se memora astfel grafuri de dimensiuni mari; 2. complexitatea optim pentru majoritatea algoritmilor fundamentali din teoria grafurilor (parcurgeri, conexitate, muchii i puncte critice, algoritmi de drum minim etc.) este obinut numai folosind liste de vecini. Exist dou modaliti de implementare a listelor de vecini. a) Prima dintre ele folosete o matrice T cu 2 linii i 2m coloane i un vector C cu n elemente care reine pentru fiecare nod indicele coloanei din T pe care este memorat primul element al listei nodului respectiv (sau 0 dac vrful respectiv nu are vecini). Apoi, pentru o anumit coloan i din T, T(i,1) reine un element din lista curent, iar T(i,2) reine coloana pe care se gsete urmtorul element din lista respectiv sau 0 dac lista s-a terminat. b) Cea de-a doua implementare folosete pentru fiecare nod o list simplu nlnuit memorat n heap. Pentru fiecare list este suficient s pstrm o singur santinel (cea de nceput a listei), introducerea vrfurilor fcndu-se mereu la nceputul listei (deoarece ordinea vrfurilor n list nu conteaz).
64

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

Parcurgerea grafurilor Parcurgerea unui graf presupune examinarea n vederea prelucrrii tuturor vrfurilor acelui graf ntr-o anumit ordine, ordine care s permit prelucrarea optim a informaiilor ataate grafului. a) Parcurgerea DF (parcurgerea n adncime) Parcurgerea DF (Depth First) presupune ca dintr-un anumit nod v, parcurgerea s fie continuat cu primul vecin al nodului v nevizitat nc. Parcurgerea n adncime a fost formulat cu mult timp n urm ca o tehnic de explorare a unui labirint. O persoan care caut ceva ntr-un labirint i aplic aceast tehnic are avantajul ca urmtorul loc n care caut este mereu foarte aproape. Parcurgerea vrfurilor n adncime 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 funcii recursive, dar exist i cazuri n care este recomandat 4 o implementare nerecursiv. 5 Implementarea acestei metode se 6 face folosind o stiv. Aceasta este iniia65

lizat cu un nod oarecare al grafului. La fiecare pas, se ia primul vecin nevizitat al nodului din vrful stivei i se adaug n stiv dac nu mai exist se coboar n stiv. 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, 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, S) pop(S) unde funcia ftop returneaz ultimul vrf inserat n stiv. Parcurgerea n adncime a unui graf nu este unic; ea depinde att de alegerea vrfului iniial, ct i de ordinea de vizitare a vrfurilor adiacente. Problem: Ct timp este necesar pentru a parcurge un graf cu n vrfuri i m muchii? Rezolvare: Deoarece fiecare vrf este vizitat exact o dat, avem n apeluri ale procedurii ad. n procedura ad, cnd vizitm un vrf, testm marcajul fiecrui vecin al su. Dac reprezentm graful prin liste de adiacen, adic prin ataarea la fiecare vrf a listei de vrfuri adiacente lui, atunci numrul total al acestor testri este m, dac graful este orientat,
66

i 2m, dac graful este neorientat. Algoritmul necesit un timp O(n) pentru apelurile procedurii ad i un timp O(m) pentru inspectarea mrcilor. Timpul de executare este O(max(m, n)) = O(m+n). Dac reprezentm graful printr-o matrice de adiacen, se obine un timp de executare de O(n2). b) Parcurgerea BF (parcurgerea n lime) Parcurgerea BF (Breath First) presupune faptul c dup vizitarea unui anumit nod v, sunt parcuri toi vecinii nevizitai ai acestuia, apoi toi vecinii nevizitai ai acestora din urm, pn la vizitarea tuturor nodurilor grafului. Parcurgerea n lime este folosit de obicei atunci cnd se exploreaz parial anumite grafuri infinite, sau cnd se caut cel mai scurt drum dintre dou vrfuri. Implementarea acestei metode se face folosind o coad. Aceasta este iniializat cu un nod oarecare al grafului. La fiecare pas, se viziteaz nodul aflat n vrful cozii i se adaug n coad toi vecinii nevizitai ai nodului respectiv. Parcurgere_BF(nod start) Coada start Vizitat(start) adevrat ct timp coada nu este vid ic nodul de la nceputul cozii adaug toti vecinii nevizitati ai lui ic n coad Vizitat(i) adevrat, unde i este un vecin nevizitat al nodului ic Pentru a efectua o parcurgere n laime a unui graf (orientat sau neorientat), aplicm urmtorul principiu: atunci cnd ajungem ntr-un vrf oarecare v nevizitat, l marcm i vizitm apoi toate vrfurile nevizitate adiacente lui v, apoi toate vrfurile nevizitate adiacente vrfurilor adiacente lui v etc. Spre deosebire de parcurgerea n adncime, parcurgerea n lime nu este n mod natural recursiv. procedure lat(v) C coada vida marca[v] vizitat insert-queue(v, C)
67

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, C) Pentru compararea celor dou metode apelm 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) Aplicaia 2.6.1: Algoritmul lui Dijkstra Fie G = (X,U) un graf orientat, unde X este mulimea vrfurilor i U este mulimea muchiilor. Fiecare muchie are o lungime nenegativ. Unul din vrfuri este desemnat ca vrf surs. Problema este s determinm lungimea celui mai scurt drum de la surs ctre fiecare vrf din graf. Vom folosi un algoritm greedy, datorat lui E.W. Dijkstra (1959). Notm cu C mulimea vrfurilor disponibile (candidaii) i cu S mulimea vrfurilor deja selectate. n fiecare moment, S conine acele vrfuri a cror distan minim de la surs este deja cunoscut, n timp ce mulimea C conine toate celelalte vrfuri. La nceput, S conine doar vrful surs, iar n final S conine toate vrfurile grafului. La fiecare pas, adugam n S acel vrf din C a crui distan de la surs este cea mai mic. La fiecare pas al algoritmului, un tablou D conine lungimea celui mai scurt drum special ctre fiecare vrf al grafului. Dup ce adugm un nou vrf v la S, cel mai scurt drum special ctre v va fi, de asemenea, cel mai scurt dintre toate drumurile ctre v. Cnd algoritmul se termin, toate vrfurile din graf sunt n S, deci toate drumurile de la surs ctre celelalte vrfuri sunt speciale i valorile din D reprezint soluia problemei. Matricea M d lungimea fiecarei muchii, cu M[i, j] = +, dac muchia (i, j) nu exist. Soluia se va construi n tabloul D[2 .. n]. Algoritmul este: S = {0} for i = 1 to n D[i] = M[1][i]
68

for i = 1 to n-2 caut cel mai mic D[v] pentru fiecare v S S = S {v} for toate vrfurile u S if (D[u] > D[v] + M[v][u]) then D[u] = D[v] + M[v][u] Implementare n C: #include <stdio.h> #include <string.h> #define FALSE 0 #define TRUE 1 #define MAXN 20 int setupDijkstra (int *nod_p, int a[MAXN][MAXN], int *startnod_p); void doDijkstra (int nod, int a[MAXN][MAXN], int startnod); void traceinfo (int S[MAXN], int D[MAXN], int nod); int main(){ int nod, startnod; int a[MAXN][MAXN]; printf("Algoritmul lui Dijkstra\n"); if (setupDijkstra(&nod, a, &startnod)) return 1; doDijkstra(nod, a, startnod); return 0; } int setupDijkstra (int *nod_p, int a[MAXN][MAXN], int *startnod_p){ int i, j; do{ printf("Introduceti 0 pentru a specifica graful,sau 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;
69

} void doDijkstra (int nod, int a[MAXN][MAXN], int startnod){ int S[MAXN]; int D[MAXN]; int i, j, urmnod, mic; /* initializare */ for (i=0; i<nod; i++) S[i] = FALSE; S[startnod] = TRUE; for (i=0; i<nod; i++) {D[i] = a[startnod][i]; } printf("Initializare\n"); traceinfo(S, D, nod); for (i=1; i<nod; i++){ urmnod = 999; mic = 999; for (j=0; j<nod; j++){ if (!S[j]){ if (D[j] < mic){ mic = D[j];urmnod = j;} }}
70

} else { printf("Enter number of nod (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 matricii: ", i+1); for (j=0; j<*nod_p; j++) if (scanf("%d", &a[i][j]) != 1) return 3; } printf("introduceti nodul (1-%d) ", *nod_p); if (scanf("%d", &i) != 1) return 4; if ( (i < 1) || (i > *nod_p) ) return 5; *startnod_p = i-1; } return 0;

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"); } *startnod_p = 0;

if (urmnod >= nod) return; // printf(" D[%c]=%2d, ", 'a'+urmnod, mic); printf("adauga nodul %c to S\n", 'a'+urmnod); S[urmnod] = TRUE; for (j=0; j<nod; j++){ if (!S[j]){ /* printf("Compara D[%c]=%2d si D[%c]+M[%c][%c]=%2d, ", \ 'a'+j, D[j], 'a'+urmnod, 'a'+urmnod, 'a'+j, \ D[urmnod]+a[urmnod][j]); */ if (D[j] > D[urmnod] + a[urmnod][j]){ D[j] = D[urmnod] + a[urmnod][j]; /*printf("D[%c] schimba %2d\n", 'a'+j, D[j]); */ } else /* printf("nu schimba\n"); */ } } traceinfo(S, D, nod); } } void traceinfo(int S[MAXN], int D[MAXN], int nod){ int i; printf(" S = {"); for (i=0; i<nod; i++) if (S[i]) printf("%c", 'a' + i); printf("}\n"); printf(" D = "); for (i=0; i<nod; i++) printf("%3d", D[i]); printf("\n"); } Aplicaia 2.6.2: Algoritmul lui Bellman-Ford (determinarea drumurilor minime dintre un nod i celelalte noduri ntr-un graf care poate s aib cicluri negative). Dac graful conine muchii de cost negativ, algoritmul Dijkstra nu mai funcioneaz corect, deoarece nu putem gsi - acum - nodurile cele mai apropiate de surs, n ordine cresctoare a distanei fa de aceasta. Aceast problem este rezolvat de algoritmul Bellman-Ford, care n plus determin i existena ciclurilor de cost negativ care pot fi atinse pornind din nodul surs. Ca i n cazul algoritmului Dijkstra,
71

vom folosi vectorul D care reine distana minim gsit la un moment dat de la s la celelalte noduri. Algoritmul foloseste o coad Q, care este iniializat cu nodul s. La fiecare pas, algoritmul scoate un nod v din coad i gsete toate nodurile w a cror distan de la surs la acestea poate fi optimizat prin folosirea nodului v. Dac nodul w nu se afl deja n coad, el este adugat acesteia. Aceti pai se repet pn cnd coada devine vid. Algoritmul utilizeaz tehnica de relaxare, procednd la descreterea estimrii d[v] a drumului minim de la sursa s la fiecare vrf v V pn cnd este obinut costul adevrat (u,v) corespunztor unui drum minim. Algoritmul returneaz adevarat dac i numai dac nu conine 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

Probleme rezolvate R2.6.1. S se afieze componentele conexe folosind parcurgerea DF a grafului. Graful este reprezentat prin matricea de adiacen citit din fiier TEXT. Rezolvare: Implementarea Pascal folosind parcurgerea DF recursiv: var a:array[1..100,1..100] of integer; viz:array[1..100] of integer; f:text;n,i,j:integer; procedure df(X:integer); var i:byte; begin write(x, ' '); viz[x]:=1; for i:=1 to n do if (a[x,i]=1) and (viz[i]=0) then df(i); end; procedure citire; begin assign(f,'matrice.txt'); reset(f); readln(f,n); for i:=1 to n do begin for j:=1 to n do read(f,a[i,j]); readln(f); end; end; begin citire; for i:=1 to n do viz[i]:=0; for i:=1 to n do if viz[i]=0 then begin df(i);writeln end; end. Exerciiu: Implementai n lumbajul C aplicaia de mai sus folosind funcia Df (iterativ) de mai jos. void df(int x){ int i,k,y,s[10],gasit; k=1;
75

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

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

end.

write('componenta tare conexa ',k,':',i,' '); for j:=1 to n do if (j<>i) and (a[i,j]<>0)and (a[j,i]<>0) then begin write(j,' '); m[j]:=true; end; inc(k); writeln; end;

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

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

procedure subgraf; var s:boolean; begin s:=true;if n1>n then s:=false; for i:=1 to n1 do for j:=1 to n1 do if (a[i,j]=1) and (b[i,j]=0) then s:=false; if s=false then writeln(' B nu e subgraf al lui A.') else writeln(' B e subgraf al lui A.'); end; procedure graf_p; var g:boolean; begin g:=true;if n<> n1 then g:=false; for i:=1 to n do for j:=1 to n do if (a[i,j]=0) and (b[i,j]=1) then g:=false; if g=false then writeln(' B nu e graf partial al lui A.') else writeln(' B e graf partial al lui A.'); end; begin clrscr; creare;creare1; graf_p;subgraf; end. Exerciiu: S se implementeze aplicaia de mai sus n limbajul C. R2.6.5. Determinarea drumurilor minime ntre oricare dou noduri. Rezolvare: Se folosete algoritmul lui ROY-FLOYD. Se pornete de la matricea costurilor C. pentru k=1,n execut pentru i=1,n execut pentru j=1,n execut c[i,j]=min(c[i,j],c[i,k]+c[k,j]) Simultan cu determinarea lungimilor minime ale drumurilor pot fi reinute drumurile folosind un tablou d, unde d[i,j] reprezint mulimea predesesorilor lui j pentru drumul minim de la i la j. Implementare Pascal: Var c:array[1..100,1..100] of longint; v:array[1..100]of integer; d:array[1..100,1..100] of set of 1..10; n,m,i,j,k,nr:integer; x,y:integer;
80

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

end.

for i:= 1 to n do begin for j:=1 to n do write(c[i,j]:4); writeln end; write('Dati doua noduri'); readln(x,y); writeln('costul minim= ', c[x,y], ' drumurile minime=' ); for x:=1 to n do for y:=1 to n do begin writeln('drum de la ',x,'la ',y); if c[x,y]=maxint then write('nu exista') else begin nr:=1;v[1]:=y; drum(x,y) end end

Exerciiu: S se implementeze algoritmul Roy-Floyd n limbajul C. R2.6.6. S se verifice dac un graf reprezentat dinamic este conex sau complet. Rezolvare: Se folosete un tablou de liste unde bl[i] reprezint lista vecinilor lui i. Implementare Pascal: type lista=^nod; nod= record inf:integer; urm:lista end; var bl:array[1..100] of lista; f:text; i,n,x:integer; complet:boolean; procedure adaugare (var p:lista;x:integer); var t,q:lista; begin new(q);q^.inf:=x;q^.urm:=nil; if p=nil then p:=q else begin t:=p;while t^.urm<>nil do t:=t^.urm; t^.urm:=q; end; end;
82

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

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

end; begin ciclic end.

if a[i]=a[j] then begin writeln('Graful din fisierul ',nume,' contine cel putin un ciclu'); close(f); halt; end; for k:=1 to n do if a[k]=a[j] then a[k]:=a[i]; end; writeln('Graful din fisierul ',nume,' nu contine cicluri'); close(f);

Implementare C: #include <stdlib.h> #include <iostream.h> #include <stdio.h> #include <conio.h> FILE *f; int n,a[10]; void ciclic(){ int i,j,k; fscanf(f,"%d",&n); for(i=1;i<=n;i++)a[i]=i; fscanf(f,"%d %d",&i,&j); if (a[i]==a[j]) { cout<<"contine ciclu"; fclose(f); exit(1); } for (k=1; k<=n; k++){ if (a[k]==a[j]) a[k]=a[i]; } cout<<"nu contine cicluri"; } void main(void){ f=fopen("in.txt","r");clrscr(); ciclic(); }
85

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

end.

for i:=1 to n do for j:=1 to n do a[i,j]:=0; while not eof(f) do begin readln(f,i,j); a[i,j]:=1; a[j,i]:=1 end; 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,j]=1) and (a[j,k]=1) and (a[k,i]=1) then writeln(i,' ',j,' ',k);

2.7. Arbori Fie G un graf orientat. G este un arbore cu radacina r, dac exist n G un vrf r din care oricare alt vrf poate fi ajuns printr-un drum unic. Adncimea unui vrf este lungimea drumului dintre rdcina i acest vrf; nlimea unui vrf este lungimea celui mai lung drum dintre acest vrf i un vrf terminal. nlimea arborelui este nalimea rdcinii; nivelul unui vrf este nlimea arborelui minus adncimea acestui vrf. Reprezentarea unui arbore cu rdcin se poate face prin adrese, ca i n cazul listelor nlnuite. Fiecare vrf va fi memorat n trei locaii diferite, reprezentnd informaia propriu-zis a vrfului (valoarea vrfului), adresa celui mai vrstnic fiu i adresa urmtorului frate. Pstrnd analogia cu listele nlnuite, dac se cunoate de la nceput numrul maxim de vrfuri, atunci implementarea arborilor cu rdcina se poate face prin tablouri paralele. Dac fiecare vrf al unui arbore cu rdacin are pn la n fii, arborele respectiv este n-ar. ntr-un arbore binar, numrul maxim de vrfuri de adncime k este 2k. Un arbore binar de nlime i are cel mult 2i+1-1 vrfuri, iar dac are exact 2i+1-1 varfuri, se numeste arbore plin. Vrfurile unui arbore plin se numeroteaz n ordinea adncimii. Un arbore binar cu n vrfuri i de nlime i este complet, dac se obine din arborele binar plin de nlime i, prin eliminarea, dac este cazul, a vrfurilor numerotate cu n+1, n+2, , 2i+1-1. Acest tip de arbore se poate reprezenta secvenial folosind un tablou T, punnd vrfurile de adncime k, de la stnga la dreapta, n poziiile T[2k], T[2k+1], , T[2k+1-1] (cu posibila excepie a nivelului 0, care poate fi incomplet). Un arbore binar este un arbore n care fiecare vrf are cel mult doi descendeni, fcndu-se distincie ntre descendentul stng i descendentul drept al fiecrui vrf.
87

Reprezentarea arborilor binari Reprezentarea prin paranteze: se ncepe cu rdcina arborelui, iar fiecare vrf care are descendeni este urmat de expresiile ataate subarborilor care au ca rdcin descendenii vrfului, desprite prin virgul i cuprinse ntre paranteze. Dac lipsete un descendent subexpresia corespunztoare este cuvntul vid. Pentru arborele de mai sus, reprezentarea este: 6(2(1,(4(3,5)), 8(7, 9(,10))) Reprezentarea standard: n care pentru fiecare vrf i este precizat descendentul su stng ST(i) descendentul su drept DR(i) = i informaia asociat v`rfului INF(i): static:ST i DR sunt dou tablouri ST=(0, 1, 0, 3, 0, 2, 0,7, 0, 0) DR=(0, 4, 0, 5, 0, 8, 0, 9,10,0) rad=6 dinamic:
type arbore=^nod; nod=record inf:integer; st,dr:arbore; end; typedef struct nod{ int inf; struct nod *st; struct nod *dr; }arbore; si se declara arbore *rad;

Reprezentarea cu doi vectori DESC i TATA: n vectorul DESC, avnd valori 1, 1,0 se precizeaz pentru fiecare nod ce fel de descendent este el pentru printele su iar n vectorul TATA se indic pentru fiecare vrf, nodul printe. Pentru exemplul de mai sus: TATA=(2,6,4,2,4,0,8,6,8,9) DESC=(-1,-1,-1,1,1,0,-1,1,1,1)
88

Parcurgerea arborilor binari preordine:se viziteaz rdcina, se traverseaz subarborele stng n preordine, se traverseaz subarborele drept n preordine; inordine: se traverseaz subarborele stng n inordine, se viziteaz rdcina, se traverseaz subarborele drept n inordine; postordine: se traverseaz subarborele stng n postordine, se traverseaz subarborele drept n postordine, se traverseaz rdcina. Aplicaia 2.7.1. S se creeze un arbore binar i apoi s se parcurg n preordine, s se caute un nod n arbore, s se afieze cheile de pe un anumit nivel dat, s se afieze drumurile de la rdcin la frunze i s se calculeze adncimea arborelui creat. Rezolvare: Implementare Pascal: program arb_binar; type arbore=^nod; nod =record st,dr:arbore; inf:integer end; var p:arbore;k,x,y,max,z:integer;a:array[1..100] of integer; {Procedura creare arbore binar} procedure creare(var p:arbore); var x:integer; begin read(x); if x=0 then p:=nil else begin new(p); p^.inf:=x; write('Dati stanga lui ',x); creare(p^.st); write('Dati dreapta lui ',x); creare(p^.dr); end; end; {Procedura parcurgere arbore binar - prin preordine} procedure preordine(p:arbore); begin if p<>nil then begin write(p^.inf,' '); preordine(p^.st); preordine(p^.dr); end; end;
89

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

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

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

void main(){ int x; rad=creare(); preordine(rad); printf("inf cautata:");scanf("%d", &x); if (cautare(rad,x)) printf("exista");else printf("nu exista"); cout<<"nivelul";cin>>x; cout<<"nodurile de pe nivelul "<<x<<":";nivel(rad,0,x); cout<<"drumuri:";drum_frunze(rad,1); adancime(rad,0); printf("adancimea=%d",max); } Arbori binari de cutare Arborele binar de cutare este un arbore binar n care pentru orice nod, cheia din succesorul su stng este mai mic dect cheia din nod, iar cheia din succesorul su drept este mai mare dect cheia din nod. n arborele binar de cutare informaia din noduri este unic. Prin parcurgerea n inordine a arborelui de cutare se obine n ordine cresctoare valorile din cmpurile cheie. Crearea se realizeaz adugnd n arbore rnd pe rnd cte un nod corespunztor fiecrei informaii. Adugarea unu nod: dac arborele nu are nici un nod se creaz rdcina; dac arborele exist se compar informaia nodului nou cu cea din nodul curent. Dac este mai mare, se reia procesul pentru subarborele din dreapta; dac este mai mic, se reia pentru subarborele din stnga, iar n caz de egalitate se afieaz eroare. Cutarea se realizeaz astfel: se caut n nodul curent; dac informaia s-a gsit, algoritmul se ncheie, astfel dac informaia este mai mare dect informaia din nodul curent, se caut n subarborele drept al acestuia, altfel n subarborele stng. Aplicaia 2.7.2. Program pentru crearea i exploatarea unui arbore binar de cutare. Rezolvare: Implementare Pascal: type arbore=^nod; nod = record inf:integer; st,dr:arbore end; var p:arbore;x:integer;
93

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

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

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

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

R2.7.4. S se scrie un subprogram pentru aflarea numrului de frunze dintr-un arborele binar . function p5(p:arbore):integer; begin if p=nil then p5:=0 else if (p^.st=nil) and (p^.dr=nil) then p5:=1 else p5:=p5(p^.st)+p5(p^.dr) end; R2.7.5.. S se scrie un subprogram pentru afiarea nodurilor care au un succesor dintr-un arbore binar. procedure p6(p:arbore); begin if p<>nil then begin if ((p^.st=nil) and (p^.dr<>nil)) or ((p^.st<>nil) and (p^.dr=nil)) then write(p^.inf,' '); p6(p^.st); p6(p^.dr) end end; R2.7.6. S se scrie un subprogram pentru aflarea numrului de noduri de pe un nivel dat dintr-un arbore binar. function p7(p:arbore;k:integer):integer; begin if p<>nil then if k=l then p7:=1+p7(p^.st,k+1)+p7(p^.dr,k+1) else p7:=p7(p^.st,k+1)+p7(p^.dr,k+1) else p7:=0 end; Probleme propuse: 1. Se d un graf orientat cu n noduri. S se verifice dac exist un nod avnd gradul interior n-1 i gradul exterior 0. 2. Fie G = (X,U) un graf orientat i far circuite. S se determine o renumerotare a vrfurilor sale astfel ncat dac (u,v)U, atunci numrul de ordine al lui u este mai mic dect numrul de ordine al lui v (sortare topologic). 3. Fie G = (X,U) un graf orientat cu n vrfuri. S se determine un alt graf avnd aceleai vrfuri, aceeai matrice a drumurilor i avnd un numr minim de arce (se pot scoate, introduce noi arce).
98

4. La un turneu particip n juctori, fiecare juctor jucnd pe rnd mpotriva celorlali juctori. tiind c nu exist jocuri egale, s se construiasc o list care s cuprind toi juctorii astfel ncat doi juctori i, j sunt alturi dac juctorul i la nvins pe juctorul j. 5. La curtea regelui Artur s-au adunat 2n cavaleri i fiecare din ei are printre cei prezeni cel mult n-1 dumani. S se arate c Merlin, consilierul lui Artur, poate s-i aeze n aa fel pe cavaleri la o masa rotund nct nici unul dintre ei s nu stea alturi de vreun duman. 6. Fie G=(X,U) un graf conex cu n noduri. S se determine eficient cel mai mic k astfel nct tergnd nodurile etichetate cu 1,2...k, n aceast ordine s rezulte un graf ale crui componente conexe au toate cel mult n/2 noduri. 7. S se determine, ntr-un graf conex, un ciclu care conine dou noduri date, dar nu conine un al treilea nod. 8. Numim transpusul unui graf G = (X,U), graful care are aceeai mulime de noduri, arcele sale fiind arcele grafului G, dar avnd sens opus. Dndu-se G prin matricea de adiacen sau prin liste de vecini, s se determine n fiecare caz transpusul grafului dat. 9. Find date n persoane n care fiecare persoan se cunoate pe sine i eventual alte persoane. S se formeze grupuri n care fiecare persoan s cunoasc toate celelalte persoane din grup (o persoan aparine unui singur grup). Relaia x cunoate pe y nu este n mod normal nici simetric, nici tranzitiv. Indicaie: Se asociaz problemei date un graf orientat cu n noduri i se construiete matricea de adiacen (a[i,j]=1 daca i cunoaste pe j =i 0 dac i nu cunoate pe j). Pentru fiecare persoan neataat la un moment dat unui grup se va construi grupul din care face parte aceasta. Soluia nu este unic. 10. S se determine, ntr-un graf turneu, un drum elementar care trece prin toate vrfurile. Un graf turneu este un graf orientat cu proprietatea c ntre oricare dou vrfuri distincte exist un arc i numai unul. Indicaie: Se adaug arcul format din nodurile 1 i 2 ntr-o list liniar. Fiecare din vrfurile urmtoare se adaug la drumul creat anterior fie n fa, fie la sfrit, fie intercalat n list. 11. Fie G=(X,U) un graf ponderat. S se calculeze diametrul grafului. Se numete diametrul unui graf, notat d(G), d(G)=max{l[i]/ iX}, unde l[i] este lungimea drumului maxim care are ca extremitate iniial vrful i.
99

12. Fie G un graf orientat n care fiecare arc are asociat un cost pozitiv. S se determine un circuit elementar care s treac prin toate vrfurile grafului care s aib cost minim. 13. Se consider un grup de n persoane. Fiecare persoana are cel puin n/2 prieteni i cel mult k dumani n grup. Una din persoane are o carte pe care fiecare dorete s o citeasc. S se determine o modalitate prin care cartea s circule pe la fiecare persoan o singur dat, transmiterea ei facndu-se numai ntre doi prieteni, iar n final cartea s ajung din nou la proprietarul crii. 14. Pentru un graf dat n numerotare aciclic (orice arc u = (x,y) din U satisface condiia x<y), determinai distana minim de la vrful 1 la toate celelate vrfuri z pentru care exist drumuri de la 1 la z, precum i cte un drum de lungime minim. Sunt date arcele i lungimile lor. 15. Ptratul unui graf orientat G se determin astfel: exist arc de la x la y n ptratul unui graf dac exist n G un drum de lungime 2 de la x la y. S se determine ptratul unui graf cnd graful este reprezentat fie prin liste de adiacen, fie prin matricea de adiacen. 16. Se d un graf orientat aciclic i se cere aranjarea vrfurilor sale astfel nct orice arc are prima extremitate naintea celei de-a doua extremiti n aranjare. 17. Se d un graf orientat aciclic, n care numrul maxim de arce n orice drum este k. S se determine o partiie a mulimii vrfurilor grafului n cel mult k submulimi, astfel nct pentru orice dou noduri x,y din aceeai submulime s nu existe drum de la x la y i nici de la y la x. Indicaie: Graful este aciclic, deci exist noduri cu gradul 0 i se formeaz prima submulime cu aceste noduri i apoi se vor elimina aceste noduri din graf mpreuna cu arcele ce pleac din ele obinnduse un graf orientat aciclic pentru care se reia procedeul. 18. Un graf orientat se numete semi-conex dac pentru pentru orice pereche de vrfuri diferite x i y exist drum de la x la y sau drum de la y la x. S se verifice dac G este semi-conex. 19. 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. 20. Se consider o clas de n ( n <= 40 ) cursani ntre care exist relaii de simpatie, nu neaparat reciproce. S se formeze grupuri de cursani ntre care exist relaii de prietenie reciproc. Un cursant nu poate s aparin mai multor grupuri.
100

3. Metode pentru rezolvarea problemelor


3.1. Metoda Divide et Impera 3.1.1. Prezentarea metodei Metoda general de programare cunoscut sub numele de divide et impera (dezbin i stapnete) const n mprirea repetat a unei probleme n subprobleme de acelai tip, dar de dimensiune mai mic, urmat de combinarea soluiilor subproblemelor rezolvate pentru a obine soluia problemei iniiale. Fiecare subproblem se rezolv direct dac dimensiunea ei este suficient de mic nct s poat fi rezolvat imediat cu un procedeu specific, altfel este mprit n subprobleme mai mici folosind acelai procedeu prin care a fost descompus problema iniial. Procedeul se reia pn cnd, n urma descompunerilor repetate, se ajunge la probleme care admit rezolvare imediat. Algoritmul fiind de natur repetitiv i deoarece subproblemele au aceeai form cu cea a problemei iniiale, metoda Divide et impera poate fi implementat elegant folosind o funcie recursiv. n continuare este dat funcia general care implementeaz algoritmul. function divimp(X: problema) if (X este suficient de mica) then y rezolv(X) else{ descompune problema x n subproblemele X1, X2,, Xk for i 1 to k do yi divimp(Xi) /* combin y1, y2, , yk pentru a obine y soluia problemei X */ y combin(y1, y2, , yk) return y } Uneori recursivitatea se poate nlocui cu un ciclu iterativ. Versiunea iterativ poate fi mai rapid i folosete mai puin memorie comparativ cu varianta recursiv care utilizeaz o stiv pentru memorarea apelurilor. 3.1.2. Probleme rezolvate R3.1.1. [Cel mai mare divizor comun] Fie n numere naturale nenule x1, x2,,xn. S se calculeze cmmdc pentru numere date.
101

Rezolvare: program divizor_comun; var x:array[1..25] of integer; n, i:integer; function Divizor(a,b:integer):integer; begin while a<>b do if a>b then a:=a-b else b:=b-a; Divizor := a end; function cmmdc(lo,hi:integer):integer; var m:integer; begin if (hi-lo<=1) then cmmdc := Divizor(x[lo],x[hi]) else begin m:=(lo+hi) div 2; cmmdc:= Divizor(cmmdc(lo,m), cmmdc(m+1,hi)); end; end; begin write('n = '); readln(n); writeln('Introduceti numerele'); for i:=1 to n do begin write('x[',i,'] = '); readln(x[i]) end; writeln('cmmdc:= ', cmmdc(1,n)); end. R3.1.2. [Cutare binar] Fie x1, x2,,xn un ir de numere ntregi ordonate cresctor i x un numr ntreg. S se verifice dac x se afl printre elementele irului i dac da, s se afieze poziia acestuia. Rezolvare: program cautare; uses crt; var x:array[1..100] of integer; nr:integer; function cauta(lo,hi:integer):integer; var m:integer; begin if (lo<=hi) then begin m:=(lo+hi) div 2; if nr=x[m] then cauta:=m else if nr<x[m] then cauta:=cauta(lo,m-1) else cauta:=cauta(m+1,hi) end else cauta:=0 end;
102

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

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

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

4. Se d o plac de tabl cu lungimea x i limea y avnd n guri date prin coordonatele lor ntregi. Se cere s se decupeze o bucat dreptunghiular de arie maxim i fr guri tiind c sunt permise numai tieturi orizontale i verticale. 5. Se consider un vector de lungime n. Se numete plierea vectorului operaia de suprapunere a unei jumti (donatoare) peste cealalt jumtate (receptoare). Dac n este impar elementul din mijloc se elimin. Elementele rezultate dup pliere vor avea numeroatarea jumtii receptoare. Plierea se poate repeta pn cnd se obine un singur element (final). Scriei un program care s determine toate elementele finale posibile i s afieze succesiunile de plieri corespunztoare. Rezolvai aceiai problem innd cont c la pliere fiecare element receptor se dubleaz i din acesta se scade elementul donator corespunztor. 6. Rezolvai problema turnurilor din Hanoi folosint dou tije de manevr. Comparai numrul de mutri efectuate. 7. Fie P(x) un polinom de grag n cu coficieni reali. S se evalueze polinomul n punctul x0 folosind metoda Divide et Imera. 8. Scriei o procedur Divide et Impera pentru inversarea unui ir de caractere. 9. Se d un dreptunghi prin dimensiunile sale numere naturale. Dreptunghiul trebuie descompus n ptrate cu laturi numere naturale, paralele cu laturile dreptunghiului iniial. Se cere numrul minim de ptrate n care se poate descompune dreptunghiul. 10. Se dau un ptrat i un cerc. Se cere s se calculeze aria lor comun cu precizie de o zecimal. Coordonatele se citesc de la tastatur i sunt numere reale. Aria se va afia pe ecran. 11. Un arbore cartezian al unui vector este un arbore binar definit recursiv astfel: rdcina arborelui este elementul cel mai mic din vector; subarborele stng este arborele cartezian al subvectorului stng (fa de poziia elementului din rdcin); subarborele drept este arborele cartezian al subvectorului drept. Se d un vector de dimensiune n. S se afieze arborele su cartezian.

106

3.2. Metoda programrii dinamice 3.2.1. Principii fundamentale ale programrii dinamice Programarea dinamic, ca i metoda divide et impera, rezolv problemele "combinnd" soluiile subproblemelor. Un algoritm bazat pe programare dinamic rezolv fiecare subproblem o singur dat i, apoi, memoreaz soluia ntr-un tablou, prin aceasta evitnd recalcularea soluiei dac subproblema mai apare din nou i subprobemele care apar n descompunere nu sunt independente. Metoda programrii dinamice se aplic problemelor de optimizare. n problemele de optim metoda const n determinarea soluiei pe baza unui ir de decizii d1, d2, d3....dn, unde di transform problema din starea si-1 n starea si. Paii pentru rezolvarea unei probleme folosind programarea dinamic: 1. Caracterizarea structurii unei soluii optime; 2. Definirea recursiv a valorii unei soluii optime; 3. Calculul valorii unei soluii optime 4. Construirea unei soluii optime din informaia calculat. Principii fundamentale ale programrii dinamice: 1. Dac d1, d2, ... dn este un ir optim de decizii care duc un sistem din starea iniial n starea final, atunci pentru orice i (1in) d1, d2, ... di este un ir optim de decizii. 2. Dac d1, d2, ... dn este un ir optim de decizii care duc un sistem din starea iniial n starea final, atunci pentru orice i (1in) di, di+1, ... dn este un ir optim de decizii. 3. Dac d1, d2, ... , di, di+1 ... dn este un ir optim de decizii care duc un sistem din starea iniial n starea final, atunci pentru orice i (1in) d1, d2,... , di i di, di+1, ... dn sunt dou iruri optime de decizii. 3.2.2. Probleme rezolvate R3.2.1. [Subir cresctor maximal] Se consider un ir de n numere ntregi. S se determine cel mai lung subir cresctor din acesta. Exemplu: n=8 7 1 8 2 11 4 12 3 Subirul cresctor maximal: 7 8 11 12 cu lungimea 4 Rezolvare: Se construiete tabloul L reprezentnd lungimea maxim a unui subir maximal care l conine ca prim element pe a[i] astfel
107

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 - deoarece soluia unei subprobleme se afl pe baza subproblemelor din urm). Implementare Pascal: var i,j,n,poz,max:integer; l,a:array[1..30] of integer; begin write('n=');read(n); for i:=1 to n do begin write('a[',i,']='); read(a[i]) end; for i:=1 to n do l[i]:=0; l[n]:=1; for i:=n-1 downto 1 do begin max:=0; for j:=1+i to n do if (a[j]>a[i]) and (max<l[j]) then max:=l[j]; l[i]:=1+max end; max:=0; for i:=1 to n do if max<l[i] then begin max:=l[i]; poz:=i end; write(a[poz],' '); i:=poz; while max>1 do begin if (a[i]>a[poz]) and (l[i]=max-1) then begin poz:=i; write(a[poz],' '); max:=max-1 end; i:=i+1 end end. Implementare C: #include<stdio.h> void main(){ int n,i,j,poz,max,a[100],l[100]; printf("n=");scanf("%d",&n); for (i=1;i<=n;i++) scanf("%d",&a[i]);
108

} Exerciiu: S se rezolve aceast problem folosind varianta napoi de programare dinamic (soluia unei subprobleme se afl pe baza subproblemelor dinainte). Indicaie: Tabloul L se construiete 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. R3.2.2. [Datorii] Domnul Tudor s-a mprumutat de n ori de la o banc cu diferite sume de bani. El trebuie s restituie banii bncii, dar dup prima restituire tie c nu mai poate restitui toate sumele mprumutate la rnd ci doar acelea care nu au fost mprumutate n etape succesive. S se determine suma maxim pe care o poate recupera banca i care sunt mprumuturile restituite. Rezolvare: Elementele tabloului L se calculeaz dup formula L[i]=a[i]+max{L[j] / j>i+1]} Implementare Pascal: var a,l:array[1..100]of integer; max,n,i,j,poz:integer; begin read(n);
109

for(i=1;i<=n;i++) l[i]=0; l[n]=1; for (i=n-1;i>0;i--){ max=0; for (j=i+1;j<=n;j++) if ((max<l[j])&&(a[j]>a[i])) max=l[j]; max=max++; l[i]=max; } max=0; for(i=1;i<=n;i++) if (l[i]>max) {max=l[i];poz=i;} printf(" %d ",a[poz]); i=poz; while (max>1){ if ((a[i]>a[poz]) &&(l[i]==max-1)) { poz=i; printf("%d ",a[poz]); max=max-1; } i++; }

end. Implementare C: #include<stdio.h> void main(){ int n,i,j,poz,max,a[100],l[100]; printf("n=");scanf("%d",&n); for (i=1;i<=n;i++) scanf("%d",&a[i]); for (i=n;i>0;i--){ max=0; for (j=i+2;j<=n;j++) if (max<l[j]) max=l[j]; max=max+a[i]; l[i]=max; } max=l[1];poz=1; for(i=1;i<=n;i++) if (l[i]>max) {max=l[i];poz=i;} printf("suma maxima %d\n",l[1]); max=l[1];poz=1; while (max>0){ printf("%d ",a[poz]); i=poz+2;
110

for i:=1 to n do read(a[i]); for i:=n downto 1 do begin max:=0; for j:=i+2 to n do if (max<l[j]) then max:=l[j]; max:=max+a[i]; l[i]:=max end; max:=l[1];poz:=1; for i:=1 to n do if l[i]>max then begin max:=l[i]; poz:=i end; writeln('suma maxima este: ',l[1]); max:=l[1];poz:=1;write('sirul: '); repeat write(a[poz],' '); i:=poz+2; while (i<n ) and (l[i]<>max-a[poz]) do i:=i+1; max:=max-a[poz]; poz:=i; until max=0

while ((i<n) && (l[i]!=max-a[poz])) i++ ; max=max-a[poz]; poz=i; }

R3.2.3. [Subiruri comune] Dndu-se dou iruri comune s se determine cel mai lung subir comun. Rezolvare: Implementarea Pascal (varianta mersului napoi): Se construiete tabloul c care reine lungimea maxim a celui mai lung subir comun a celor dou iruri pn la i respectiv j. var a,b,d:string; i,j,n,m,max,t,v:integer; c:array[1..50,1..50] of integer; begin write('primul sir:');readln(a);write('sirul doi:');readln(b); n:=length(a);m:=length(b); for i:=1 to m do if a[1]=b[i] then c[1,i]:=1 else c[1,i]:=0; for i:=1 to n do if a[i]=b[1] then c[i,1]:=1 else c[i,1]:=0; for i:=2 to n do for j:=2 to m do if a[i]=b[j] then c[i,j]:=c[i-1,j-1]+1 else c[i,j]:=0; max:=0; for i:=1 to n do for j:=1 to m do if max<c[i,j] then begin max:=c[i,j]; t:=i; v:=j end; writeln('secventa maxima are lungimea :',max); d:=a[t]; while max>1 do begin dec(max); dec(t); d:=a[t]+d end; writeln(d); end. Exerciiu: S se implementeze n C aplicaia de mai sus. R3.2.4. [Partiii] S se determine numrul de moduri n care se poate descompune un numr natural n suma de numere. Exemplu: n=4, numrul de moduri = 5 Rezolvare: Se construiete tabloul a unde a[n][0] reprezint numrul de moduri n care se poate descompune:
111

a[n,n]=1; a[n,k]=a[n-k,0] pentru n2k; a[n,k]=a[n-k,i] pentru i de la 1 la k. Implementare C: #include <stdio.h> void main(){ int n,i,k,j,p,a[100][100]; printf("n=");scanf("%d",&n); a[1][0]=1;a[1][1]=1; for( i=2;i<=n;i++){ a[i][0]=0; for(k=1;k<=i;k++){ if(k==i) a[i][k]=1; else if(i<2*k) a[i][k]=a[i-k][0]; else { a[i][k]=a[i-k][k]; for(int l=1;l<=k-1;l++) a[i][k]=a[i][k]+a[i-k][l]; } a[i][0]=a[i][0]+a[i][k]; } } printf("nr de moduri=%d",a[n][0]); } Exerciiu: S se implementeze n Pascal aplicaia de mai sus. R3.2.5. [Drum] Dndu-se un tablou bidimensional cu elemente numere naturale. S se determine un traseu de la poziia 1,1 la poziia n,m, deplasarea fcndu-se numai n direciile S i E, astfel nct suma elementelor de pe traseu s fie maxim. Rezolvare: Implementarea Pascal este: var i,j,n,m,max,p,q:integer; a,l:array[1..10,1..10]of integer; begin read(m,n); for i:=1 to n do for j:=1 to m do read(a[i,j]); l[1,1]:=a[1,1]; for i:=2 to m do l[1,i]:=l[1,i-1]+a[1,i]; for i:=2 to n do l[i,1]:=l[i-1,1]+a[i,1]; for i:=2 to n do for j:=2 to m do
112

if l[i-1,j]>l[i,j-1] then l[i,j]:=l[i-1,j]+a[i,j] else l[i,j]:=l[i,j-1]+a[i,j]; writeln(l[n,m]); max:=l[n,m];p:=n;q:=m; write(a[n,m],' '); while (p<>1) and (q<>1) do begin if l[p-1,q] = l[p,q]-a[p,q] then p:=p-1 else q:=q-1; write(a[p,q],' '); end; write(a[1,1]); end. Exerciiu: S se implementeze aplicaia de mai sus n C. 3.2.3. Probleme propuse 1. [Triunghi] Se consider un triunghi de numere. S se calculeze cea mai mare dintre sumele numerelor ce apar pe drumurile ce pleac din vrf i ajung la baz i s se reconstituie drumul de sum maxim. n punctul (i,j) se poate ajunge numai din (i-1,j) sau (i-1,j-1). Exemplu: N=3 6 3 8 8 4 1 suma maxim este 18 i drumul 6 8 4 Indicaie: Se construiete tabloul c astfel c[i,j]=max{a[i,j]+ c[i+1,j], a[i,j]+ c[i+1,j+1]} (varianta mersului nainte). c[1,1] este suma maxim cerut. 2. [nmulirea optim a unui ir de matrice] Se dau n matrice. Asociativitatea nmulirii a dou matrice ne ofer mai multe posibiliti de a calcula produsul i care au un numr diferit de operaii. S se determine o posibilitate de asociere a nmulirii matricelor astfel nct numrul de operaii s fie minim. Indicaie: Se construiete tabloul bidimensional L, unde l[i,j] reprezint numrul minim de nmuliri pentru a efectua produsul AiAi+1.....Aj. 3. [Triangularizarea optim a poligoanelor] Se d un poligon convex i o funcie de pondere p definit pe triunghiurile formate de laturile i diagonalele poligonului. S se gseasc o triangulare care minimizeaz suma ponderilor triunghiurilor din triangularizare. Indicaie Exist o coresponden ntre triangularizarea unui poligon i parantezarea unei expresii cum ar fi produsul unui ir de matrici. 4.[ Tiprirea uniform] Textul de intrare este o succesiune de n cuvinte de lungimi l1, l2,...ln, lungimea fiind msurat n caractere. Se dore113

te tiprirea uniform a paragrafului pe un anumit numr de linii, fiecare linie avnd cel mult m caractere astfel: dac o linie conine cuvintele de la cuvntul i la cuvntul j, cu i j iar ntre cuvinte se las exact un spaiu. S se minimizeze suma cuburilor numrului de spaii suplimentare de la sfritul liniilor, n raport cu toate liniile, mai puin ultima. 5. [Problema patronului] Un patron a cumprat un calculator i dorete s nvee s lucreze cu el. Pentru aceasta va umple un raft de cri din colecia Informatica n lecii de 9 minute i 60 secunde. Raftul are lungimea L cm (L numr natural). Seria dispune de n titluri 1, 2, ,n avnd grosimile g1, g2, ..., gn cm (numere naturale). S se selecteze titlurile pe care le poate cumpra patronul, astfel nct raftul s fie umplut complet (suma grosimilor crilor cumprate s fie egal cu lungimea raftului) i numrul crilor achiziionate s fie maxim. Olimpiada Naional de Informatic 1996 Indicaie: Se construiete tabloul bidimensional a unde a[i,j] reprezint numrul maxim de cri dintre primele i (n ordinea dat la intrare) cu lungimea total j sau, 0 dac nu exist nici o submulime a mulimii primelor i cri cu lungimea total j. 6. [Planificarea unei recepii] Corporaia AMC are o structur ierarhic, relaiile de subordonare formeaz un arbore n care rdcina este preedintele. Fiecare angajat are un coeficient de convieuire (numr real). Preedintele dorete s organizeze o petrecere astfel nct nici un angajat s nu se ntlneasc cu seful su direct. Informaticianul Tom trebuie s alctuiasc lista invitailor astfel nct suma coeficienilor de convieuire a invitailor s se maximizeze i preedintele s participe la propia petrecere. 7. [Mouse] Un experiment urmrete comportarea unui oricel pus ntr-o cutie dreptunghiular, mprit n mxn cmrue egale de form ptrat. Fiecare cmru conine o anumit cantitate de hran. oricelul trebuie s porneasc din colul (1,1) al cutiei i s ajung n colul opus, mncnd ct mai mult hran. El poate trece dintr-o camer n una alturat (dou camere sunt alturate dac au un perete comun), mnnc toat hrana din cmru atunci cnd intr i nu intr niciodat ntr-o camer fr hran. Stabilii care este cantitatea maxim de hran pe care o poate mnca i traseul pe care l poate urma pentru a culege aceast cantitate maxim. Se d n, m i cantitatea de hran existent n fiecare cmeru (numere ntre 1 i 100). Olimpiada judeean de informatic, 2002
114

Exemplu: 24 1263 3412 Ieire: 7 21 1 1 --> 2 1 --> 2 2 --> 1 2 --> 1 3 --> 1 4 -->2 4 8. [Semne] Pentru n numr natural, s se gseasc o combinaie de semne + i - (adic un vector x = (x(1), x(2), ..., x(k)), x(i) se afl n <-1, 1>) i un numr k natural nenul astfel nct: n = x(1)*12+x(2)*22+...+x(k)*k2. Datele se citesc dintr-un fiier text ce conine pe fiecare linie cte un numr ce reprezint valorile lui n pentru care se doresc reprezentri ca mai sus. Datele de ieire vor fi introduse ntr-un fiier text pe cte o linie combinaia de semne corespunztoare. Exemplu: Intrare: 2 4 8 5 Ieire: ---+ --+ --++--+ ++--+ Indicaie: Pentru k ncepnd de la 1, se gsesc ntr-o list numerele care se pot obine cu k semne; lista pentru k se obine din cea pentru k-1. Pentru unele numere k este foarte mare i programul nu ar intra n timp. O alt soluie ar fi folosirea observaiei: (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 adugarea secvenei + - - + se ajunge de la un numar n la n+4. Dac am obine secvenele pentru n = 0, 1, 2 i 3, am rezolva problema. Acestea sunt: 0 secvena vid 1+ 2 - - - + (dat n exemplu) 3 - (pentru -1), apoi + - - +

115

9. [ah] a) Dndu-se dou poziii pe o tabl de ah de dimensiune ptratic nxn, s se determine cel mai scurt drum dintre acestea utiliznd mutrile calului. b) Determinai numrul minim de cai care pot fi amplasai pe o tabl de ah de dimensiune nxm astfel nct s nu se atace. 10. [Linii navale] Pe malul de nord i cel de sud al unui fluviu exist n orae. Fiecare ora are un unic ora prieten pe cellalt mal; nu exist dou orae pe un mal avnd acelai priten pe cellalt mal. Intenia este ca oraele prietene s se lege printr-o linie naval. Se impune ns restricia ca s nu existe linii navale care s se intersecteze. S se determine numrul maxim de linii navale care pot fi nfiinate, cu respectarea condiiei de mai sus. Pe prima linie a fiierului de intrare apare numrul n de perechi de orae prietene, iar pe urmtoarele n linii apar perechile de orae prietene (primul pe malul de nord, iar al doilea pe malul de sud), fiecare ora fiind specificat prin distana sa (cel mult egal cu 6000) fa de kilometrul 0 al fluviului. Indicaie: Se ordoneaz posibilele linii navale dup primul argument i se determin cel mai lung subir cresctor format din coordonatele celui de-al doilea argument. (vezi problema rezolvat 1). 11. [Drumuri minime] Se consider un graf orientat, fiecare arc avnd un cost ataat. Se cere s se determine pentru fiecare pereche de vrfuri ( i, j) i s se tipreasc lungimea drumului minim de la i la j. 12. [Submulimi de sum dat] S se determine pentru un vector dat dac un numr k se poate scrie ca sum de numere din vector, un element din vector se poate folosi o dat. Indicaie: Se construiete un tablou a cu valori logice, unde a[i] este true dac i se poate scrie ca sum de elemente din vectorul dat i false n caz contrar.

3.3. Metoda Greedy


3.3.1. Prezentarea metodei Algoritmii de tip Greedy sunt folosii la probleme de optimizare i sunt n general simpli i eficieni. Un astfel de algoritm determin soluia optim n urma unei succesiuni de alegeri. La fiecare moment decizional, din algoritm se va alege opiunea care pare a fi cea mai potrivit pe baza unui criteriu de optim local, n ideea c la final se va obine o soluie optim global.
116

n general, datele de intrare pentru un algoritm Greedy se prezint sub forma unei mulimi finite, iar soluia este o submulime sau o permutare a datelor de intrare n aa fel nct s fie ndeplinite anumite condiii de optim. Condiiile de optim cer determinarea unei soluii care maximizeaz sau minimizeaz o funcie dat, numit funcie obiectiv. Dac un element este inclus n soluie el va rmne n aceast mulime, nu se face nici o revenire asupra unei decizii luate. Selectarea unui element la un moment dat poate depinde de elementele alese pn la acel moment dar nu depinde de cele care urmeaz s fie alese ulterior. Dac un element a fost selectat, dar nu poate face parte din soluie atunci acest element nu va mai fi luat n calcul la alegerile urmtoare. n acest fel se poate ajunge rapid la o soluie, dar nu se asigur (pentru toate problemele) optimalitatea global. Exist i probleme pentru care o astfel de metod nu conduce la soluie, dei aceasta exist. Problemele care se pot rezolva folosind algoritmi de tip Greedy trebuie s verifice dou proprieti: proprietatea alegerii Greedy i substructura optimal. Proprietatea alegerii Greedy spune c se poate ajunge la o soluie de optim global dac la fiecare pas de decizie se selecteaz un element care ndeplinete criteriul de optim local. Proprietatea de structur optimal spune c soluia optimal a problemei conine soluiile optimale ale subproblemelor. O problem care se va rezolva folosind o strategie Greedy este dat de: O mulime finit de candidai care reprezint datele de intrare; O funcie care verific dac o anumit mulime de elemente constituie o soluie posibil, nu neaparat optim, a problemei; O funcie care verific dac o submulime a datelor de intrare este o soluie parial a problemei; O funcie de selecie care alege la orice moment cel mai potrivit candidat dintre elementele nefolosite nc; O funcie obiectiv care trebuie minimizat sau maximizat. Un algoritm Greedy nu furnizeaz dect o singur soluie. n contiunare este prezentat forma general a metodei.
117

function greedy(C) {C este mulimea datelor de intrare } S {S este multimea care va conine soluia} while not Soluie(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 soluie) Aceast metod i gsete multe aplicaii n teoria grafurilor la determinarea unui arbore parial de cost minim (Kruskal, Prim), la determinarea drumurilor de cost minim de la un vrf la celelalte vrfuri ale unui graf (Dijkstra), compresia datelor (arbori Huffman) .a. 3.3.2. Probleme rezolvate R3.3.1. [Problema continu a rucsacului] Avem la dispoziie un rucsac cu care se poate transporta o greutate maxim G. Trebuie s alegem din n obiecte pentru care se cunoate greutatea gi i profitul pi care se obine prin transportul obiectului i cu rucsacul. S se determine obiectele care trebuiesc alese pentru transport astfel nct profitul obinut s fie maxim, iar greutatea total a acestora s nu depeasc G tiind c putem lua orice parte dintr-un obiect. Rezolvare: Programul n C este: #include <stdio.h> #define MAX 25 void main(){ int p[MAX]; int g[MAX]; int n,i,j,aux,nr[MAX]; float G, gr,profit,sol[MAX]; printf("Greutatea maxima G = ");scanf("%f",&G); printf("Numarul de obiecte: "); scanf("%d", &n); for (i=0; i<n; i++){ printf("Obiectul nr. %d:\n",i+1); printf("Greutatea = "); scanf("%d",&g[i]); printf("Profitul = "); scanf("%d",&p[i]); sol[i] = 0.0; nr[i] = i; }
118

/* ordonare descrescatoare dupa raportul p/g */ for (i=0;i<n-1;i++) for (j=i+1;j<n;j++) if(p[i]/g[i] < p[j]/g[j]){ aux=p[i]; p[i]=p[j]; p[j]=aux; aux=g[i]; g[i]=g[j]; g[j]=aux; aux=nr[i]; nr[i]=nr[j]; nr[j]=aux; } /*alegere */ gr = G; for (i=0; i<n && g[i]<gr; i++){ sol[i] = 1.0; //100% gr -= g[i]; } if (i < n) sol[i] = gr/g[i]; /*afisare zezultate */ profit = 0.0; for (i=0;i<n;i++) if(sol[i] > 0){ printf("Obiect %d - %5.2f%%\n", nr[i]+1, sol[i] *100); profit += sol[i] * p[i]; } printf("Profit = %5.2f", profit); } R3.3.2.[Planificarea activitilor] ntr-o sal, ntr-o zi trebuie planificate n activiti, pentru fiecare activitate se cunoate intervalul n care se desfoar [s, f). Se cere s se planifice un numr maxim de activiti astfel nct s nu se suprapun. Rezolvare:Programul Pascal este: program Activitati; uses crt; const max=100; var n,i,j,aux:integer; s,f:array[1..max] of integer; sol:array[1..max] of 0..1; nsol, finish:integer; begin { citire date }
119

write('Nr de activitati = '); readln(n); for i:=1 to n do begin writeln('Activitatea nr. ',i,':'); write('Start = '); readln(s[i]); write('Finish = '); readln(f[i]); sol[i]:=0; end; {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]; s[i]:=s[j]; s[j]:=aux; aux:=f[i]; f[i]:=f[j]; f[j]:=aux; end; {calcul} finish := 0; for i := 1 to n do if (s[i] >= finish ) then begin sol[i]:=1; finish := f[i]; end; {afisare rezultate} writeln('Solutie:'); j := 1; for i := 1 to n do if sol[i]=1 then begin writeln('Activitatea nr. ',j,': ', s[i], ' - ' ,f[i]); j := j + 1; end; end. R3.3.3. [Schimbarea banilor] Presupunem c a avem la dispoziie k tipuri de monede cu valorile c0, c1, ck-1 unde cN*, s se scrie un program care s determine o modalitate de schimb a unei sume S folosind un numr minim de monede (numrul de monede din fiecare tip fiind nelimitat). Rezolvare: Programul C este:
120

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

end.

if t = n5 then begin inc(k); n5 := 5*f[k] end end; for i:=1 to n do write(f[i],' '); readln;

R3.3.5. [Copaci i ciori] Pe n copaci aezai n cerc se afl n-1 ciori, maxim una pe fiecare copac. Dndu-se o configuraie iniial i una final a ciorilor i tiind c la un moment dat o singur cioar poate zbura de pe copacul ei pe cel liber, s se scrie un program care s determine o secven de zboruri pentru a ajunge la configuraia final. Rezolvare: Programul C este: #include <stdio.h> #define MAX 10 int initial[MAX]; int final[MAX]; int n; int CopacLiber(){ int i=0; while(initial[i]!=0) i++; return i; } int Copac(int c){ int i=0; while(initial[i] != c) i++; return i; } void Zboara(int s,int d){ printf("Cioara %d zboara de pe copacul %d pe %d !\n", \ initial[s], s+1,d+1); initial[d] = initial[s]; initial[s] = 0; } void main(){ int i, k; printf("n = "); scanf("%d",&n); printf("Introduceti configuratia initiala (0 pt. liber):\n"); for(i=0;i<n;i++) {printf("initial[%d] = ",i+1); scanf("%d",&initial[i]);} printf("Introduceti configuratia finala (0 pt. liber):\n"); for(i=0;i<n;i++) {printf("final[%d] = ",i+1);scanf("%d",&final[i]);} for(i=0;i<n;i++) if (final[i] && initial[i] != final[i]){ if(initial[i]) { k = CopacLiber(); Zboara(i,k); } k = Copac(final[i]); Zboara(k,i); } }
122

R3.3.6. [Problema comis-voiajorului] Un comis-voiajor trebuie s viziteze un numr de n orae i s revin n oraul de plecare. Cunoscnd legturile dintre oricare dou orae se cere s se afieze cel mai scurt traseu posibil pe care poate s-l parcurg comisvoiajorul tiind c nu trebuie s treac de dou ori prin acelai ora. Rezolvare: Programul Pascal este: program comis; const max = 25; var harta:array[1..max,1..max] of integer; traseu:array[1..max] of integer; v:array[1..max] of 0..1; i,j,k,min,n,lungime,pos:integer; begin write('n = '); readln(n); for i:=1 to n-1 do for j:=i+1 to n do begin write('distanta[',i,', ', j,'] = '); readln(harta[i,j]); harta[j,i]:=harta[i,j]; end; write('Orasul de pornire = '); readln(k); lungime:=0; traseu[1]:=k; v[k]:=1; for i:=2 to n do begin min:=maxint; for j:=1 to n do if v[j] = 0 then if harta[k, j] < min then begin min := harta[k, j]; pos := j end; inc(lungime,min); traseu[i]:=pos; v[pos]:=1; k:=pos end; inc(lungime,harta[k,1]); for i:=1 to n do write(traseu[i]:3); writeln(traseu[1]:3); writeln('lungimea = ', lungime); readln; end.
123

3.3.3. Probleme propuse 1. [Problema planificrii optime a lucrrilor] Se presupune c avem de executat un numr de n lucrri, cunoscndu-se pentru fiecare lucrare i termenul de finalizare ti i penalizarea pi pltit n cazul n care lucrarea nu este predat la termen. tiind c fiecare lucrare este executat ntr-o unitate de timp i c nu se pot executa mai multe lucrri simultan, s se planifice ordinea de execuie a lucrrilor astfel nct penalizarea total s fie minim. 2. [Amplasarea canalelor] n jurul unui ora avem N bazine cu ap ce trebuiesc unite ntre ele prin canale. Fiecare bazin poate fi unit prin cte un canal cu mai multe bazine. Perechile de bazine ce vor fi unite sunt date ntr-o list. Un canal poate trece doar prin interiorul sau exteriorul cercului format de bazine. Se cere modul de amplasare al fiecrui canal. 3. Se dau numerele ntregi nenule a1, a2, , an i b1, b2, , bm cu n m. S se determine o submulime {x1, x2, , xm} a mulimii {a1, a2, , an} care s maximizeze expresia E = b1x1 + b2x2 + + bmxm. 4. ntr-un depozit al monetriei statului sosesc n saci cu monezi. Se cunoate numrul de monezi din fiecare sac i se dorete mutarea monezilor dintr-un sac n altul n aa fel nct n fiecare sac s apar acelai numr de monezi. Scriei un program care rezolv problema efectund un numr minim de mutri. 5. Fie n iruri ordonate cresctor S1, S2, , Sn cu lungimile L1, L2, , Ln. S se interclaseze cele n iruri obinndu-se un singur ir cresctor de lungime L1 + L2 + + Ln cu un numr minim de comparaii ntre elementele irurilor. 6. Fie X = {x1, x2, ,xn} o mulime de numere reale. S se detmine o mulime de cardinal minim de intervale de lungime 1 a cror reuniune s includ mulimea X. 7. Se cunosc poziiile oraelor unei ri date prin coordonatele lor. S se determine configuraia unei reele telefonice astfel nct toate oraele s fie conectate la reea i costul reelei s fie minim. 8. Se dau n i k, naturale, kn. S se construiasc un tablou nn care ndeplinete simultan condiiile: conine toate numerele de la 1 la n2 o singur dat; pe fiecare linie numerele sunt aezate n ordine cresctoare, de la stnga la dreapta; suma elementelor de pe coloana k s fie minim. 9. Un instructor de schi trebuie s distribuie n perechi de schiuri la n elevi nceptori. Descriei un algoritm care s fac distribuirea n aa
124

fel nct suma diferenelor absolute dintre nlimea elevului i lungimea schiurilor s fie minim. 10. Se d un polinom P(X) cu coeficieni ntregi. S se afle toate rdcinile raionale ale polinomului. 11. Se dau n puncte n plan prin coordonatele lor numere ntregi. S se construiasc, dac este posibil, un poligon convex care s aib ca vrfuri aceste puncte. 12. Fiind dat o hart cu n ri, descriei un algoritm euristic care s determine o modalitate de colorare a hrii astfel nct dou ri care se nvecineaz s fie colorate diferit. 13. Descriei un algoritm euristic care s determine o modalitate prin care un cal aflat n colul stnga-sus s strbat ntreaga tabl de ah fr a trece de dou ori prin aceeai poziie. 14. Descriei un algoritm euristic care s schimbe o sum S dat folosind un numr minim de monete avnd valorile v1, v2, , vn.

3.4. Metoda backtracking


3.4.1.Prezentarea metodei Aceast tehnic se folosete la rezolvarea problemelor a cror soluie se poate reprezenta sub forma unui vector S = x1x2...xn cu x1 S1, x2 S 2, , xn S n, iar mulimile S1, S2, , Sn, care pot coincide, sunt mulimi finite ordonate liniar (pentru orice element, cu exceptia ultimului este cunoscut succesorul). Pentru fiecare problem concret sunt precizate relaiile dintre componentele vectorului care memoreaz soluia, numite condiii interne. Mulimea S = S1 S1 se numete spaiul soluiilor, iar elementele produsului cartezian care satisfac i condiiile interne se numesc soluii rezultat. Metoda evit generarea tuturor combinaiilor completnd pe rnd componentele vectorului soluie cu valori ce ndeplinesc condiiile de continuare, scurtndu-se astfel timpul de calcul. Vectorul x este privit ca o stiv, lui xk nu i se atribuie o valoare dect dup ce x1, , xk-1 au primit valori. La nceput xk este iniializat la o valoare (cu ajutorul unei funcii init) al crei succesor este primul element din Sk. Cu ajutorul unei funcii succesor xk ia valoarea primului element din Sk. Dup ce xk a primit o valoare, nu se trece direct la atribuirea unei valori lui xk+1 ci se verific mai nti anumite condiii de continuare referitoare la x1, , xk cu ajutorul unei funcii valid de tip logic. Dac aceste condiii sunt satisfcute se verific dac s-a obinut o soluie caz n care se trece la afiarea acesteia.
125

Nendeplinirea condiiilor de continuare exprim faptul c oricum am alege xk+1, , xn, nu vom ajunge la o soluie. n acest caz se face o nou alegere pentru xk sau, dac Sk a fost epuizat, se micoreaz k cu o unitate i se ncearca o nou alegere pentru xk (k >0) din restul elementelor lui Sk nc nealese folosind funcia succesor. Ca urmare se trece la atribuirea unei valori lui xk+1 doar dac sunt ndeplinite condiiile de continuare. Algoritmul se termin n momentul n care au fost luate n calcul toate elementele mulimii S1. Metoda backtracking poate fi descris prin urmtoarea procedur (n varianta iterativ): k := 1; init(k, st); while k > 0 do begin repeat succesor(as, st, k); if as then valid(ev, st, k); until (not as) or (as and ev); if as if solutie(k) then tipar else begin k := k + 1; init(k, st) end else k := k 1; end; Rezolvarea problemelor prin aceast metod necesit un timp mare de execuie, motiv pentru care metoda este recomandat numai n cazurile n care spaiul soluiilor este destul de redus, sau dac nu se cunoate un alt algoritm mai rapid. Metoda admite i o variant recursiv n care stiva nu este gestionat explicit de programator. n continuare este dat forma general a procedurii backtracking n variant recursiv (care se va apela cu Back(1)): procedure Back(k); var i:integer; begin if solutie(k) then tipar(x) else begin init(k,x); while succesor(x,k) do begin x[k]:=i; if valid(x,k) then Back(k+1) end; end end;
126

3.4.2. Probleme rezolvate R3.4.1. [Permutri] Se d un numr n N, se cere s se genereze toate permutrile mulimii {1, 2, ,n}. Rezolvare: program permutari; uses crt; type stack = array[1..25] of integer; var st: stack; n:integer; k:integer; as, ev: boolean; procedure init(k:integer; var st: stack); begin st[k]:=0 end; procedure succesor(var as:boolean; var st: stack; k:integer); begin if st[k] < n then begin st[k] := st[k] + 1; as := true end else as:=false; end; procedure valid(var ev:boolean; st: stack; k:integer); var i:integer; begin ev:=true; for i:=1 to k-1 do if st[k] = st[i] then ev:=false end; function solutie(k:integer) :boolean; begin solutie:=(k=n) end; procedure tipar; var i:integer; begin for i:=1 to n do write(st[i],' '); writeln end; begin write ( ' n = ' ); readln(n) ; k:=1; init(k,st); while (k>0) do begin repeat succesor (as, st, k) ; if as then valid(ev,st,k); until (not as) or (as and ev) ; if as then if solutie(k) then tipar else begin k:=k+1; init(k,st) end else k:=k-1 end; end.
127

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

R3.4.3. [Problema damelor] Pe o tabl de ah trebuie aezate opt dame astfel nct s nu existe dou dame pe aceeai linie, coloan sau diagonal. Problema se generalizeaz imediat pentru n dame pe o tabl cu n linii i n coloane. S se determine toate soluiile. Rezolvare : #include <stdio.h> #include <conio.h> #include <math.h> typedef int stack[25]; stack st; int n; void tipar(){ int j; for(j = 0; j < n; j++) printf("%d ", st[j]); printf("\n"); } void dame(int k){ int i,j, valid; if (k==n) tipar(); else for(i = st[k]+1; i <= n; i++) { st[k] = i; valid = 1; for(j = 0; j < k; j++) if ((st[j]==st[k])||(abs(st[k]-st[j])==k-j)) valid = 0; if (valid ==1) dame(k+1); } st[k] = 0; } void main(){ int i; printf("n = "); scanf("%d",&n); for(i = 0; i < n; i++) st[i]=0; dame(0); getch(); } R3.4.4. [Problema colorrii hrilor] Fiind dat o hart cu n ri, se cer toate soluiile de colorare a hrii utiliznd un numr minim de culori, astfel nct dou tri cu frontier comun s fie colorate diferit. Menionm c este demonstrat faptul c sunt suficiente 4 culori pentru a colora orice hart.
129

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

R3.4.5. [Sritura calului] Se consider o tabl de ah n x n i un cal plasat n colul din stnga sus. Se cere s se afieze toate posibilitile de mutare a calului astfel nct s treac o singur dat prin fiecare ptrat al tablei. Rezolvare: #include <stdio.h> #include <conio.h> typedef int tabla[25][25]; int linT[8] = {-1,+1,+2,+2,+1,-1,-2,-2}; int colT[8] = {+2,+2,+1,-1,-2,-2,-1,+1}; tabla tab; int n; void tipar(){ int i,j; for(i = 0; i < n; i++){ printf("\n"); for(j = 0; j < n; j++) printf("%3d", tab[i][j]); } printf("\n"); getch(); } void cal(int lin, int col, int k){ int i,lin2,col2; if (tab[lin][col]) return; k++; tab[lin][col]=k; if (k==n*n) tipar(); else for (int i = 0; i < 8; i++){ lin2 = lin + linT[i]; col2 = col + colT[i]; if (lin2>=0 && lin2<n && col2>=0 && col2<n) cal(lin2,col2,k); } tab[lin][col] = 0; } void main(){ int i,j; printf("n = "); scanf("%d",&n); for(i = 0; i < n; i++) for(j = 0; j < n; j++) tab[i][j]=0; cal(0,0,0); printf("\n%d solutii",t); }
131

3.4.3. Probleme propuse 1. Se dau numerele naturale n i k, s se genereze toate aranjamentele (funciile injective) de elemente din mulimea {1, 2, , n} luate cte k. 2. Fie dou numere naturale n i k cu n k, se cere s se genereze toate submulimile (combinrile) de k elemente din mulimea {1, 2, ,n}. 3. Se dau mulimile A1 = {1, 2, , p1}, A2 = {1, 2, , p2}, , An = {1, 2, , pn} se cere s se genereze produsul cartezian al mulimilor A1, A2, , An. 4. S se descompun un numr natural n n toate modurile posibile ca sum de numere naturale. 5. Se consider mulimea {1, 2, , n}. Se cer toate partiiile acestei mulimi. 6. Se d o sum S i n tipuri de monede avnd valorile v1, v2, , vn lei. Se cer toate modalitile de plat a sumei S utiliznd aceste monede. 7. Considerndu-se o tabl de ah de dimensiuni n n, s se determine toate modalitile de amplasare a n ture pe aceast tabl n aa fel nct s nu se atace ntre ele. 8. Un ntreprinztor 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. 9. S se determine toate delegaiile de n persoane din care p femei care se pot forma din t persoane din care v femei. 10. Avem la dispoziie 6 culori: alb, negru, rou, albastru, verde, galben. S se genereze toate steagurile ce se pot forma cu trei culori diferite avnd la mijloc alb sau negru. 11. Un comis-voiajor trebuie s viziteze un numr de n orae i s revin n oraul de plecare. Cunoscnd legturile dintre orae se cere s se afieze toate drumurile posibile pe care poate s le parcurg comis-voiajorul tiind c nu trebuie s treac de dou ori prin acelai ora. 12. ntr-un grup de persoane fiecare persoan se cunoate pe sine i cunoate eventual i alte persoane din grup. S se determine toate modurile n care cele N persoane se pot repartiza n echipe astfel nct orice persoan din grup s fie cunoscut de cel puin un membru al fiecrei echipe.
132

13. Cei doi fii ai unei familii motenesc prin testament, n mod egal, o avere format din monede avnd ca valori numere ntregi pozitive. O condiie din testament cere ca fraii s mpart monezile n dou pri avnd valori egale pentru a intra n posesia lor, altfel suma va fi donat unei biserici. Scriei un program care s i ajute pe cei doi frai s intre n posesia motenirii. 14. Pe malul unui ru se gsesc c canibali i m misionari. Ei urmeaz s treac rul cu o barc cu dou locuri. Dac pe unul dintre maluri se vor afla mai muli canibali dect misionari acetia din urm vor fi mncai de canibali. Se cere un program care s afieze toate modalitile de trecere a rului n care misionarii s nu fie mncai. 15. Pentru elaborarea unui test de aptitudini avem un set de n ntrebri, fiecare fiind cotat cu un numr de puncte. S se elaboreze toate chestionarele avnd ntre a i b ntrebri distincte, fiecare chestionar totaliznd ntre p i q puncte. ntrebrile sunt date prin numr i punctaj. 16. 2n + 1 persoane particip la discuii (mas rotund) care dureaz n zile. S se gseasc variantele de aezare la mas astfel ca o persoan s nu aib n dou zile diferite acelai vecin. 17. S se determine 5 numere de cte n cifre fiecare cifr putnd fi 1 sau 2, astfel nct oricare dintre cele 5 numere s coincid n m poziii i s nu existe nici o pozitie care s conin aceeai cifr n toate cele 5 numere. 18. S se genereze o secven binar de lungime 2n+n+1 astfel nct orice dou secvente consecutive de n biti s fie diferite. 19. Se dau x1, x2, , xn numere naturale cu cel mult 9 cifre i n 100. Fiecare numr xi este reprezentat n baza bi (2 bi 10) care nu este cunoscut. S se gaseasc baza bi pentru fiecare numr xi astfel nct intervalul [a, b] n care sunt cuprinse cele n numere (dup transformarea n baza 10) s fie de lungime minim. 20. Numrul 123456789 nmulit cu 2, 4, 7 sau 8 d ca rezultat tot un numr de nou cifre distincte (fr 0). Aceast proprietate nu funcioneaz pentru numerele 3, 6 sau 9. Exist totui multe numere de nou cifre distincte (fr 0) care nmulite cu 3 au aceeai proprietate. S se listeze toate aceste numere n care ultima cifr este 9. 21. S se dispun pe cele 12 muchii ale unui cub toate numerele de la 1 la 12, astfel nct suma numerelor aflate pe muchiile unei fee s fie aceeai pentru toate feele.
133

22. Toate oraele unei ri sunt legate la o reea de linii feroviare. Dou orae i i j pot fi legate prin cel mult o legtur direct prin care circul un singur tren pe zi ntre orele p(i, j) i s(i, j). Dac se dau dou orae A i B, s se afieze traseul, staiile de schimbare a trenurilor i timpii de ateptare n aceste staii astfel nct durata total a cltoriei s fie minim. 23. Configuraia unui teren este specificat printr-o gril gen tabl de ah de dimensiune nn, fiecare careu avnd o anumit nlime. ntr-un careu precizat al grilei se plaseaz o minge. tiind c mingea se poate deplasa ntr-unul din cele maxim 8 careuri vecine doar dac acesta are o cot strict mai mic, s se genereze toate trasele pe care le poate urma mingea pentru a prsi terenul. 24. Un cal i un rege se afl pe o tabl de ah. Unele cmpuri ale tablei sunt "arse", poziiile lor fiind cunoscute. Calul nu poate clca pe cmpuri "arse", iar orice micare a calului face ca respectivul cmp s devin "ars". S se afle dac exist o succesiune de mutri permise (cu restriciile de mai sus), prin care calul s poat ajunge la rege i s revin la poziia iniial. Poziia iniial a calului, precum i poziia regelui sunt considerate "nearse". 25. Fie o matrice n x m cu valori de 0 i 1. Dndu-se o poziie iniial (i,j) s se gseasc toate ieirile din matrice mergnd doar pe elemente cu valoarea 1. 26. O fotografie alb-negru este dat printr-o matrice cu valori 0 i 1. Fotografia prezint unul sau mai multe obiecte. Punctele fiecrui obiect sunt marcate cu 1. Se cere un program care s calculeze numrul de obiecte din fotografie. 27. Se d o matrice binar n care elementele cu valoarea 1 delimiteaz o suprafa marcat cu elemente de zero. Dndu-se coordonatele unui punct n cadrul matricei s se coloreze suprafaa n interiorul creia cade punctul. 28. Se dau n puncte albe i n puncte negre n plan prin perechi (i,j) de numere ntregi. Fiecare punct alb se va uni cu un singur punct negru asttfel nct segmentele formate s nu se intersecteze. S se gseasc o soluie tiind ca oricare 3 puncte sunt necoliniare. 29. Se dau n puncte n plan prin perechi (i,j) de numere ntregi. S se selecteze 4 puncte ce reprezint colurile ptratului care cuprinde numrul maxim de puncte din cele n puncte date.

134

30. Se d un cuvnt si o matrice de caractere de dimensiune m x n. S se gseasc n matrice prefixul de lunginme maxim al cuvntului dat. 31. Se d un numr natural par n. S se afieze toate irurile de n paranteze care se nchid corect. 32. Se consider o bar de lungime n i k repere de lungimi l1, l2,, lk. Din bar trebuiesc tiate buci de lungimea reperelor date, astfel nct s avem cel puin cte o bucat de lungime li cu i = 1..k i pierderile s fie nule. 33. Se consider un numr nelimitat de piese dreptunghiulare de dimensiuni a 2a. Piesele se vor folosi la pavarea fr fisuri a unei zone rectangulare de dimensiuni ka pa. Se cer toate soluiile (reprezentare grafic).

3.5. Metoda Branch and Bound


3.5.1. Prezentarea metodei Metoda branch and bound foloseste la rezolvarea problemelor la care domeniul n care se caut soluia este foarte mare i nu se cunoate un alt algoritm care s conduc mai rapid la rezultat. Problemele care pot fi abordate prin aceast metod pot fi modelate ntr-un mod asemntor celui folosit la metoda backtracking. Se pleac de la o configuraie iniial i se reine irul de operaii prin care aceasta este transformat ntr-o configuraie final dac aceasta este dat, n alte cazuri se cere configuraia final tiind c trebuie s verifice anumite condiii de optim. Diferena dintre cele dou metode const n faptul c metoda backtracking la fiecare etap selecteaz un singur succesor dup care se face verificarea condiiilor de continuare, iar metoda branch and bound genereaz la fiecare pas toate configuraiile posibile (toi succesorii) care rezult din cea curent i le stocheaz ntr-o list. Se alege apoi un element din list dup un criteriu ce depinde de problem i se reia procesul de expandare. Alegerea optim a unui element din aceast list pentru expandare se face cu ajutorul unei funcii f = g + h n care g este o funcie care msoar lungimea drumului parcurs de la configuraia iniial pn la nodul curent, iar h este o funcie (euristic) care estimeaz efortul necesar pan se ajunge la soluie i este specific fiecrei probleme. Alegerea funciei h este foarte important din punct de vedere a vitezei de execuie a programului.
135

Se lucreaz cu dou liste: lista open n care se rein configuraiile neexpandate nc i lista close care le memoreaz pe cele expandate. Soluia se construiete folosind un arbore care se parcurge pe baza legturii tat. Nodurile sunt nregistrri care cuprind urmtoarele informaii: 1. configuraia la care s-a ajuns, t; 2. valorile funciilor g si h, 3. adresa nodului 'tat'; 4. adresa nregistrrii urmtoare n lista open sau close; 5. adresa nregistrrii urmtoare n lista succesorilor. Algoritmul este urmtorul: A. nregistrarea corespunztoare configuraiei iniiale este ncrcat n open cu g=0 i f=h; B. att timp ct nu s-a selectat spre expandare nodul corespunztor configuraiei finale i lista open este nevid, se execut urmtoarele: 1. se selecteaz din lista open nodul t cu f minim; 2. se expandeaz acest nod obinnd o list liniar simplu nlnuit cu succesorii si; 3. pentru fiecare succesor din aceast list se execut: 3.1. se ataeaz noul g, obinut ca sum ntre valoarea lui g a configuraiei t i costul expandrii (de obicei 1); 3.2. se testeaz dac acest succesor aparine listei open sau close i n caz afirmativ, se verific dac valoarea lui g este mai mic dect cea a configuraiei gsite n list: 3.2.1. n caz afirmativ, nodul gsit este direcionat ctre actualul printe (prin fixarea legturii tat) i se ataeaz noul g, iar dac acest nod se gsete n close, este trecut n open; 3.2.2. n caz c acest nod nu se gsete n open sau close, este introdus n lista open; C. dac s-a selectat pentru expandare nodul corespunztor configuraiei finale atunci se traseaz folosind o procedur recursiv drumul de la configuraia iniial la cea final utiliznd legtura 'tat'; D. dac ciclul se ncheie deoarece lista open este vid nseamn c problema nu are soluie. Observaie. Algoritmul se poate implementa folosind o singur list, iar diferenierea dintre nodurile expandate i cele neexpandate se va face dup un cmp special. Apare ns dezavantajul c operaiile de
136

cutare se fac ntr-o list mai lung. Acest dezavantaj se poate elimina folosind o structur special numit tabel hash. n unele cazuri se poate folosi un arbore binar. 3.5.2. Probleme rezolvate R.3.5.1. [Problema discret a rucsacului] Se d un rucsac de capacitate M i un numr de n obiecte, specificndu-se masele obiectelor i profiturile ce se obin prin transportul lor cu rucsacul. Se cere un program care s determine obiectele alese astfel nct s se obin un profit maxim. Soluia se va da sub forma unui vector definit astfel: xk=0 dac obiectul k nu este luat n rucsac, xp = 1 dac obiectul p este luat n rucsac. Rezolvare: n rezolvarea acestei probleme nu vom folosi dou liste ci un arbore binar. Algoritmul face, n prealabil, o ordonare descresctoare a obiectelor dup raportul profit/mas. Se pornete de la configuraia iniial n care nici obiect nu a fost nc ales. Se parcurge iterativ lista de obiecte. La fiecare iteraie se decide includerea sau nu a obiectului curent n rucsac i se expandeaz configuraia curent n dou configuraii corespunztoare celor doi subarbori. Nodul corespunztor fiului drept se obine din nodul tat la care se adaug obiectul curent, iar cel corespunztor fiului stng se obine din nodul tat ns fr adugarea obiectului analizat. Analiza continu numai pe una din cele dou ramuri ale arborelui binar, iar opiunea pentru una din cele dou ramuri se face pe baza unei funcii H care estimeaz profitul. program RucsacBB; uses crt; const max = 25; type TObiect = record masa, profit:integer; nr:integer end; PNod= ^Nod; Nod = record nivel,luat:integer; p_estimat,profit,masa:integer; tata,drept,stang:PNod; end; var n: integer; obiect: array[1..max] of TObiect; G, profitmax,masatotala:integer; solutie:array[1..max] of 0..1;
137

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

var i:integer; begin {main} write('Capacitatea rucsacului = '); readln(G); write('Numarul obiectelor = '); readln(n); for i:= 1 to n do begin write('Masa[',i ,'] = '); readln(obiect[i].masa); write('Profitul[',i ,'] = '); readln(obiect[i].profit); obiect[i].nr := i; end; Sort; Branch; writeln('Solutie:'); for i:= 1 to n do if solutie[i]=1 then write(obiect[i].nr,' '); writeln; writeln('Profitul obtinut = ', profitmax); writeln('Masa totala = ', masatotala); readln; end. R3.5.2. [Jocul Perspico] Se consider o tabl cu 4 x 4 csue, fiecare csu conine un numr ntre 1 si 15 si o csut conine zero (este liber). tiind c 0 i poate schimba poziia cu orice numr natural aflat deasupra, la dreapta, la stnga sau jos, n raport cu pozii n care se afl numrul 0, se cere s se precizeze irul de mutri prin care se poate ajunge de la o configuraie iniial dat la o configuraie final. Se cere de asemenea ca acest sir s fie optim, n sensul c trebuie s se ajung la configuraia final ntr-un numr minim de mutri. Rezolvare: #include<stdio.h> #include<stdlib.h> #include<conio.h> #define MAX 4 #define maxop 4
139

end;

profitmax := nodc^.profit; masatotala := nodc^.masa; while nodc^.tata<>nil do begin solutie[nodc^.nivel]:=nodc^.luat; nodc:=nodc^.tata; end

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

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

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

3.5.3. Probleme propuse 1. [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. [Diamante] Se d o tabl sub form de cruce pe care sunt aejate 32 de piese de diamant () aa cum se poate observa n figura de mai jos. Poziia din centru este liber. O pies se poate muta doar srind peste o alt pies ntr-un loc liber, numai pe orizontal sau pe vertical iar piesa peste care se sare trebuie luat. Se cere s se gaseasc un ir de mutri astfel nct (s lum ct mai multe piese de diamant) pornind de la configuraia iniial s se ajung la o configuraie final care s conin numai o singur pies i aceasta s se afle n centru.

Configuraia iniial

Configuraia final

3. [Operaii] Se d un tablou mn (1 m+n 15) cu elemente numere ntregi. Se numete "operaie" n acest tablou nmulirea unei linii sau coloane cu -1. S se determine cea mai mic secven de operaii care aduce tabloul la o form n care toate sumele de linii sau coloane dau numere nenegative. 4. [Buldozerul] Un teren de form dreptunghiular de dimensiuni mn este mprit n ptrate de dimensiuni egale (ca la ah). Unele ptrate conin grmezi de pamnt iar altele sunt netede. Un buldozer plasat ntr-un ptrat neted trebuie s niveleze tot terenul. S se gseasc un loc de unde poate porni buldozerul i ordinea de nivelare a ptratelor (n cazul n care exist o soluie) tiind c acesta: se deplaseaz doar pe direciile N, S, E, V; nu se poate deplasa peste un loc neted;
143

trece dintr-un loc neted peste ptratul cu pmnt de lng el n alt ptrat neted netezind astfel ptratul peste care a trecut. 5. [Obstacole i cai] Pe o tabl de ah n n se gsesc p cai i k obstacole amplasate ntr-o configuraie iniial dat. Mutarea calului este cea cunoscut de la ah. Calul poate sri peste un obstacol sau peste un alt cal, dar nu poate staiona pe o poziie ocupat de un cal sau de un obstacol. S se determine, dac exist, un ir de mutri ale cailor astfel nct s se ajung la o configuraie final dat. 6. [Inele] Fie dou inele n care sunt aezate echidistant 13 bile. Inelele au dou bile n comun. Deci n total vor fi 24 de bile din care 11 negre, 11 roii i dou gri (ca n figura de mai jos). Fiecare inel se poate roti n sensul acelor de ceasornic cel puin o poziie i cel mult 12, antrennd cu el cele 13 bile din interiorul su. Problema const n a aduce o configuraie iniial dat, la configuraia (final) din figura urmtoare printr-un numr minim de rotiri. 7. [Joc] Se d o tabl de joc cu 31 de ptrate care conine opt piese de O i opt piese de X ca n figura de mai jos. O pies poate fi mutat numai pe orizontal i pe vertical ntrun loc liber nvecinat, sau prin sritur peste o alt pies alturat dac se ajunge ntr-un loc liber. Jocul const n a schimba ntre ele locurile ocupate de piesele 'O i 'X' ntr-un numr minim de mutri. 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

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

TEHNICI AVANSATE DE PROGRAMARE Exemple de subiecte colectia 2008

1.
a. q, r, p b. p, q, r c. r, q, p d. p, q, r

2.
a. Q, R, P b. R, Q, P c. P, R, Q d. P, Q, R

3.
a. b. c. d.

Q P P Q

-> -> -> ->

urm urm urm urm

-> == -> ==

urm == P Q urm == Q P -> urm -> urm

4.
a. b. c. d.

P P Q Q

-> -> -> ->

urm urm urm urm

-> -> -> ->

urm urm urm urm

== == -> ==

Q -> urm Q urm == P -> urm P -> urm

5.
a. b. c. d.

P Q Q P

-> -> -> ->

URM URM URM URM

= Q = P -> URM = P -> URM = Q

6.
a. c.

b.

d.

7. 8. 9.

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. Stiind ca variabila p contine adresa primului element din lista si variabila t este de acelasi tip cu variabila p, stabiliti care dintre urmatoarele secvente elibereaza intreaga zona de memorie ocupata de elementele listei. a. while(p) {t = p; p = p->urm; free(p);} b. while(p) {t = p; p = p->urm; free(t);} c. while(p) {t=p; t=t->urm; free(t);} d. free(p);

Intr-o lista liniara simplu inlantuita, fiecare element retine in campul urm adresa urmatorului nod din

lista, iar in campul inf un numar intreg. Adresa primului element al listei este retinuta in variabila p. Daca in lista sunt memorate, in aceasta ordine, numerele: 5, 9, 3, si 6 (6 fiind ultimul element), in urma executarii secventei de instructiuni (p indica, initial, nodul cu numarul 5): { q = p -> urm -> urm; p->urm -> urm = q -> urm; q->urm = p -> urm; p -> urm = q;} in lista vor fi in ordine numerele: a. 9, 5, 3, 6 b. 5, 9, 6, 3 c. 5, 3, 6, 9 d. 5, 3, 9, 6

O lista liniara simplu inlantuita formata dintr-un numar impar de cel putin 5 noduri are adresa

primului nod memorata in variabila prim. In campul urm al fiecarui nod al listei se memoreaza adresa urmatorului element din lista. Adresa carui nod va fi memorata in variabila p, dupa executarea secventei de program: {p = prim; q = prim; while(q->urm) { q = q -> urm -> urm; p = p -> urm; } } a. penultimul nod al listei

b. nodul aflat in mijlocul listei c. ultimul nod al listei d. nodul al treilea din lista

10.

Intr-o lista simplu inlantuita, alocata dinamic, fiecare element retine in campul next adresa

urmatorului nod din lista, iar in campul info un numar intreg. Adresa primului element al listei este memorata in variabila prim. Se stie ca lista are cel putin 3 noduri. Care dintre urmatoarele secvente de instructiuni elimina corect penultimul element al listei? a. { p = prim; do p = p->next; while(p->next->next->next); p->next=p->next->next; } b. { p = prim; while (p->next->next->next) p = p->next; p->next=p->next->next; } c. { p = prim; while (p->next->next) p = p->next; p->next=p->next->next; } d. prim -> next = prim->next -> next;

11.
a. b. c. d.

Intr-o lista liniara, simplu inlantuita, alocata dinamic, fiecare element retine in campul next

adresa urmatorului nod din lista, iar in campul info in numar intreg. Adresa primului element al listei este memorata in variabila prim. Lista contine cel putin 3 noduri. Care este efectul executarii urmatoarei secvente de program { p = prim; q = p->next -> next; while ( q-> next) {p = p->next; q = q-> next;} p -> next = q; } Eliminarea nodului din mijlocul listei Eliminarea din lista a ultimului nod; Eliminarea din lista a penultimului nod Eliminarea celui de-al doilea nod al listei

12 13

Fiecare element al unei liste liniare simplu inlantuite alocata dinamic retine in campul adru

adresa elementului urmator din lista. Daca p retine adresa primului element, iar lista are cel putin doua elemente, care dintre urmatoarele secvente dee instructiuni sterge al doilea element al listei? a. q = p->adru; p->adru = q -> adru; free(q); b. p -> adru = p->adru -> adru; free (p->adru); c. q = p-> adru; free(q); p ->adru = q->adru; d. free(p->adru);

O lista liniara simplu inlantuita alocata dinamic, in care fiecare element memoreaza in

campul nr un numar intreg, iar in campul urm adresa elementului urmator din lista, contine exact trei elemente ale caror adrese sunt memorate in variabilele p, q si r. Stiind ca q -> nr == 3, p -> nr == 5, r -> nr == 8, q -> urm != NULL, p -> urm == NULL si r -> urm == q, care este ordinea numerelor din lista? a. 8, 3, 5 b. 5, 8, 3 c. 3, 8, 5 d. 5, 3, 8

14.

Intr-o lista circulara simplu inlantuita alocata dinamic cu cel putin un element, fiecare

element retine in campul nr un numar intreg si in campul urm adresa urmatorului element din lista. Stiind ca variabila p retine adresa unui element din lista si variabila t este de acelasi tip cu p, stabiliti care dintre urmatoarele secvente afiseaza toate valorile memorate in nodurile listei, fiecare valoare fiind afisata exact odata. a. t = p; while(t -> urm != p) { printf(%d , t -> nr; t = t->urm;} b. t = p; do{ printf(%d , t -> nr;} t = t->urm; }while(t != p); c. t = p; while(t != p) { printf(%d , t -> nr; t = t->urm;} d. t = p->urm; do{ printf(%d , t -> nr;} t = t->urm; }while(t != p);

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?

a. 5 b. 3

c. 2 d. 4

26

Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar

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

27

Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar

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

28

Se considera lista dublu inlantuita cu noduri care contin in campul inf (ce retine un n umar

natural), in aceasta ordine, numerele: 9, 7, 8, 3, 2, 4. In campurile st si dr sunt retinute adresa nodului precedent, respectiv adresa nodului urmator din lista.Variabilele globale p si sf retin adresele primului si respectiv ultimului element din lista. O variabila ce retine adresa unui element este de tip nod. Care va fi continutul listei la o parcurgere de la st la dr dupa apelul functiei sub(), unde, functia sub este: void sub(){ nod *man = sf; while(man->inf > sf -> inf ) man = man ->st; nod *q = man; man -> st -> dr = q -> dr; q -> dr -> st = man -> st; free(q); } a. 9, 7, 3, 2, 4 c. 9, 7, 8, 3, 2 b. 9, 7, 8, 2, 4 d. 9, 8, 3, 2, 7

29 30 31

Intr-o lista simplu inlantuita circulara, fiecare element retine in campul adr adresa

elementului urmator din lista. Daca p si q sunt adresele a doua elemente distincte din lista astfel incat sunt satisfacute conditiile p == q -> adr si q == p -> adr. Atunci lista are a. un numar impar de elemente c. cel putin 3 elemente b. exact 2 elemente d. exact 1 element

Se considera o stiva implementata prin intermediul vectorului a cu elementele a[0] = 0, a[1]

= 10, a[2] = 20, a[3] = 30, a[4] = 40, a[5] = 50. Daca cel de-al doilea element, incepand de la baza stivei este 10, atunci primul element care iese din stiva este: a. a[6] c. a[5] b. a[1] d. a[0]

Intr-o lista circulara simplu inlantuita, cu cel putin un element, fiecare nod retine in campul

adr adresa elementului urmator din lista. Daca p este o variabila care retine adresa primului element din lista, iar q este o variabila care poate sa retina adresa unui element din lista, care dintre urmatoarele secvente de instructiuni calculeaza in variabila nr, de tip int, numarul de elemente al listei? a. nr = 0; q = p; while(q != p) {nr++; q = q -> adr;} b. nr = 0; q = p; do {nr ++; q = q -> adr;} while (q != p);

c. nr = 0; q = p; do {nr ++; q = p -> adr;} while (q != p); d. nr = 0; q = p; while (p != q){ nr ++; p = p -> adr;}

32 33
a. b. c. d.

Intr-o lista circulara simplu inlantuita fiecare element retine in campul adr adresa

elementului urmator din lista. 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. a. p -> adr == p c. p -> adr -> adr == p b. p -> adr -> adr == NULL d. p -> adr != NULL

Se considera urmatoarea functie recursiva apelata numai pentru numere naturale nenule:

int f(int a, int b){ if (a<b) return a; else return f(a-b, b); } Care dintre urmatoarele functii este echivalenta cu functia data? int f(int a, int b){return a*b;} int f(int a, int b){return a-b+1;} int f(int a, int b){return a%b;} int f(int a, int b){return a/b;}

34 35

Se considera definitia

void f(int n){ int j; if (n>0) for (j=1; j<=n; j++) {printf(%d,j); f(n-1);} } Ce se afiseaza ca urmare a apelului f(2)? a. 1122 c. 121 b. 112 d. 1121

Se considera definitia:

long f(int n){ if (n == 0) return 1; else if (n == 1) return 4;

else return f(n-1) - f(n-2); } Stabiliti ce valoasre returneaza apelul f(7).

a. 1 b. -3

c. -4 d. 4

36.
a. 3 b. 1

Se considera definitia

long f(int n, int k){ if (n == k || k == 1) return 1; if (n < k) return 0; long s=0, i; for (i=1; i<=k; i++) s+=f(n-k,i); return s; } Stabiliti ce valoare returneaza apelul f(6,3). c. 2 d. 4

37
a. 50 b. 45

Se considera definitia:

long f(int x, int y){ if (x == y || x == 0) return 1; else return f(x,y-1)+f(x-1,y-1); } Ce valoare returneaza apelul f(8,10)?

c. 40 d. 55

38

In functia recursiva de mai jos se considera ca tabloul unidimensional v este declarat global.

void star(int i){ if(i<10) { printf(*); if (v[i] == i+1) star(i+2); else star(i+1); } } Pentru care dintre declaratiile urmatoare, apelul star(0) produce 7 asteriscuri (stelute)?

a. b. c. d.

int v[] = {1, 4, 3, 2, 1, 6, 5, 4, 3, 10}; int v[] = {3, 2, 1, 4, 3, 6, 7, 2, 9, 2}; int v[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int v[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

39 40 41
a. 012 b. 120

Pentru o valoare naturala mai mare decat 1 memorata in variabila globala n, subprogramul

urmator afiseaza cel mai mare divizor al lui n, mai mic decat n, la apelul divi(n). void divi(long i){ if ( ... == 0) printf(%ld, ...); else divi(i-1); } Cu ce expresii trebuie completate punctele de suspensie? a. n % i si i c. n%(i-1)=0 si i b. n% (i-1) si i-1 d. n%i si i-1

Stiind ca p este un vector (tablou unidimensional) cu 3 componente intregi (tabloul este

declarat global), M este multimea tuturor cifrelor nenule, iar functia tipar afiseaza valorile elementelot p[0], p[1] si p[2], cu ce trebuie inlocuite simbolurile a, 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; for (i = a; i<=b; i++) { p[k] = i; if (k == c) tipar(); else G(k+1);} } a. a = 0, b = 10, c = 3 c. a = 1, b = 9, c = 3 b. a = 1, b = 3, c = 9 d. a = 1, b = 9, c = 2

Pentru definitia alaturata a functiei ex(), stabiliti ce se afiseaza la apelul ex(120)?

void ex(int x){ if (x != 0){ printf(%d, x %10); ex(x/10); } }


c. 021 d. 21

42.
a. 230 b. 220

Gasiti elementul f(20) din sirul definit prin relatia (f(n))2 = 8(f(n-1))2, unde f(0) = 2 c. 219 d. 231

43
b.

Se considera relatia de recurenbta neomogena de ordinul intai f(n) - f(n-1) = 9n2, f(0) = 8,

n>0; Atunci f(n) = a.

c. d.

44
a. b.

Se considera relatia de recurenta f(n) - 7f(n-1) = 9(5n), n > 0; f(0) = 3. Atunci f(n) = c. d.

45 46

Solutia f(n) a relatiei de recurenta f(n) - 7f(n-1) = 9(7n), n>0, f(0) = 3, este c. (9n+9)7n d. (3n+3)7n

a. (9n+3)7n b. (3n+9)7n

Solutia relatiei de recurenta f(n) = 6 f(n-1) - 9 f(n-2), n0, f(0) = 1, f(1) = 2 este f(n) = c. 3n+1-n3n d. 3n+1-n3n-1

a. 3n-n3n-1 b. 3n-1-n3n

47
a. b.

Solutia relatiei de recurenta f(n) = 2f(n-1) - 4f(n-2), n>1, f(0)=1, f(1) = 3 este f(n) = c. d.

48 49 50

Un algoritm de tip backtracking genereaza in ordine lexicografica, toate sirurile de 5 cifre 0

si 1 cu proprietatea ca nu exista mai mult de doua cifre de 0 consecutive. Primele sase solutii generate sunt: 00100, 00101, 00110, 01001, 01010. Care este cea de-a opta solutie? a. 01110 c. 01011 b. 01100 d. 01101

Un algoritm backtracking genereaza toate sirurile alcatuite din cate 5 cifre binare (0 si 1).

Numarul tuturor solutiilor generate va fi egal cu : a. 5 c. 10 b. 32 d. 31

Aplicand metoda backtracking pentru a genera toate permutarile celor n elemente ale unei

multimi, o solutie se memoreaza sub forma unui tablou unidimensional x1, x2, ..., xn. Daca sunt deja generate valori pentru componentele x1, x2, ..., xk-1, iar pentru componenta xk (1 <k<n)au fost testate toate valorile posibile si nu a fost gasita niciuna convenabila, atunci: a. se incearca alegerea unei noi valori pentru componenta xk-1. b. se incearca alegerea unei noi valori pentru componenta x1, oricare ar fi valoarea k. c. se incheie algoritmul. d. se incearca alegerea unei valori pentru componenta xk+1.

51 52 53 54

Daca se utilizeaza metoda backtracking pentru a genera toate numerele naturale, in ordine

strict crescatoare, formate din 4 cifre pare distincte, care dintre numerele de mai jos trebuie, eliminate astfel incat cele ramase sa reprezinte o succesiune de numere corect generate? 1) 2068; 2) 2084; 3) 2088; 4) 2468; 5) 2086; 6) 2406 a. numai 3) b. atat 3) cat si 5) c. atat 3) cat si 4) d. numai 4)

Se considera multimea {1, 7, 5, 16, 12}. Se genereaza prin metoda backtracking toate

submultimile sale formate din exact 3 elemente: primele patru solutii generate sunt, in ordine: {1, 7, 5}, {1, 7, 16}, {1, 7, 12}. Care dintre solutii trebuie eliminate din sirul urmator astfel incat cele ramase sa apara in sir in ordinea generarii lor: {1, 16, 12}, {5, 16, 12}, {7, 5, 16}, {7, 5, 12} a. {1, 16, 12} b. {5, 16, 12} c. {7, 5, 16} d. {7, 5, 12}

Se considera algoritmul care genereaza in ordine strict crescatoare toate numerele formate cu

5 cifre distincte alese din multimea {1, 0, 5, 7, 9} in care cifra din mijloc este 0.Selectati numarul care precede si numarul care urmeaza secventei de numere generate: 19075; 51079; 51097 a. 19057, 57019 b. 15079, 71059 c. 19057, 59071 d. 15097, 71095

Daca pentru generarea tuturor submultimilor unei multimi A = {1, 2, ..., n} cu 1 n 10, se

utilizeaza un algoritm backtracking astfel incat se afiseaza in ordine, pentru n=3, submultimile {}, {1}, {2}, {3}, {1, 2}, {1,3}, {2,3}, {1, 2, 3}, atunci, utilizand exact acelasi algoritm pentr n = 4, in sirul submultimilor generate, solutia a 7-a va fi: a. {1,3} b. {4}

c. {1,2,3} d. {1,4}

55 56 57 58

Produsul cartezia {1,2,3}x{2,3} este obtinut cu ajutorul unui algoritm backtracking care

genereaza perechile (1,2), (1,3), (2,2), (2,3), (3,2) si (3,3). Care este numarul perechilor obtinute prin utilizarea aceluiasi algoritm la generarea produsului cartezian {1, 2, 3, 4}x{2, 3, 4}? a. 12 c. 81 b. 10 d. 6

Se genereaza toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu

4, avand primul termen 1 sau 2, ultimul termen 4 si cu diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2, obtinandu-se solutiile (1, 2, 3,4), (1, 2, 4), (1, 3, 4), (2, 3, 4), (2, 4). Folosind aceeasi metoda generam toate sirurile strict crescatoare de numere naturale nenule mai mic sau egale cu 6, avand primul termen 1 sau 2, ultimul termen 6 si diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2, care dintre afirmatiile urmatoare este adevarata: a. imediat dupa solutia (1, 3, 4, 5, 6) se genereaza solutia (2, 3, 4, 5, 6) b. penultima solutie generata este (2, 3, 5, 6) c. imediat dupa solutia (1, 2, 4, 6) se genereaza solutia (1, 3, 4, 6) d. in total sunt generate 13 solutii.

Avand la dispozitie cifrele 0, 1 si 2 putem genera, in ordine crescatoare, numerele care au

suma cifrelor egala cu 2 astfel: 2, 11, 20, 101, 110, 200, etc. Folosind acest algoritm generati numerele cu cifrele 0, 1 si 2 care au suma cifrelor egala cu 3. Care va fi al saptelea numar din aceasta generare? a. 120 b. 1002 c. 201 d. 210

Generarea tuturor cuvintelor de 4 litere, fiecare litera putand fi orice element din multimea

{a, c, e, m, v, s}, se realizeaza cu ajutorul unui algoritm echivalent cu algoritmul de generare a: a. produsului cartezian c. partitiilor unei multimi b. combinarilor d. permutarilor

59 60 61 62

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, unde s si k sunt numere naturale nenule. Astfel pentru valorile k = 2 si s = 6 se genereaza numerele: 15, 24, 33, 42, 51, 60. Care vor fi primele 4 numere ce se vor genera pentru k = 3 si s=8? a. 800, 710, 620, 530 c. 125, 233, 341, 431 b. 107, 116, 125, 134 d. 116, 125, 134, 143

Se considera multimile A = {1, 2, 3}, B = {1}, C = {2, 3, 4}. Elementele produsului

cartezian AxBxC se genereaza, in ordine astfel: (1, 1, 2), (1, 1, 3), (1, 1, 4), (2, 1, 2), (2, 1, 3), (2, 1, 4), (3, 1, 2), (3, 1, 3), (3, 1, 4). Daca prin acelasi algoritm se genereaza produsul cartezian al multimilor AxBxC, unde A = {a}, B ={a, b}, C = {b, c, d}, atunci cel de-al patrulea element generat este: a. (a, b, c) b. (a, c, b) c. (a, b, b) d. (a, c, d)

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, in ordine, toate solutiile 1+2+5, 1+3+4, 1+7, 2+6, 3+5. Aplicand exact acelasi procedeu, se determina solutiile pentru scrierea numarului 10. Cate solutii de forma 1+ ... exista? a. 3 c. 5 b. 4 d. 6

Se considera multimile A = {1, 2, 3}, B = {1}, C = {2, 3, 4}. Elementele produsului

cartezian AxBxC se genereaza, folosind metoda backtracking, in ordinea (1, 1, 2), (1, 1, 3), (1, 1, 4), (2, 1, 2), (2, 1, 3), (2, 1, 4), (3, 1, 2), (3, 1, 3), (3, 1, 4). Daca prin acelasi algoritm se genereaza produsul cartezian al multimilor AxBxC unde A = {x, y}, B = {x}, c = {x, y, z}, atunci cel de-al treilea element generat este: a. (x, x, y) c. (x, x, z) b. (x, y, x) d. (x, y, z)

63 64 65 66

Generarea tuturor sirurilor formate din trei elemente, fiecare element putand fi oricare numar

din multimea {1, 2, 3}, se realizeaza cu ajutorul unui algoritm echivalent cu algoritmul de generare a: a. permutarilor c. produsului cartezian b. combinarilor d. aranjamentelor

In utilizarea metodei backtracking pentru a genera toate cuvintele alcatuite din doua litere

ale multimii {a, c, e, q}, astfel incat sa nu existe doua consoane alaturate, cuvintele se genereaza in urmatoarea ordine: aa, ac, ae, aq, ca, ce, ea, ec, ee, eq, qa, qe. Daca se utilizeaza exact aceeasi metoda pentru a genera cuvinte formate din 4 litere ale multimii {a, b, c, d, e, f}, astfel incat sa nu existe doua consoane alaturate in cuvant, care este penultimul cuvant generat? a. fefa c. feef b. fafe d. fefe

Utilizand metoda backtracking se genereaza toate numerele formate doar din trei cifre astfel

incat fiecare numar sa aiba cifrele distincte. Cifrele fiecarui numar sunt din multimea {12, 2, 3, 4}. acest algoritm genereaza numerele, in aceasta ordine: 123, 124, 132, 134, 213, 214, 231, 234, 312, 314, 321, 324, 412, b413, 421, 423, 431, 432. Daca utilizam acelasi algoritm pentru a genera toate numerele de 4 cifre, fiecare numar fiind format din cifre distincte din multimea {1, 2, 3, 4, 5}, precizati care este numarul generat imedia dupa 4325. a. 4351 c. 4521 b. 5123 d. 4321

Utilizand metoda backtracking se genereaza toate numerele palindrom formate din 4 cifre.

Fiecare numar contine cifre din multimea {1, 3, 5}. Elementele sunt generate in urmatoarea ordine: 111, 1331, 1551, 3113, 3333, 3553, 5115, 5335, 5555. Daca se utilizeaza exact aceeasi metoda pentru a genera toate numerele palindrom formate din 4 cifre, fiecare element avand cifre din multimea {1, 2, 3, 4, 5, 6, 7, 8, 9}. Sa se precizeze cate numere pare se vor genera. a. 99 c. 36 b. 40 d. 72

67 68 69 70

Utilizand metoda backtracking se genereaza elementele produsului cartezian a n multimi A1,

A2, ..., An. Daca utilizam acest algoritm pentru a genera elementele produsului cartezian a 3 multimi: M = {1, 2, 3}, N = {1, 2} si P = {1, 2, 3, 4} atunci care din urmatoarele secvente nu reprezinta o solutie acestui algoritm, pentru produsul cartezian PxNxM? a. (4, 2, 3) c. (3, 2, 1) b. (3, 3, 3) d. (1, 1, 1)

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. Precizati care dintre urmatoarele numere reprezinta o solutie a algoritmului? a. 235 c. 281 b. 986 d. 455

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. fiecare solutie se exprima sub forma unui vector c = (c1, c2, ..., c8) unde c1 reprezinta coloana pe care se afla dama de pe linia i. Stiind ca primele doua solutii generate sunt (1, 5, 8, 6, 3, 7, 2, 4), (1, 6, 8, 3, 7, 4, 2, 5) sa se determine solutia generata de algoritm imediat dupa solutia (8, 2, 4, 1, 7, 5, 3, 6). a. (8, 1, 2, 3, 4, 5, 6, 7) c. (8, 2, 5, 3, 1, 7, 4, 6) b. (8, 4, 2, 7, 6, 1, 3, 5) d. (7, 4, 2, 5, 8, 1, 3, 6)

Se genereaza toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu

4, avand primul termen 1 sau 2, ultimul termen 4 si cu diferenta dintre oricare doi termeni aflati pe pozitii consecutive cel mult 2, obtinandu-se solutiile (1, 2, 3, 4), (1, 2, 4), (1, 3, 4), (2, 3, 4), (2, 4). Folosind aceeasi metoda, generam toate sirurile strict crescatoare de numere naturale nenule mai mici sau egale cu 5, care dintre afirmatiile urmatoare este adevarata: a. imediat dupa solutia (1, 3, 5) se genereaza solutia (2, 3, 4, 5). b. imediat dupa solutia (2, 3, 5) se genereaza solutia (2, 5). c. penultima solutie generata este (2, 4, 5). d. in total sunt generate 5 solutii.

71 72 73 74

Se genereaza in ordine crescatoare numerele de cate sase cifre care contin cifra 1 o singura

data, cifra 2 de cate doua ori si cifra 3 de trei ori. Se obtin, in aceasta ordine, numerele 122333, 123233, 123323, ...,333221. care din urmatoarele propozitii este adevarata? a. Imediat dupa numarul 332312 se genereaza 332321 b. Sunt 8 numere generate prin aceasta metoda care au prima cifra 1 si ultima cifra 2. c. Sunt 6 numere generate prin aceasta metoda care au prima cifra si a doua cifra 2. d. Penultimul numar generat este 333122.

Utilizand metoda backtracking se genereaza in ordine lexicografica toate anagramele

cuvantului caiet. Stiind ca primele 2 solutii sunt aceit si aceti, care este cuvantul generat inaintea cuvantului tiaec? a. teica c. ticae b. tieac d. tiace

O singura statie de servire (procesor, pompa de benzina etc) trebuie sa satisfaca cererile a n

clienti. Timpul de servire necesar fiecarui client este cunoscut in prealabil: pentru clientul i este necesar un timp ti, 1 i n. Daca dorim sa minimizam timpul total de asteptare atunci a. selectam intotdeauna clientul cu timpul maxim de servire din multimea de clienti ramasa b. selectam intotdeauna clientul cu timpul minim de servire din multimea de clienti ramasa

Se considera graful ponderat din imaginea alaturata.

Ordinea de selectare a muchiilor in vederea obtinerii unui arbore partial de cost minim, prin utilizarea strategiei Greedy de tip Kruskal, este: a. (1, 2), (2, 3), (4, 5), (6, 7), (1, 4), (4, 7) b. (1, 2), (2, 3), (6, 7), (4, 5), (2, 5), (1, 4) c. (5, 6), (5, 7), (3, 6), (2, 4), (3, 5), (1, 4)

75

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. Stiind ca i s-au propus 8 spectacole si pentru fiecare spectacol i-a fost anuntat intervalul in care se va desfasura: 1: [10, 15) 2: [2, 4) 3: [7, 9) 4: [21, 25) 5: [10, 12) 6: [12, 15) 7: [7, 8) 8: [20, 27) Care spectacole trebuie selectate pentru a permite spectatorilor sa vizioneze un numar cat mai mare de spectacole? a. 2, 3, 5, 6, 8 b. 1, 8 c. 2, 4, 5, 6, 7 d. 2, 3, 1, 8

76 77

Se considera ca trebuie transportate cu ajutorul unui rucsac de capacitate 10kg, obiecte cu

greutatile 8kg, 6kg si 4kg. Pentru fiecare kg transportat castigul obtinut este 1 LEU. Stiind ca obiectele se incarca integral in sac si ca se poate alege cel mult un obiect din fiecare tip, atunci solutia optima este (se noteaza prin 1 - selectarea obiectului, iar prin 0 - neselectarea acestuia): a. (1, 0, 0) c. (1, 1, 1) b. (0, 1, 1) d. (1, 1, 0)

Se doreste planificarea optimala (penalizarea totala sa fie minima) a 7 lucrari, 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. Se presupune ca pentru executarea unei lucrari este necesara o unitate de timp si ca nu se pot executa doua lucrari in acelasi timp. Se considera datele de intrare: i t[i] p[i] 1 4 50 2 3 40 3 2 60 4 3 20

5 4 70 6 2 10 7 1 130 Care este penalizarea totala minima ce se poate obtine? a. 10 b. 130 c. 20 d. 70

78 79 80 81

Fie tabloul unidimensional a in care elementele sunt, in ordine 1, 3, 5, 7, 10, 16, 21. Pentru a

verifica daca numarul x = 4 se afla printre elementele tabloului, se aplica metoda cautarii binare. Care este succesiunea corecta de elemente cu care se compara x? a. 1, 3, 5 b. 7, 5, 3 c. 7, 3, 5 d. 21, 16, 10, 7, 5, 3

Se considera doua tablouri unidimensionale A si B: A = (1, 3, 5, 9, 10), respectiv B = (2, 4,

6, 7). In urma interclasarii lor in ordine crescatoare se obtine tabloul cu elementele: a. (1, 2, 3, 4, 5, 6, 9, 7, 10) c. Nu se poate realiza interclasarea b. (1, 2, 3, 4, 5, 6, 7, 9, 10) d. (1, 3, 5, 9, 10, 2, 4, 6, 7)

Pentru cautarea unei valori intre elementele unui tablou ordonat descrescator vom utiliza

utiliza un algoritm eficient de tip: a. interclasare b. quicksort

c. cautare binara d. backtracking

Fie secventele de numere:

i) 1, 4, 6, 8, 9 ii) 8, 5, 4, 3, 2, 1 iii) 2, 3, 8, 5, 9 Algoritmul de cautare binara se poate aplica direct, fara alte prelucrari prealabile a. numai secventei i) c. numai secventei ii) b. numai secventei iii) d. atat secventei i) cat si secventei ii)

82 83
a. b. c. d. e.

Se considera metoda sortarii prin interclasare a n siruri de caractere in ordine lexicografica

crescatoare. Presupunand ca procesul de divizare se bazeaza pe metoda injumatatirii la fiecare pas, atunci timpul cerut de algoritm este: a. O(n) c. O(n log2n) b. O(n2) d. O(n ln n)

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 considera algoritmul cautarii binare si 2k-1 n 2k. In cazul unei cautari cu succes se fac c. cel mult k comparatii d. n comparatii

a. k-1 comparatii b. exact k comparatii

Fie S(n) numarul de comparatii necesar sortarii a n siruri de caractere prin metoda insertiei

binare, Atunci S(n) este a.

c. d.

86

Se presupune ca n siruri de caractere sunt sortate prin metoda sortarii rapide (quicksort).

Notam prin T(n) numarul mediu de comparatii pentru ordonarea lexicografica crescatoare a celor n siruri. Atunci T(n) =

a. O(n) b. O(n2)

c. O(n ln n) d. O(n log2n)

87 88 89

Se considera functia C din biblioteca standard:

void * bsearch(const void *x, const void *s, size_t dim, size_t n, int (*f)(const void *, const void *)); Atunci: a. f este functie de comparare definita de c. s este adresa elementului ce va fi cautat utilizator b. x este tabloul in care se cauta d. n este numarul de componente ale sirului in care se face cautarea

Se considera arborele binar a carui reprezentare standard (ST[i] - descendent stang, DR[i] -

descendent drept) este ST = (2, 3, 4, 0, 6, 0, 0, 0, 0) si DR = (8, 5, 0, 0, 7, 0, 0, 9, 0), unde prin 0 s-a notat lipsa descendentului corespunzator. Atunci prin parcurgerea in inordine, nodurile arborelui sunt vizitate astfel: a. 1, 2, 3, 4, 5, 6, 7, 8, 9 c. 4, 3, 2, 6, 5, 7, 1, 8, 9 b. 1, 2, 8, 3, 5, 9, 4, 6, 7 d. 4, 3, 6, 7, 5, 2, 9, 8, 1

Metoda Divide et impera, cu divizare binara, pentru rezolvarea unei probleme relativ la

obiectele O1, O2, ..., On, se poarte reprezenta sub forma unui arbore binar. Daca fiecare secventa Op, Op+1, ...., Oq se reprezinta prin perechea (p, q), atunci varfurile terminale ale arborelui sunt etichetate cu: a. (1, n) b. (n+1, ) c. (p, q) cu q = p+1 d. (p, q) cu q-p , unde este dimensiunea subproblemei ce se poate rezolva direct.

Metoda backtracking (modele de subiecte)

1. [Cuvinte] Urmatorul enunt este comun pentru intrebarile i)- iv). Utiliznd metoda backtracking se genereaz n ordine lexicografic cuvintele de cte patru litere din mulimea A={a,b,c,d,e}, cuvinte care nu conin dou vocale alturate. Primele opt cuvinte generate sunt, n ordine: abab, abac, abad, abba, abbb, abbc, abbd, abbe. i) Cte dintre cuvintele generate ncep cu litera b i se termin cu litera e? a. 9 b. 15 c. 12 d. 20 ii) Care este ultimul cuvnt generat? a. edcb b. eeee c. edde d. eded iii) Care este penultimul cuvnt generat? a. edec b. eded c. edde d. edcb iv) Care este antepenultimul cuvnt generat? a. edde b. eddb c. edeb d. edcb v) Se genereaz, utiliznd metoda bactracking, cuvintele cu exact 3 litere din mulimea {a,x,c,f,g}. Dac primele patru cuvinte generate sunt, n ordine, aaa, aax, aac, aaf, scriei ultimele trei cuvinte care ncep cu litera a, n ordinea n care vor fi generate. vi) Se utilizeaz metoda backtracking pentru a genera toate cuvintele formate din dou litere distincte din muimea {w,x,z,y} astfel nct niciun cuvnt s nu nceap cu litera x i niciun cuvnt s nu conin litera w lng litera z. Cuvintele vor fi generate n ordinea wx, wy, zx, zy, yw, yx, yz. Folosind aceeai metod se genereaz toate cuvintele de dou litere distincte din mulimea {w,x,z,y,t} astfel nct niciun cuvnt s nu nceap cu litera x i niciun cuvnt s nu conin litera w lng litera z. Care este a treia i a patra soluie generat? 2. [Combinari] i) Folosind modelul combinrilor se genereaz numerele naturale cu cte trei cifre distincte din mulimea {1, 2, 3, 7}, numere cu cifrele n ordine strict cresctoare, obinndu-se, n ordine: 123, 127, 137, 237. Dac se utilizeaz exact aceeai tehnic pentru a genera numerele naturale cu patru cifre distincte din mulimea {1,2,3,4,5,6,7,8}, cte dintre numerele generate au prima cifr 2 i ultima cifr 7? a. 8 b. 3 c. 4 d. 6 ii) Utiliznd metoda backtracking se genereaz toate submuimile mulimii {3,6,2,5}. Primele ase submulimi generate sunt, n ordine: {3}, {3,6}, {3,6,2}, {3,6,2,5}, {3,6,5}, {3,2}. Care sunt, n ordinea obinerii, ultimele trei submulimi, generate dup aceast regul?

iii) Folosind modelul combinrilor se genereaz numerele naturale cu cte trei cifre distincte din mulimea {1,2,3,4}, numere cu cifrele n ordine strict cresctoare, obinndu-se, n ordine: 123, 124, 134, 234. Dac se utilizeaz exact aceeai tehnic pentru a genera numerele naturale cu cte patru cifre distincte din mulimea {1,2,3,4,5}, cte dintre numerele generate au prima cifr 1 i ultima cifr 5? a. 4 b. 2 c. 6 d. 3 3. [Numere cu trei cifre] i) Utiliznd metoda backtracking sunt generate numerele de 3 cifre, avnd toate cifrele distincte i cu proprietatea c cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele ase soluii generate sunt, n aceast ordine, 103, 105, 107, 109, 123, 125, care este a zecea soluie generat? a. 145 b. 147 c. 230 d. 149 ii) Utiliznd metoda backtracking sunt generate numerele de 3 cifre care au cifrele n ordine cresctoare, iar cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele cinci soluii generate sunt, n aceast ordine, 123, 125, 127, 129, 145, care este cel de al 8-lea numr generat? a. 169 b. 149 c. 167 d. 147 iii) Utiliznd metoda backtracking, sunt generate toate numerele de 3 cifre, astfel nct cifrele sunt n ordine cresctoare, iar cifrele aflate pe poziii consecutive sunt de paritate diferit. tiind c primele trei soluii generate sunt, n aceast ordine, 123, 125, 127, cte dintre toate numerele generate au suma cifrelor egal cu 6? iv) Utiliznd metoda backtracking se genereaz numerele formate din cte 3 cifre distincte din mulimea {1, 3, 5, 7}. Dac primele trei numere generate sunt, n acest ordine: 135, 137, 153 care este cel de-al patrulea numr generat? a. 157 b. 173 c. 315 d. 357 v) Folosind cifrele {1,2,3} se genereaz, n ordinea cresctoare a valorii, toate numerele pare formate din trei cifre distincte. Astfel, se obin n ordine, numerele: 132, 312. Folosind aceeai metod, se genereaz numerele pare formate din patru cifre distincte din mulimea {1,2,3,4}. Care va fi al 4-lea numr generat ? a. 2134 b. 1432 c. 2314 d. 1423 vi) Folosind cifrele {2,3,4} se genereaz, n ordinea cresctoare a valorii, toate numerele impare formate din trei cifre distincte. Astfel se obin, n ordine, numerele: 243, 423. Folosind aceeai metod, se genereaz numerele pare formate din patru cifre distincte din mulimea {2,3,4,5}. Care va fi al 5-lea numr generat? a. 3452 b. 3524 c. 2534 d. 3542 vii) Folosind cifrele {1,2,3} se genereaz, n ordinea cresctoare a valorii, toate numerele formate din exact trei cifre, n care cifrele alturate au valori consecutive. Astfel se obin n ordine, numerele: 121, 123, 212, 232, 321 i 323. Folosind aceeai metod se genereaz numere de patru cifre din mulimea {1, 2, 3, 4} care ndeplinesc aceeai condiie. Care va fi al 5-lea numr generat? a. 2121 b. 2123 c. 3121 d. 2323

viii) Folosind cifrele {2,3,4} se genereaz, n ordinea cresctoare a valorii, toate numerele pare formate din trei cifre distincte. Astfel se obin, n ordine, numerele: 234, 324, 342, 432. Folosind aceeai metod, se genereaz numerele impare formate din patru cifre distincte din mulimea {2,3,4,5}. Care va fi al 5-lea numr generat? a. 3425 b. 2543 c. 4235 d. 3245 ix) Folosind cifrele {1,2,3} se genereaz, n ordinea cresctoare a valorii, toate numerele impare formate din trei cifre distincte. Astfel se obin, n ordine, numerele: 123, 213, 231, 321. Folosind aceeai metod, se genereaz numerele impare formate din patru cifre distincte din mulimea {1, 2, 3, 4}. Care va fi al 5-lea numr generat ? a. 2413 b. 1423 c. 2431 d. 3241 4. [Numere de orice lungime] i) Folosind tehnica backtracking, in timpul pregatirii examenului, ati scris un program care genereaz toate numerele de cte n cifre (0<n9), cifrele fiind n ordine strict cresctoare. a) Dac n este egal cu 5, cte numere au fost generate de catre program? __________ b) Pentru n egal cu 5, cte dintre numerele generate au prima cifr 4? ___________ ii) Un algoritm genereaz n ordine cresctoare toate numerele de n cifre, folosind doar cifrele 3, 5 i 7. Dac pentru n=5, primele 5 soluii generate sunt 33333, 33335, 33337, 33353, 33355, precizai care sunt ultimele 3 soluii generate, n ordinea generrii. ____________________ iii) Un algoritm genereaz n ordine descresctoare toate numerele de 5 cifre, fiecare dintre ele avnd cifrele n ordine strict cresctoare. tiind c primele 5 soluii generate sunt 56789, 46789, 45789, 45689, 45679, precizai care sunt ultimele 3 soluii generate, n ordinea generrii. ______________________ iv) Un algoritm genereaz n ordine cresctoare, toate numerele de n cifre (n<9), cu cifre distincte, care nu au dou cifre pare alturate. Dac pentru n=5, primele 5 soluii generate sunt 10325, 10327, 10329, 10345, 10347, precizai care sunt urmtoarele 3 soluii generate, n ordinea obinerii lor. ______________________ v) Un algoritm genereaz n ordine descresctoare, toate numerele de n cifre (n<9), cu cifrele n ordine strict cresctoare, care nu au dou cifre pare alturate. Dac pentru n=5, primele 5 soluii generate sunt 56789, 45789, 45679, 45678, 36789, precizai care sunt urmtoarele 3 soluii generate, n ordinea obinerii lor. ______________ vi) Pentru generarea numerelor cu n cifre formate cu elementele mulimii {0, 2, 8} se utilizeaz un algoritm backtracking care, pentru n=2, genereaz, n ordine, numerele 20, 22, 28, 80, 82, 88. Dac n=4 i se utilizeaz acelai algoritm, precizai cte numere generate sunt divizibile cu 100? a. 601 b. 100 c. 6 d. 10 vii) Pentru generarea numerelor cu n cifre formate cu elementele mulimii {0, 4, 8} se utilizeaz un algoritm backtracking care, pentru n=2, genereaz, n ordine, numerele

40, 44, 48, 80, 84, 88. Dac n=4 i se utilizeaz acelai algoritm, care este numrul generat imediat dup numrul 4008 ? a. 4040 b. 4004 c. 4080 d. 8004 viii) Un program genereaz, n ordine cresctoare, numerele naturale de exact 5 cifre din mulimea {1, 2, 3, 4, 5}. Fiecare dintre numerele generate are cifrele distincte dou cte dou. Primele 3 numere astfel generate sunt: 12345, 12354, 12435. Care este numrul generat imediat dup 12543? a. 15342 b. 12534 c. 13245 d. 13452 ix) Se genereaz n ordine cresctoare, toate numerele naturale de 5 cifre distincte, care se pot forma cu cifrele 2,3,4,5 i 6. S se precizeze numrul generat imediat naintea i numrul generat imediat dup secvena urmtoare : 34256, 34265, 34526, 34562: a. 32645 i 34625 b. 32654 i 34655 c. 32654 i 34625 d. 32645 i 34655 x) Se genereaz n ordine cresctoare, toate numerele naturale de 5 cifre distincte, care se pot forma cu cifrele 5,6,7,8 i 9. S se precizeze numrul generat imediat naintea i numrul generat imediat dup secvena urmtoare : 67589,67598,67859,67895. a. 65987 i 67958 b. 65978 i 67988 c. 65978 i 67958 d. 65987 i 67988 xi) Se genereaz n ordine cresctoare toate numerele de exact 4 cifre care se pot forma cu elementele mulimii {0, 1, 2, 3, 4}. Primele 8 soluii generate sunt, n ordine: 1000, 1001, 1002, 1003, 1004, 1010, 1011, 1012. Care sunt primele trei numere ce se vor genera imediat dup numrul 3443? a. 4000, 4001, 4002 b. 3444, 4443, 4444 c. 3444, 4444, 4000 d. 3444, 4000, 4001 xii) Se genereaz n ordine cresctoare toate numerele de 4 cifre, cu cifre distincte, astfel nct diferena n valoare absolut dintre prima i ultima, respectiv a doua i a treia cifr este egal cu 2. Primele 11 soluii generate sunt, n ordine: 1023, 1203, 1243, 1423, 1463, 1573, 1643, 1683, 1753, 1793, 1863. Care dintre urmtoarele numere se va genera imediat naintea numrului 9317? a. 9247 b. 9357 c. 9207 d. 8976 xiii) Se genereaz n ordine cresctoare toate numerele de 4 cifre, cu cifre distincte, astfel nct diferena n valoare absolut dintre ultimele dou cifre ale fiecrui numr generat este egal cu 2. Primele opt soluii generate sunt, n ordine: 1024, 1035, 1042, 1046, 1053, 1057, 1064, 1068. Care dintre urmtoarele numere se va genera imediat dup numrul 8975? a. 8979 b. 9013 c. 8957 d. 9024

xiv) Avnd la dispoziie cifrele 0, 1 i 2 se pot genera, n ordine cresctoare, numere care au suma cifrelor egal cu 2. Astfel, primele 6 soluii sunt 2, 11, 20, 101, 110, 200. Folosind acelai algoritm, se genereaz numere cu cifrele 0, 1, 2 i 3 care au suma cifrelor egal cu 4. Care va fi al 7-lea numr din aceast generare? a. 130 b. 301 c. 220 d. 103 5. [Siruri de biti] i) Un algoritm de tip backtracking genereaz, n ordine lexicografic, toate irurile de 5 cifre 0 i 1 cu proprietatea c nu exist mai mult de dou cifre 0 pe poziii consecutive. Primele 7 soluii generate sunt: 00100, 00101, 00110, 00111, 01001, 01010, 01011. Care este a 8-a soluie generat de acest algoritm? a. 01110 b. 01100 c. 01011 d. 01101 ii) Un algoritm genereaz, n ordine lexicografic, toate irurile alctuite din cte n cifre binare (0 i 1). tiind c pentru n=5, primele 4 soluii generate sunt 00000, 00001, 00010, 00011, precizai care sunt ultimele 3 soluii generate, n ordinea obinerii lor. _____________________ iii) Un program citete o valoare natural nenul pentru n i apoi genereaz i afieaz, n ordine cresctoare lexicografic, toate combinaiile formate din n cifre care aparin mulimii {0,1}. Astfel, pentru n=2, combinaiile sunt afiate n urmtoarea ordine: 00, 01, 10, 11. Dac se ruleaz acest program i se citete pentru n valoarea 9, imediat dup combinaia 011011011 va fi afiat combinaia: a. 011100100 b. 011011100 c. 011011011 d. 011100000 iv) Un program citete o valoare natural nenul pentru n i apoi genereaz i afieaz, n ordine descresctoare lexicografic, toate combinaiile de n cifre care aparin mulimii {0,1}. Astfel, pentru n=2, combinaiile sunt afiate n urmtoarea ordine: 11, 10, 01, 00. Dac se ruleaz acest program i se citete pentru n valoarea 8, imediat dup combinaia 10101000 va fi afiat combinaia: a. 01010111 b. 10100111 c. 01010100 d. 10100100 6. [Secvente de suma data] i) Pentru a scrie valoarea 10 ca sum de numere prime se folosete metoda backtracking i se genereaz, n aceast ordine, sumele distincte: 2+2+2+2+2, 2+2+3+3, 2+3+5, 3+7, 5+5. Folosind exact aceeai metod, se scrie valoarea 9 ca sum de numere prime. Care sunt primele trei soluii, n ordinea generrii lor? ______ ii) Folosind un algoritm de generare putem obine numere naturale de k cifre care au suma cifrelor egal cu un numr natural s. Astfel, pentru valorile k=2 i s=6 se genereaz, n ordine, numerele: 15, 24, 33, 42, 51, 60. Care va fi al treilea numr generat pentru k=4 i s=5? a. 1301 b. 1022 c. 2201 d. 1031 iii) Utilizm metoda backtracking pentru generarea tuturor modalitilor de a scrie numrul 9 ca sum a cel puin dou numere naturale nenule distincte. Termenii descompunerii sunt n ordine strict cresctoare. Soluiile se genereaz n ordinea:

1+2+6, 1+3+5, 1+8, 2+3+4, 2+7, 3+6 i 4+5. Se aplic exact aceeai metod pentru scrierea lui 12. Scriei, n ordinea generrii, toate soluiile de forma 2+... iv) Utilizm metoda backtracking pentru generarea tuturor modalitilor de a scrie numrul 9 ca sum a cel puin dou numere naturale nenule distincte. Termenii fiecrei sume sunt n ordine strict cresctoare. Soluiile se genereaz n ordinea: 1+2+6, 1+3+5, 1+8, 2+3+4, 2+7, 3+6 i 4+5. Se aplic exact aceeai metod pentru scrierea lui 8. Cte soluii vor fi generate? a. 3 b. 4 c. 6 d. 5 v) Utilizm metoda backtracking pentru generarea tuturor modalitilor de a scrie numrul 6 ca sum a cel puin dou numere naturale nenule. Termenii fiecrei sume sunt n ordine cresctoare. Soluiile se genereaz n ordinea: 1+1+1+1+1+1, 1+1+1+1+2, 1+1+1+3, 1+1+4, 1+5, 2+2+2, 2+4 i 3+3. Se aplic exact aceeai metod pentru scrierea lui 9. Care este penultima soluie? a. 3+3+3 b. 3+6 c. 4+5 d. 2+7 vi) Utilizm metoda backtracking pentru generarea tuturor modalitilor de a scrie numrul 6 ca sum a cel puin dou numere naturale nenule. Termenii fiecrei sume sunt n ordine cresctoare. Soluiile se genereaz n ordinea: 1+1+1+1+1+1, 1+1+1+1+2, 1+1+1+3, 1+1+4, 1+5, 2+2+2, 2+4 i 3+3. Se aplic exact aceeai metod pentru scrierea lui 9. Cte soluii de forma 2+... vor fi generate? a. 2 b. 3 c. 4 d. 5 vii) Utiliznd metoda backtracking, se genereaz numerele naturale formate din exact 3 cifre i care au suma cifrelor egal cu 4, n aceast ordine: 103, 112, 121, 130, 202, 211, 220, 301, 310, 400. Dac utilizm acelai algoritm pentru a genera toate numerele de 4 cifre care au suma cifrelor egal cu 7, precizai care este numrul generat imediat dup 1222. a. 1231 b. 1223 c. 1213 d. 1321 ix) Utiliznd metoda backtracking pentru afiarea tuturor modalitilor de descompunere a unui numr natural ca o sum de numere naturale nenule, pentru n=3 se obin, n ordine, soluiile: 1+1+1; 1+2; 2+1; 3. Ordinea de scriere a termenilor dintr-o descompunere este semnificativ. Folosind aceeai metod pentru n=10, care este soluia generat imediat dup 1+1+3+5? a. 1+1+4+1+1+1+1 b. 1+1+7+1 c. 1+2+7 d. 1+1+4+4 7. [Permutari] i) In timpul procesului de generare a permutrilor mulimii {1,2,,n} prin metoda backtracking, n tabloul unidimensional x este plasat un element x[k] (1kn). Acesta este considerat valid dac este ndeplinit condiia: a. x[k]{x[1], x[2], , x[k-1]} b. x[k]x[k-1] c. x[k]{x[1], x[2], , x[n]} d. x[k]x[k-1] i x[k]x[k+1] ii) Se utilizeaz un algoritm pentru a genera n ordine lexicografic invers toate permutrile mulimii {1,2,3,4,5}. Primele patru permutri generate sunt: 54321, 54312, 54231, 54213. A cincea permutare este: a. 53421 b. 54321 c. 54132 d. 54123

iii) Utiliznd metoda backtracking se genereaz toate permutrile mulimii {1,2,3,4}. Dac primele trei permutri generate sunt, n acest ordine: 1234, 1243, 1324 precizai care este permutarea generat imediat dup 3412. a. 3421 b. 3413 c. 4123 d. 3214 iv) Utiliznd metoda backtracking se genereaz permutrile cuvntului info. Dac primele trei soluii generate sunt: fino, fion, fnio care este cea de-a cincea soluie? a. foin b. fnoi c. foni d. ifon v) Dac se utilizeaz metoda backtracking pentru a genera toate permutrile de 4 obiecte i primele 5 permutri 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 avnd cifrele ordonate strict cresctor, este echivalent cu algoritmul de generare a: a. submulimilor unei mulimi cu 5 elemente b. produsului cartezian a unor mulimi decifre c. aranjamentelor de 9 elemente luate cte 5 d. combinrilor de 9 elemente luate cte 5 ii) Generarea tuturor cuvintelor de trei litere mici, nu neaprat distincte, ale alfabetului englez, se poate realiza cu ajutorul unui algoritm echivalent cu cel de generare a: a. produsului cartezian b. combinrilor c. aranjamentelor d. permutrilor iii) Pentru generarea tuturor mulimilor de cte 5 cifre, avnd la dispoziie cifrele de la 1 la 9, se poate utilza un algoritm echivalent cu algoritmul de generare a: a. permutrilor de 5 elemente b. submulimilor mulimii {1,2,3,4,5,6,7,8,9} c. combinrilor de 9 elemente luate cte 5 d. aranjamentelor de 9 elemente luate cte 5 iv) Pentru a genera toate numerele naturale cu exact 4 cifre i care au cifrele n ordine strict descresctoare, se poate utiliza un algoritm echivalent cu cel pentru generarea: a. aranjamentelor de 4 obiecte luate cte 10 b. combinrilor de 10 obiecte luate cte 4 c. permutrilor a 10 obiecte d. permutrilor a 4 obiecte v) Generarea matricelor ptratice 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 utiliznd metoda backtracking. Algoritmul utilizat este echivalent cu algoritmul de generare a: a. combinrilor

b. permutrilor c. aranjamentelor d. produsului cartezian vi) Pentru rezolvarea crei probleme dintre cele enumerate mai jos se poate utiliza metoda backtracking ? a. determinarea reuniunii a 3 mulimi b. determinarea tuturor divizorilor unui numr din 3 cifre c. determinarea tuturor elementelor mai mici dect 30000 din irul lui Fibonacci d. avnd 3 culori (rou, galben, albastru), determinarea tuturor variantelor n care se pot genera toate steagurile cu 3 culori avnd la mijloc culoarea galben vii) La un concurs sportiv sunt 5 echipe, iar n fiecare echip sunt cte 10 elevi. Problema determinrii tuturor grupelor de cte 5 elevi, cte unul din fiecare echip, este similar cu generarea tuturor: a. elementelor produsului cartezian AxAxAxAxA, unde A={1,2,,10} b. submulimilor cu 5 elemente ale mulimii {1,2,,10} c. permutrilor mulimii {1,2,3,4,5} d. partiiilor mulimii {1,2,,10} viii) Problema generrii tuturor codurilor formate din exact 4 cifre nenule, cu toate cifrele distincte dou cte dou, este similar cu generarea tuturor: a. aranjamentelor de 9 elemente luate cte 4 b. permutrilor elementelor unei mulimi cu 4 elemente c. elementelor produsului cartezian AxAxAxA unde A este o mulime cu 9 elemente d. submulimilor cu 4 elemente ale mulimii {1,2,3,4,5,6,7,8,9} ix) Cu studentii unei grupe 28 de studenti se dorete formarea unei echip de 4 persoane. Ordinea studentilor n cadrul echipei nu are importan. Algoritmul de generare a tuturor posibilitilor de a forma o asfel de echip este similar cu algoritmul de generare a tuturor: a. aranjamentelor de 28 de elemente luate cte 4 b. combinrilor de 28 de elemente luate cte 4 c. partiiilor unei mulimi d. elementelor produsului cartezian AxAxAxA, A fiind o mulime cu 28 de elemente x) La examenul de licenta, un absolvent primete 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 posibilitilor de a forma un test este similar cu algoritmul de generare a: a. elementelor produsului cartezian b. aranjamentelor c. permutrilor d. submulimilor xi) Trei studenti vor s nfiineze 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. Toi trei tiu s cnte att la PHP, ct i la multimedia, i se pricep cu toii i la baze de date. Algoritmul de generare a tuturor posibilitilor de a forma echipa este similar cu algoritmul de generare a:

a. aranjamentelor b. permutrilor c. elementelor produsului cartezian d. submulimilor 9. [Siruri de caractere] i) Genernd irurile de maximum 3 caractere distincte din mulimea {A,B,C,D,E}, ordonate lexicografic, obinem succesiv: A, AB, ABC, ABD,. Ce ir va fi generat dup BAE? a. BCA b. CAB c. BC d. BEA ii) Utiliznd metoda backtracking se genereaz toate cuvintele de cte 3 litere din mulimea {a,b,c}. Dac primele patru cuvinte generate sunt, n acest ordine: aaa, aab, aac, aba, care este cel de-al optulea cuvnt generat? a. acb b. acc c. aca d. bca iii) Se utilizeaz metoda backtracking pentru a genera toate cuvintele de cte patru litere distincte din mulimea {d,a,n,s}. tiind c al doilea cuvnt generat este dans, iar al treilea este dsan, care va fi ultimul cuvnt obinut? a. nsad b. snad c. snda d. dans iv) Se utilizeaz metoda backtracking pentru a genera toate cuvintele de cte trei litere distincte din mulimea {i,n,f,o}. tiind c ultimele trei cuvinte generate sunt, n ordine, ion, inf i ino, care este cel de-al doilea cuvnt obinut? a. ofn b. ifo c. foi d. nif v) Se utilizeaz metoda backtracking pentru a genera toate cuvintele care conin toate literele din mulimea {i,n,f,o}, astfel nct fiecare liter s apar exact o dat ntr-un cuvnt. tiind c al doilea cuvnt generat este info iar al treilea este ionf, care este ultimul cuvnt obinut? a. nifo b. ofni c. ofin d. foni vi) Se utilizeaz metoda backtracking pentru a genera toate cuvintele care conin toate literele din mulimea {i,n,f,o}, astfel nct fiecare liter s apar exact o dat ntr-un cuvnt i literele n i o s nu se afle pe poziii vecine. tiind c primul cuvnt generat este info, iar al treilea este nifo care este cel de-al doilea cuvnt obinut? a. iofn b. inof c. ionf d. niof 10 [Numarare ] i) Cte numere cu exact 3 cifre pot fi construite folosind doar cifre pare? a. 125 b. 100 c. 64 d. 128 ii) n cte dintre permutrile elementelor mulimii {I,N,F,O} vocalele apar pe poziii consecutive? a. 24 b. 6 c. 12 d. 4

iii) Se consider un numr natural nenul x avnd exact 8 cifre, distincte dou cte dou; printer cifrele sale se gsete i cifra 0. Permutnd cifrele lui x se obin alte numere naturale. Cte dintre numerele obinute, inclusiv x, au exact 8 cifre? ______ iv) Utiliznd metoda backtracking, se genereaz n ordine lexicografic toate anagramele cuvntului caiet ( cuvinte formate din aceleai litere, eventual n alt ordine). Cte cuvinte vor fi generate? a. 60 b. 100 c. 200 d. 120 v) Se genereaz, prin metoda backtracking, toate partiiile mulimii A={1,2,3} obinndu-se urmtoarele soluii: {1}{2}{3}; {1}{2,3}; {1,3}{2}; {1,2}{3}; {1,2,3}. Se observ c dintre acestea, prima soluie e alctuit din exact trei submulimi. Dac se folosete aceeai metod pentru a genera partiiile mulimii {1,2,3,4} stabilii cte dintre soluiile generate vor fi alctuite din exact trei submulimi. a. 3 b. 12 c. 6 d. 5 vi) Se utilizeaz metoda backtracking pentru a genera toate submulimile cu p elemente ale unei mulimi cu m elemente. Dac m=7 i p=4 atunci numrul de submulimi generate este: a. 60 b. 35 c. 5 d. 15 vii) Prin metoda backtracking se genereaz toate anagramele (cuvintele obinute prin permutarea literelor) unui cuvnt dat. tiind c se aplic aceast metod pentru cuvntul pescar, precizai cte cuvinte se vor genera astfel nct prima i ultima liter din fiecare cuvnt generat s fie vocal (sunt considerate vocale caracterele a, e, i , o, u)? a. 96 b. 24 c. 48 d. 12 viii) n cte dintre permutrile elementelor mulimii {I,N,F,O} vocala I apare pe prima poziie? a. 1 b. 24 c. 6 d. 12 11. [Probleme diverse] i) Un program citete o valoare natural nenul impar pentru n i apoi genereaz i afieaz n ordine cresctoare lexicografic toate combinaiile formate din n cifre care ndeplinesc urmtoarele proprieti: - conin doar valori pozitive sau nule; - ncep i se termin cu 0; - modulul diferenei ntre oricare dou cifre alturate dintr-o combinaie este 1. Astfel, pentru n=5, combinaiile afiate sunt, n ordine, urmtoarele: 01010, 01210. Dac se executa acest program i se citete pentru n valoarea 7, imediat dup combinaia 0101210 va fi afiat combinaia: a. 0121210 b. 0123210 c. 0111210 d. 0121010 ii) Pentru generarea numerelor cu n cifre formate cu elementele mulimii {0, 2, 8} se utilizeaz un algoritm backtracking care, pentru n=2, genereaz, n ordine, numerele 20,22,28,80,82,88. Dac n=4 i se utilizeaz acelai algoritm, care este numrul generat imediat dup numrul 2008 ? a. 2002 b. 2020 c. 2080 d. 8002

iii) Avnd la dispoziie cifrele 0, 1 i 2 putem genera, n ordine cresctoare, numere care au suma cifrelor egal cu 2 astfel nct primele 6 numere generate sunt, n aceast ordine: 2, 11, 20, 101, 110, 200. Folosind acelai algoritm se genereaz numere cu cifrele 0, 1, 2 i 3 care au suma cifrelor egal cu 4. Care va fi al 7-lea numr din aceast generare ? a. 103 b. 301 c. 220 d. 130 iv) Completarea unui bilet de LOTO presupune colorarea a 6 numere dintre cele 49, nscrise pe bilet. O situaie statistic pe o anumit perioad de timp arat c cele mai frecvente numere care au fost extrase la LOTO sunt: 2, 20, 18, 38, 36, 42, 46, 48. Cte bilete de 6 numere se pot completa folosind doar aceste valori, tiind c numrul 42 va fi colorat pe fiecare bilet? a. 21 b. 6! c. 42 d. 56 v) Se genereaz prin metoda backtracking mulimile distincte ale cror elemente sunt numere naturale nenule i care au proprietatea c suma elementelor fiecrei mulimi este egal cu 7. Astfel, sunt generate, n aceast ordine, mulimile: {1, 2, 4}, {1, 6}, {2, 5}, {3, 4}, {7}. Folosind aceeai metod pentru a genera mulimile distincte ale cror elemente sunt numere naturale nenule i care au proprietatea c suma elementelor fiecrei mulimi este egal cu 9, stabilii n ce ordine sunt generate urmtoarele mulimi: M1={2, 3, 4}; M2={3, 6}; M3={2, 7}; M4={4, 5}. vi) Se genereaz n ordine strict cresctoare numerele de cte ase cifre care conin: cifra 1 o singur dat, cifra 2 de dou ori i cifra 3 de trei ori. Se obin, n aceast ordine, numerele: 122333, 123233, 123323, , 333221. Cte numere generate prin aceast metod au prima cifr 1 i ultima cifr 2? ________________ vii) Se genereaz n ordine strict cresctoare toate numerele de cte ase cifre care conin: cifra 1 o singur dat, cifra 2 de dou ori i cifra 3 de trei ori. Se obin, n aceast ordine, numerele: 122333, 123233, 123323, , 333221. Ce numr se genereaz imediat dup 332312? viii) Utiliznd metoda backtracking se genereaz n ordine lexicografic toate anagramele cuvntului caiet ( cuvinte formate din aceleai litere, eventual n alt ordine). Care este a asea soluie? a. catei b. actie c. actei d. catie ix) Utiliznd metoda backtracking se genereaz toate matricele ptratice de ordinul 4 ale cror elemente aparin mulimii {0,1}, cu proprietatea c pe fiecare linie i pe fiecare coloan exist o singur valoare 1. Primele 3 soluii generate sunt, n aceast ordine: 1000 0100 0010 0001

1000 0100 0001 0010 1000 0010 0100 0001 Care este penultima soluie? a. 0001 0010 1000 0100 b. 0100 1000 0010 0001 c. 0001 0100 0010 1000 d. 0010 1000 0100 0001 x) Se genereaz, prin metoda backtracking, toate modalitile de aezare a numerelor naturale de la 1 la 5, astfel nct oricare 2 numere consecutive s nu se afle pe poziii alturate. Dac primele dou soluii sunt: (1,3,5,2,4) i (1,4,2,5,3), care este prima soluie generat n care primul numr este 4? a. (4, 1, 3, 2, 5) b. (4, 2, 5, 1, 3) c. (4, 3, 5, 3, 1) d. (4, 1, 3, 5, 2) xi) Se genereaz, prin metoda backtracking, toate modalitile de aezare a numerelor naturale de la 1 la 5 astfel nct oricare dou numere consecutive s nu se afle pe poziii alturate. Dac primele dou soluii sunt: (1,3,5,2,4) i (1,4,2,5,3), care este prima soluie generat care ncepe cu 2? a. (2, 4, 1, 3, 5) b. (2, 5, 4, 3, 1) c. (2, 4, 1, 3, 1) d. (2, 3, 5, 4, 1) xii) Construim anagramele unui cuvnt c1c2c3c4 prin generarea n ordine lexicografic a permutrilor indicilor literelor cuvntului i obinem c1c2c3c4 c1c2c4c3 c1c3c2c4 c4c3c1c2 c4c3c2c1. Pentru anagramele cuvntului rateu, dup irul raetu, raeut, raute cuvintele imediat urmtoare sunt: a. rauet i rtaeu b. rtaeu i rtaue

c. rauet i rtaue d. rtaeu i ratue xiii) Trei baieti, Alin, Bogdan i Ciprian, i trei fete, Delia, Elena i Felicia, trebuie s formeze o echip de 3 studenti, care s participe la un concurs de prezentare software. Echipa trebuie s fie mixt (adic s conin cel puin o fat i cel puin un biat). Ordinea copiilor n echip este important deoarece aceasta va fi ordinea de intrare a studentilor n concurs (de exemplu echipa Alin, Bogdan, Delia este diferit de echipa Bogdan, Alin, Delia). Cte echipe se pot forma, astfel nct din ele s fac parte simultan Alin i Bogdan? _______________ xiv) n vederea participrii la un concurs de programare, studentii din anii 2 si 3 au dat o prob de selecie, n urma creia primii 6 au obinut punctaje egale. n cte moduri poate fi format echipa selecionat tiind c poate avea doar 4 membri, alei dintre cei 6, i c ordinea acestora n cadrul echipei nu conteaz? a. 24 b. 30 c. 15 d. 4 xv) Un program construiete i afieaz elementele produsului cartezian AxBxC pentru mulimile A={1,2,3,4}, B={1,2,3}, C={1,2}. Care dintre urmtoarele triplete NU va fi afiat? a. (3,2,1) b. (1,3,2) c. (1,2,3) d. (2,2,2)

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

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

S-ar putea să vă placă și