48967575 Cursuri Carte Algoritmi Si Exemple Programe

519
ALGORITMI S ¸I STRUCTURI DE DA TE Note de curs (uz intern - draft v2.3)

Transcript of 48967575 Cursuri Carte Algoritmi Si Exemple Programe

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 1/518

ALGORITMI SI STRUCTURI DE DATE

Note de curs(uz intern - draft v2.3)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 2/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 3/518

Prefat ¸aCand dorim s a reprezent˘am obiectele din lumea real˘ a ıntr-un program pe

calculator, trebuie s˘ a avem ın vedere:

• modelarea obiectelor din lumea real˘a sub forma unor entit˘ ati matematiceabstracte si tipuri de date,

• operat iile pentru ınregistrarea, accesul si utilizarea acestor entit˘ ati,

• reprezentarea acestor entit˘ati ın memoria calculatorului, si

• algoritmii pentru efectuarea acestor operat ¸ii.Primele dou˘a elemente sunt ın esent ¸ a de natur˘a matematic˘a si se refer a la

”ce” structuri de date si operat ¸ii trebuie s˘a folosim, iar ultimile dou˘a elementeimplic a faza de implementare si se refer˘ a la ”cum” s a realiz am structurile de datesi operat iile. Algoritmica si structurile de date nu pot separate. Desi algoritmica si programarea pot separate, noi nu vom face acest lucru, ci vom implementaalgoritmiiıntr-un limbaj de programare (Pascal, C/C++, Java). Din aceast˘ a cauz aacest curs este si o init iere ın algoritmic˘ a si programare .

Scopul cursului este subordonat scopului specializ˘ arii (informatic˘a, ın cazulnostru) care este s˘a preg ateasc a specialisti competent ¸i , cu ınalt˘a calicare ındomeniul informaticii, cadre didactice competente ın acest domeniu (profesor deinformatic˘a ın gimnaziu si liceu), informaticieni ın diverse domenii cu prol tehnic,economic, etc. ce pot ıncepe lucrul imediat dup˘ a absolvirea facult˘at ii.Dezideratulnal este deci competent ¸a . Competent¸a ıntr-un domeniu de activitate implic˘ aexperient ¸a ın rezolvarea problemelor din acel domeniu de activitate. Atˆ atcompetent¸a c at si experient¸a ın rezolvarea problemelor se pot obt ¸ine numai dac˘apermanent se ıntreprind eforturi pentru ınsusirea de noi cunostint ¸e. De exemplu,

orice informatician (programator sau profesor) care elaboreaz˘ a programe pentrurezolvarea unor probleme diverse, trebuie s˘ a aib a competent e conform schemei 1 :

PROBLEMA(model fizic)

ALGORITMICA(model virtual)

PROGRAMARE

Gandire algoritmica Experienta(rezolvarea de probleme)

Cursul de Algoritmi si structuri de date este util (si chiar necesar) pentruformarea competent ¸elor si abilit˘ at ilor unui bun programator sau profesor deinformatic˘a. Pentru a vedea care sunt aceste competent ¸e si abilit˘at i putem, de

1 M. Vlada; E-Learning si Software educat ¸ional; Conferint ¸a Nat¸ional˘a de Inv at am ant Virtual,Bucuresti, 2003

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 4/518

exemplu, s a citim Programa pentru informatic˘ a - Concursul nat ional unic pentru ocuparea posturilor didactice declarate vacante ın ınv˘ at amantul preuniversitar .2

Intr-un fel, primul semestru al cursului Algoritmi si structuri de date esteechivalent cu ceea ce se pred˘a la informatic˘aın clasa a IX-a iar al doilea semestru cuclasa a X-a (specializarea: matematic˘ a-informatic˘a, intensiv informatic˘ a). Diferent aeste dat˘a ın primul rˆ and de dicultatea problemelor abordate de c˘ atre noi ın cadrulacestui curs. Din aceast˘ a cauz a vom avea ın vedere si ce prevede Pograma solar a pentru clasa a IX-a, Prol real, Specializarea: Matematic˘ a-informatic˘ a, intensiv informatic˘ a . De asemenea, merit˘a sa vedem ce p areri au cei care au terminat decur and o facultate cu un prol de informatic˘ a si care au un ınceput de carier˘ areusit. Vom ınt ¸elege de ce acest curs este orientat pe rezolvarea de probleme .

Alegerea limbajului Java pentru prezentarea implement˘ arilor algoritmilor afost facut a din c ateva considerente. Java veric˘ a validitatea indicilor tablourilor(programele nu se pot termina printr-o violare de memorie sau eroare de sistem).Java realizeaz˘a gestiunea automat˘ a a memoriei (recupereaz˘ a automat memoriacare nu mai este necesar˘a programului) ceea ce simplic˘ a scrierea programelorsi permite programatorului s˘ a se concentreze asupra esent ¸ei algoritmului. Exist˘ adocumentat¸ie pe internet. Compilatorul de Java este gratuit. Un program scris ınJava poate executat pe orice calculator (indiferent de arhitectur˘ a sau sistem deoperare).

Student ii nu sunt obligat ¸i sa realizeze implement˘arile algoritmilor ın Java;ei pot folosi Pascal sau C/C++. Algoritmii prezentat ¸i ın curs sunt descrisi ın limbaj natural sau ın limbaj algoritmic iar implement˘arile sunt ın limbajul de programareJava. Java este un limbaj orientat-obiect, dar noi vom utiliza foarte put ¸in aceast˘aparticularitate. Sunt prezentate toate elementele limbajului de programare Javanecesare pentru acest curs dar ecesta nu este un curs de programare ın Java .

Cunostint ¸ele minimale acceptate la sfˆ arsitul cursului rezult˘ a din Legea nr.288 din 24 iunie 2004 privind organizarea studiilor universitare si, de exemplu,din Ghidul calit˘ at ii ın ınv at amantul superior 3 . Aici se precizeaza faptul c a diplomade licent a se acord a unui absolvent al programului de studii care: demonstreazaacumulare de cunostint ¸e si capacitatea de a ınt ¸elege aspecte din domeniulde studii ın care s-a format, poate folosi at at cunostint ¸ele acumulate precumsi capacitatea lui de ınt ¸elegere a fenomenelor printr-o abordare profesionalaın domeniul de activitate, a acumulat competent ¸e necesare demonstrarii ,argumentarii si rezolvarii problemelor din domeniul de studii considerat, si-adezvoltat deprinderi de ınv˘ at are necesare procesului de educat ¸ie continu˘a.

2 Aprobat˘ a prin O.M:Ed.C. nr.5287/15.11.20043 Editura Universit˘ at ii din Bucuresti, 2004; Capitolul 4, Calitatea programelor de studii uni-

versitare , Prof.univ.dr. Gabriela M. Atanasiu - Universitatea Tehnic˘ a ”Gh.Asachi” din Iasi

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 5/518

Cuprins

1 Not iuni fundamentale 11.1 Programe ciudate . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.1.1 Un program ciudat ın Pascal . . . . . . . . . . . . . . . . . 11.1.2 Un program ciudat ın C++ . . . . . . . . . . . . . . . . . . 21.1.3 Un program ciudat ın Java . . . . . . . . . . . . . . . . . . 31.1.4 Structura unui program Java . . . . . . . . . . . . . . . . . 4

1.2 Conversii ale datelor numerice . . . . . . . . . . . . . . . . . . . . 51.2.1 Conversia din baza 10 ın baza 2 . . . . . . . . . . . . . . . . 51.2.2 Conversia din baza 2 ın baza 10 . . . . . . . . . . . . . . . . 61.2.3 Conversii ıntre bazele 2 si 2 r . . . . . . . . . . . . . . . . . 6

2 Structuri de date 72.1 Date si structuri de date . . . . . . . . . . . . . . . . . . . . . . . . 7

2.1.1 Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.1.2 Structuri de date . . . . . . . . . . . . . . . . . . . . . . . . 92.2 Structuri si tipuri de date abstracte . . . . . . . . . . . . . . . . . . 102.2.1 Structuri de date abstracte . . . . . . . . . . . . . . . . . . 102.2.2 Tipuri de date abstracte . . . . . . . . . . . . . . . . . . . . 10

2.3 Structuri de date elementare . . . . . . . . . . . . . . . . . . . . . 112.3.1 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.3.2 Stive si cozi . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.3.3 Grafuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.3.4 Arbori binari . . . . . . . . . . . . . . . . . . . . . . . . . . 142.3.5 Heap-uri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.3.6 Structuri de mult ¸imi disjuncte . . . . . . . . . . . . . . . . 16

3 Algoritmi 173.1 Etape ın rezolvarea problemelor . . . . . . . . . . . . . . . . . . . . 173.2 Algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

3.2.1 Ce este un algoritm? . . . . . . . . . . . . . . . . . . . . . . 183.2.2 Propriet˘atile algoritmilor . . . . . . . . . . . . . . . . . . . 203.2.3 Tipuri de prelucr˘ ari . . . . . . . . . . . . . . . . . . . . . . 20

v

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 6/518

3.3 Descrierea algoritmilor . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3.1 Limba j natural . . . . . . . . . . . . . . . . . . . . . . . . . 213.3.2 Scheme logice . . . . . . . . . . . . . . . . . . . . . . . . . . 223.3.3 Pseudocod . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.4 Limbaj algoritmic . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.4.1 Declararea datelor . . . . . . . . . . . . . . . . . . . . . . . 233.4.2 Operat ii de intrare/iesire . . . . . . . . . . . . . . . . . . . 233.4.3 Prelucr˘ari liniare . . . . . . . . . . . . . . . . . . . . . . . . 243.4.4 Prelucr˘ari alternative . . . . . . . . . . . . . . . . . . . . . 243.4.5 Prelucr˘ari repetitive . . . . . . . . . . . . . . . . . . . . . . 253.4.6 Subalgoritm . . . . . . . . . . . . . . . . . . . . . . . . . . . 263.4.7 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . 273.4.8 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . 30

3.5 Instruct¸iuni corespondente limbajului algoritmic . . . . . . . . . . 323.5.1 Declararea datelor . . . . . . . . . . . . . . . . . . . . . . . 323.5.2 Operat ii de intrare/iesire . . . . . . . . . . . . . . . . . . . 343.5.3 Prelucr˘ari liniare . . . . . . . . . . . . . . . . . . . . . . . . 353.5.4 Prelucr˘ari alternative . . . . . . . . . . . . . . . . . . . . . 353.5.5 Prelucr˘ari repetitive . . . . . . . . . . . . . . . . . . . . . . 353.5.6 Subprograme . . . . . . . . . . . . . . . . . . . . . . . . . . 363.5.7 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . 373.5.8 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . 52

4 Analiza complexitat ¸ii algoritmilor 554.1 Scopul analizei complexit˘atii . . . . . . . . . . . . . . . . . . . . . . 55

4.1.1 Complexitatea spat ¸iu . . . . . . . . . . . . . . . . . . . . . 574.1.2 Complexitatea timp . . . . . . . . . . . . . . . . . . . . . . 57

4.2 Notat ia asimptotic˘ a . . . . . . . . . . . . . . . . . . . . . . . . . . 584.2.1 Denire si propriet˘ ati . . . . . . . . . . . . . . . . . . . . . 584.2.2 Clase de complexitate . . . . . . . . . . . . . . . . . . . . . 604.2.3 Cazul mediu si cazul cel mai defavorabil . . . . . . . . . . . 614.2.4 Analiza asimptotic˘ a a structurilor fundamentale . . . . . . 62

4.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624.3.1 Calcularea maximului . . . . . . . . . . . . . . . . . . . . . 624.3.2 Sortarea prin select¸ia maximului . . . . . . . . . . . . . . . 624.3.3 Sortarea prin insert ¸ie . . . . . . . . . . . . . . . . . . . . . . 63

4.3.4 Sortarea rapid˘a (quicksort) . . . . . . . . . . . . . . . . . . 644.3.5 Problema celebrit˘ atii . . . . . . . . . . . . . . . . . . . . . . 66

4.4 Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674.4.1 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . 674.4.2 Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . 69

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 7/518

5 Recursivitate 715.1 Funct ii recursive . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

5.1.1 Funct ii numerice . . . . . . . . . . . . . . . . . . . . . . . . 715.1.2 Funct ia lui Ackerman . . . . . . . . . . . . . . . . . . . . . 745.1.3 Recursii imbricate . . . . . . . . . . . . . . . . . . . . . . . 74

5.2 Proceduri recursive . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

6 Analiza algoritmilor recursivi 776.1 Relat ii de recurent¸a . . . . . . . . . . . . . . . . . . . . . . . . . . 77

6.1.1 Ecuat ia caracteristic˘ a . . . . . . . . . . . . . . . . . . . . . 786.1.2 Solutia general˘a . . . . . . . . . . . . . . . . . . . . . . . . 78

6.2 Ecuat ii recurente neomogene . . . . . . . . . . . . . . . . . . . . . 806.2.1 O forma simpl a . . . . . . . . . . . . . . . . . . . . . . . . . 806.2.2 O forma mai general a . . . . . . . . . . . . . . . . . . . . . 816.2.3 Teorema master . . . . . . . . . . . . . . . . . . . . . . . . 826.2.4 Transformarea recurent ¸elor . . . . . . . . . . . . . . . . . . 84

6.3 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

7 Algoritmi elementari 937.1 Operat ii cu numere . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

7.1.1 Minim si maxim . . . . . . . . . . . . . . . . . . . . . . . . 937.1.2 Divizori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 947.1.3 Numere prime . . . . . . . . . . . . . . . . . . . . . . . . . 95

7.2 Algoritmul lui Euclid . . . . . . . . . . . . . . . . . . . . . . . . . . 957.2.1 Algoritmul clasic . . . . . . . . . . . . . . . . . . . . . . . . 957.2.2 Algoritmul lui Euclid extins . . . . . . . . . . . . . . . . . . 96

7.3 Operat ii cu polinoame . . . . . . . . . . . . . . . . . . . . . . . . . 977.3.1 Adunarea a dou˘a polinoame . . . . . . . . . . . . . . . . . . 977.3.2 Inmult irea a dou˘a polinoame . . . . . . . . . . . . . . . . . 987.3.3 Calculul valorii unui polinom . . . . . . . . . . . . . . . . . 987.3.4 Calculul derivatelor unui polinom . . . . . . . . . . . . . . . 98

7.4 Operat ii cu mult imi . . . . . . . . . . . . . . . . . . . . . . . . . . 1007.4.1 Apartenent ¸a la mult ime . . . . . . . . . . . . . . . . . . . . 1007.4.2 Diferent a a dou a mult imi . . . . . . . . . . . . . . . . . . . 1007.4.3 Reuniunea si intersect ¸ia a dou a mult imi . . . . . . . . . . . 1017.4.4 Produsul cartezian a dou˘ a mult imi . . . . . . . . . . . . . . 1017.4.5 Generarea submult ¸imilor unei mult¸imi . . . . . . . . . . . . 102

7.5 Operat ii cu numere ıntregi mari . . . . . . . . . . . . . . . . . . . . 1047.5.1 Adunarea si sc aderea . . . . . . . . . . . . . . . . . . . . . . 1047.5.2 Inmult irea si ımp˘ artirea . . . . . . . . . . . . . . . . . . . . 1057.5.3 Puterea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

7.6 Operat ii cu matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077.6.1 Inmult irea . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077.6.2 Inversa unei matrice . . . . . . . . . . . . . . . . . . . . . . 107

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 8/518

8 Algoritmi combinatoriali 1098.1 Principiul includerii si al excluderii si aplicat ¸ii . . . . . . . . . . . . 109

8.1.1 Principiul includerii si al excluderii . . . . . . . . . . . . . . 1098.1.2 Numarul funct iilor surjective . . . . . . . . . . . . . . . . . 1108.1.3 Numarul permut˘arilor f ar a puncte xe . . . . . . . . . . . . 112

8.2 Principiul cutiei lui Dirichlet si aplicat ¸ii . . . . . . . . . . . . . . . 1138.2.1 Problema subsecvent ¸ei . . . . . . . . . . . . . . . . . . . . . 1138.2.2 Problema subsirurilor strict monotone . . . . . . . . . . . . 114

8.3 Numere remarcabile . . . . . . . . . . . . . . . . . . . . . . . . . . 1148.3.1 Numerele lui Fibonacci . . . . . . . . . . . . . . . . . . . . 1158.3.2 Numerele lui Catalan . . . . . . . . . . . . . . . . . . . . . 116

8.4 Descompunerea ın factori primi . . . . . . . . . . . . . . . . . . . . 1198.4.1 Funct ia lui Euler . . . . . . . . . . . . . . . . . . . . . . . . 1198.4.2 Numarul divizorilor . . . . . . . . . . . . . . . . . . . . . . 1218.4.3 Suma divizorilor . . . . . . . . . . . . . . . . . . . . . . . . 121

8.5 Partit¸ia numerelor . . . . . . . . . . . . . . . . . . . . . . . . . . . 1228.5.1 Partit¸ia lui n ın exact k termeni . . . . . . . . . . . . . . . 1228.5.2 Partit¸ia lui n ın cel mult k termeni . . . . . . . . . . . . . . 1238.5.3 Partit¸ii multiplicative . . . . . . . . . . . . . . . . . . . . . 123

8.6 Partit¸ia mult imilor . . . . . . . . . . . . . . . . . . . . . . . . . . . 1238.7 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

9 Algoritmi de cautare 1279.1 Problema c aut arii . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1279.2 Cautarea secvent ¸ial a . . . . . . . . . . . . . . . . . . . . . . . . . . 1279.3 Cautare binar˘ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

9.4 Inserare ın tabel˘ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1309.5 Dispersia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

10 Algoritmi elementari de sortare 13310.1 Introducere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13310.2 Sortare prin select¸ie . . . . . . . . . . . . . . . . . . . . . . . . . . 13410.3 Sortare prin insert¸ie . . . . . . . . . . . . . . . . . . . . . . . . . . 139

10.3.1 Insert ie direct˘a . . . . . . . . . . . . . . . . . . . . . . . . . 13910.3.2 Insert ie binar˘a . . . . . . . . . . . . . . . . . . . . . . . . . 141

10.4 Sortare prin interschimbare . . . . . . . . . . . . . . . . . . . . . . 14210.5 Sortare prin micsorarea incrementului - shell . . . . . . . . . . . . 143

11 Liste 14511.1 Liste liniare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14511.2 Cozi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15111.3 Stive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15511.4 Evaluarea expresiilor aritmetice prexate . . . . . . . . . . . . . . 15711.5 Operat ii asupra listelor . . . . . . . . . . . . . . . . . . . . . . . . . 159

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 9/518

12 Algoritmi divide et impera 163

12.1 Tehnica divide et impera . . . . . . . . . . . . . . . . . . . . . . . . 16312.2 Ordinul de complexitate . . . . . . . . . . . . . . . . . . . . . . . . 16412.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

12.3.1 Sortare prin partitionare - quicksort . . . . . . . . . . . . . 16512.3.2 Sortare prin interclasare - MergeSort . . . . . . . . . . . . . 16612.3.3 Placa cu g auri . . . . . . . . . . . . . . . . . . . . . . . . . 16812.3.4 Turnurile din Hanoi . . . . . . . . . . . . . . . . . . . . . . 16912.3.5 Injum at at ire repetat˘ a . . . . . . . . . . . . . . . . . . . . . 173

13 Algoritmi BFS-Lee 17713.1 Prezentare general˘ a . . . . . . . . . . . . . . . . . . . . . . . . . . . 17713.2 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

13.2.1 Romeo si Julieta - OJI2004 clasa a X-a . . . . . . . . . . . 18013.2.2 Sudest - OJI2006 clasa a X-a . . . . . . . . . . . . . . . . . 18513.2.3 Muzeu - ONI2003 clasa a X-a . . . . . . . . . . . . . . . . . 19113.2.4 P aianjen ONI2005 clasa a X-a . . . . . . . . . . . . . . . . 19713.2.5 Algoritmul Edmonds-Karp . . . . . . . . . . . . . . . . . . 20413.2.6 Cupla j maxim . . . . . . . . . . . . . . . . . . . . . . . . . 208

14 Metoda optimului local - greedy 21314.1 Metoda greedy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21314.2 Algoritmi greedy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21414.3 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

14.3.1 Problema continu˘ a a rucsacului . . . . . . . . . . . . . . . . 215

14.3.2 Problema plas˘arii textelor pe o band˘ a . . . . . . . . . . . . 21614.3.3 Problema plas˘arii textelor pe m benzi . . . . . . . . . . . . 21714.3.4 Maximizarea unei sume de produse . . . . . . . . . . . . . . 21714.3.5 Problema stat ¸iilor . . . . . . . . . . . . . . . . . . . . . . . 21714.3.6 Problema cutiilor . . . . . . . . . . . . . . . . . . . . . . . . 21814.3.7 Problema subsirurilor . . . . . . . . . . . . . . . . . . . . . 21914.3.8 Problema intervalelor disjuncte . . . . . . . . . . . . . . . . 21914.3.9 Problema alegerii taxelor . . . . . . . . . . . . . . . . . . . 22014.3.10 Problema acoperirii intervalelor . . . . . . . . . . . . . . . . 22014.3.11Algoritmul lui Prim . . . . . . . . . . . . . . . . . . . . . . 22014.3.12Algoritmul lui Kruskal . . . . . . . . . . . . . . . . . . . . . 22814.3.13 Algoritmul lui Dijkstra . . . . . . . . . . . . . . . . . . . . . 230

14.3.14 Urgent a - OJI2002 cls 11 . . . . . . . . . . . . . . . . . . . 24114.3.15Reactivi - OJI2004 cls 9 . . . . . . . . . . . . . . . . . . . . 24614.3.16Pal - ONI2005 cls 9 . . . . . . . . . . . . . . . . . . . . . . 25014.3.17 Sant¸ - ONI2006 cls 9 . . . . . . . . . . . . . . . . . . . . . . 25514.3.18Cezar - OJI2007 cls 11 . . . . . . . . . . . . . . . . . . . . . 260

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 10/518

15 Metoda backtracking 26915.1 Generarea produsului cartezian . . . . . . . . . . . . . . . . . . . . 269

15.1.1 Generarea iterativ˘ a a produsului cartezian . . . . . . . . . . 26915.1.2 Generarea recursiv˘ a a produsului cartezian . . . . . . . . . 274

15.2 Metoda bactracking . . . . . . . . . . . . . . . . . . . . . . . . . . 27715.2.1 Bactracking iterativ . . . . . . . . . . . . . . . . . . . . . . 27915.2.2 Backtracking recursiv . . . . . . . . . . . . . . . . . . . . . 279

15.3 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 28015.3.1 Generarea aranjamentelor . . . . . . . . . . . . . . . . . . . 28015.3.2 Generarea combin˘ arilor . . . . . . . . . . . . . . . . . . . . 28415.3.3 Problema reginelor pe tabla de sah . . . . . . . . . . . . . . 29415.3.4 Turneul calului pe tabla de sah . . . . . . . . . . . . . . . . 29615.3.5 Problema color˘arii h art ilor . . . . . . . . . . . . . . . . . . 29815.3.6 Problema vecinilor . . . . . . . . . . . . . . . . . . . . . . . 30115.3.7 Problema labirintului . . . . . . . . . . . . . . . . . . . . . 30315.3.8 Generarea partit ¸iilor unui num˘ar natural . . . . . . . . . . 30615.3.9 Problema parantezelor . . . . . . . . . . . . . . . . . . . . . 31015.3.10 Algoritmul DFS de parcurgere a grafurilor . . . . . . . . . . 31115.3.11 Determinarea componentelor conexe . . . . . . . . . . . . . 31315.3.12 Determinarea componentelor tare conexe . . . . . . . . . . 31415.3.13 Sortare topologic˘a . . . . . . . . . . . . . . . . . . . . . . . 31615.3.14 Determinarea nodurilor de separare . . . . . . . . . . . . . 32015.3.15 Determinarea muchiilor de rupere . . . . . . . . . . . . . . 32115.3.16 Determinarea componentelor biconexe . . . . . . . . . . . . 32315.3.17 Triangulat ¸ii - OJI2002 clasa a X-a . . . . . . . . . . . . . . 32615.3.18 Partit¸ie - ONI2003 clasa a X-a . . . . . . . . . . . . . . . . 330

15.3.19 Scuta - ONI2003 clasa a X-a . . . . . . . . . . . . . . . . . 33616 Programare dinamic˘ a 343

16.1 Prezentare general˘ a . . . . . . . . . . . . . . . . . . . . . . . . . . . 34316.2 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

16.2.1 Inmult irea optimal˘a a matricelor . . . . . . . . . . . . . . . 34516.2.2 Subsir cresc˘ator maximal . . . . . . . . . . . . . . . . . . . 34816.2.3 Suma maxim a ın triunghi de numere . . . . . . . . . . . . . 35216.2.4 Subsir comun maximal . . . . . . . . . . . . . . . . . . . . . 35316.2.5 Distant a minim˘a de editare . . . . . . . . . . . . . . . . . . 36016.2.6 Problema rucsacului (0 −1) . . . . . . . . . . . . . . . . . . 36616.2.7 Problema schimbului monetar . . . . . . . . . . . . . . . . . 36716.2.8 Problema travers˘ arii matricei . . . . . . . . . . . . . . . . . 36816.2.9 Problema segment˘ arii vergelei . . . . . . . . . . . . . . . . . 37016.2.10 Triangularizarea poligoanelor convexe . . . . . . . . . . . . 37316.2.11 Algoritmul Roy-Floyd-Warshall . . . . . . . . . . . . . . . . 37416.2.12 Oracolul decide - ONI2001 cls 10 . . . . . . . . . . . . . . . 37516.2.13 Pav ari - ONI2001 clasa a X-a . . . . . . . . . . . . . . . . . 381

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 11/518

xi

16.2.14 Balant a ONI2002 clasa a X-a . . . . . . . . . . . . . . . . . 38316.2.15 Aliniere ONI2002 clasa a X-a . . . . . . . . . . . . . . . . . 38716.2.16Munte - ONI2003 cls 10 . . . . . . . . . . . . . . . . . . . . 39316.2.17 Lacusta - OJI2005 clasa a X-a . . . . . . . . . . . . . . . . 40116.2.18Avere ONI2005 cls 10 . . . . . . . . . . . . . . . . . . . . . 41216.2.19Suma - ONI2005 cls 10 . . . . . . . . . . . . . . . . . . . . 416

17 Potrivirea sirurilor 42917.1 Un algoritm inecient . . . . . . . . . . . . . . . . . . . . . . . . . 42917.2 Un algoritm ecient - KMP . . . . . . . . . . . . . . . . . . . . . . 43117.3 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 436

17.3.1 Circular - Campion 2003-2004 Runda 6 . . . . . . . . . . . 43617.3.2 Cifru - ONI2006 baraj . . . . . . . . . . . . . . . . . . . . . 438

18 Geometrie computat ¸ional˘ a 44518.1 Determinarea orient˘ arii . . . . . . . . . . . . . . . . . . . . . . . . 44518.2 Testarea convexit˘ atii poligoanelor . . . . . . . . . . . . . . . . . . . 44618.3 Aria poligoanelor convexe . . . . . . . . . . . . . . . . . . . . . . . 44618.4 Pozit ia unui punct fat ¸a de un poligon convex . . . . . . . . . . . . 44618.5 Pozit ia unui punct fat ¸a de un poligon concav . . . . . . . . . . . . 44718.6 Infasur˘atoarea convex˘a . . . . . . . . . . . . . . . . . . . . . . . . . 448

18.6.1 Impachetarea Jarvis . . . . . . . . . . . . . . . . . . . . . . 44818.6.2 Scanarea Craham . . . . . . . . . . . . . . . . . . . . . . . . 452

18.7 Dreptunghi minim de acoperire a punctelor . . . . . . . . . . . . . 46218.8 Cerc minim de acoperire a punctelor . . . . . . . . . . . . . . . . . 46318.9 Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . 463

18.9.1 Seceta - ONI2005 clasa a IX-a . . . . . . . . . . . . . . . . 46318.9.2 Antena - ONI2005 clasa a X-a . . . . . . . . . . . . . . . . 47718.9.3 Mosia lui P˘acal a - OJI2004 clasa a XI-a . . . . . . . . . . . 48218.9.4 Partit¸ie - ONI2006 baraj . . . . . . . . . . . . . . . . . . . . 48318.9.5 Triunghi - ONI2007 cls 9 . . . . . . . . . . . . . . . . . . . 487

19 Teoria jocurilor 49319.1 Jocul NIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493

19.1.1 Prezentare general˘ a . . . . . . . . . . . . . . . . . . . . . . 49319.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493

20 Alt¸i algoritmi 49520.1 Secvent a de sum a maxim a . . . . . . . . . . . . . . . . . . . . . . . 495

20.1.1 Prezentare general˘ a . . . . . . . . . . . . . . . . . . . . . . 49520.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495

20.2 Algoritmul Belmann-Ford . . . . . . . . . . . . . . . . . . . . . . . 49520.2.1 Algoritmul Belmann-Ford pentru grafuri neorientate . . . . 49520.2.2 Alg Belmann-Ford pentru grafuri orientate . . . . . . . . . 498

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 12/518

xii

20.2.3 Alg Belmann-Ford pentru grafuri orientate aciclice . . . . . 501

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 13/518

Capitolul 1

Not iuni fundamentale

In general, student ¸ii din anul I au cunostint ¸e de programare ın Pascal sauC/C++. Noi vom prezenta implement˘ arile algoritmilor ın Java. Nu are prea mareimportant¸ a dac a este Java, C/C++, Pascal sau alt limbaj de programare. Oricarear limbajul de programare, trebuie s˘ a stim ın primul rˆ and cum se reprezint˘ anumerele ın memoria calculatorului. Altfel putem avea surprize ciudate.

1.1 Programe ciudate

Daca nu suntem atent ¸i la valorile pe care le pot lua variabilele cu care lucr˘ am,

putem obt ine rezultate gresite chiar dac˘ a modalitatea de rezolvare a problemei estecorect a. Prezent˘am astfel de situat¸ii ın Pascal, C/C++ si Java.

1.1.1 Un program ciudat ın Pascal

Iat a un program Pascal ın care dorim s˘ a calcul am suma 20 .000 + 30.000.

var x,y,z:integer;BEGIN

x:=20000;y:=30000;z:=x+y;

write(x,’+’,y,’=’,z);END.

Desi ne asteptam s˘ a apar a ca rezultat 50 .000, surpriza este c˘a pe ecran apare

20000+30000=-15536

1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 14/518

2 CAPITOLUL 1. NOTIUNI FUNDAMENTALE

Figura 1.1: Un program ciudat ın Pascal

1.1.2 Un program ciudat ın C++Iat a un program ın C++ ın care dorim s˘ a calcul am suma 20 .000 + 30.000.

#include<iostream.h>int main()

int x,y,z;x=20000; y=30000; z=x+y;cout << x <<"+"<<y<<"="<<z;return 0;

Desi ne asteptam s˘ a apar a ca rezultat 50 .000, surpriza este c˘a pe ecran apare20000+30000=-15536

Figura 1.2: Un program ciudat ın C++

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 15/518

1.1. PROGRAME CIUDATE 3

1.1.3 Un program ciudat ın Java

Iat a un program ın C++ ın care dorim s˘ a calcul am suma 200 .000∗300.000.class Ciudat

public static void main(String args[]) int x,y,z;x=200000;y=300000;z=x*y;System.out.println(x+"*"+y+"="+z);

Desi ne asteptam s˘ a apar a ca rezultat 60 .000.000.000, surpriza este c˘a pe ecranapare

200000*300000=-129542144

Figura 1.3: Un program ciudat ın Java

Calculul cu numerele ıntregi este relativ simplu. Calculele sunt f˘ acute ıntr-oaritmetic˘a modulo N = 2 n unde n este num arul de bit i ai cuv antului masin˘ a.Exist a masini pe 16, 32 si 64 bit¸i pentru care N este aproximativ egal cu 6 ×104 ,4

×109 si respectiv 2

×1019 .

Se pot reprezenta si numerele ıntregi negative. Modul curent de reprezentareeste ın complement fat ¸ a de 2. In notat ie binar˘a, bitul cel mai semnicativ estebitul de semn. Numerele negative sunt cuprinse ıntre −2n −1 si 2n −1 −1.

Atunci c and valorile obt inute din calcule dep˘ asesc marginile permise de tipul variabilelor implicate ın respectivele calcule, se pot obt ¸ine rezultate eronate.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 16/518

4 CAPITOLUL 1. NOTIUNI FUNDAMENTALE

1.1.4 Structura unui program Java

Un program simplu ın Java are urm˘ atoarea structur˘ a:class numeClasa

public static void main(String args[])

// declar˘ ari de variabile// instruct ¸iuni

Programul prezentat ın sect ¸iunea anterioar˘ a se poate scrie sub forma:class Ciudat

public static void main(String args[])

// declar˘ ari de variabileint x,y,z;

// instruct ¸iunix=200000;y=300000;z=x*y;System.out.println (x+”*”+y+”=”+z);

Clasa este elementul de baz˘a ın Java. Cel mai simplu program ın Java este

format dintr-o clas˘ a (numele clasei este la latitudinea programatorului; singurarecomandare este s˘a ınceap˘a cu liter a mare) si funct¸ia main .

In exemplul de mai sus sunt declarate trei variabile (x, y si z) de tip int(adic a de tip ıntreg cu semn ). Spat iul alocat variabilelor de tip int este de 4 octet i(32 biti). Aceasta ınseamn˘ a ca o astfel de variabil˘a poate avea valori ıntre −263 si263 −1. Valoarea maxim˘ a este de aproximativ 2 miliarde.

In programul anterior x are valoarea 200 .000 iar y are valoarea 300 .000, deciprodusul are valoarea 60 miliarde care dep˘ aseste cu mult valoarea maxim˘ a de 2miliarde.

In binar, 60 miliarde se scrie (folosint 36 bit ¸i) sub forma1101 11111000010001110101100000000000

dar sunt ret¸inut i numai 32 bit i din partea dreapt˘ a, adic a11111000010001110101100000000000

Primul bit reprezint˘ a bitul de semn (1 reprezint˘ a semnul - iar 0 reprezint˘asemnul +). Aceast˘ a reprezentare trebuie gˆ andit a ca ind o reprezentare ın cod

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 17/518

1.2. CONVERSII ALE DATELOR NUMERICE 5

complementar (ea este ın memoria calculatorului si toate numerele ıntregi cu semnsunt reprezentate ın acest cod).

Reprezentarea ın cod direct se obtine din reprezentarea ın cod complementar(mai precis, trecˆand prin reprezentarea ın cod invers si adunˆand, ın binar, 1):

11111000010001110101100000000000 (cod complementar)10000111101110001010011111111111 (cod invers)10000111101110001010100000000000 (cod direct)

Din codul direct se obtine -129542144 ın baza 10. Aceasta este explicat ¸ia aceluirezultat ciudat !

1.2 Conversii ale datelor numerice

1.2.1 Conversia din baza 10 ın baza 2

Fie x = an ...a 0 num arul scris ın baza 10. Conversia ın baza 2 a num˘ arului xse efectueaz a dup a urm atoarele reguli:

• Se ımparte num˘ arul x la 2 iar restul va reprezenta cifra de ordin 0 anum arului scris ın noua baz˘ a (b0).

• Catul obt inut la ımp˘ art irea anterioar˘ a se ımparte la 2 si se obt ¸inecifra de ordin imediat superior a num˘ arului scris ın noua baz˘ a. Secvent ade ımp˘art iri se repet˘a pan a cand se ajunge la c atul 0.

• Restul de la a k-a ımp˘art ire va reprezenta cifra bk−1 . Restul dela ultima ımp˘ art ire reprezint˘ a cifra de ordin maxim ın reprezentareanum arului ın baza 2.

Metoda conduce la obt¸inerea rezultatului dup˘ a un num ar nit de ımp˘ artiri,ıntrucˆat ın mod inevitabil se ajunge la un cˆ at nul. In plus, toate resturile obt ¸inuteapart in mult imii 0, 1.

Exemplu .Fie x = 13 num˘arul ın baza 10. Secvent ¸a de ımp˘art iri este:

(1) se ımparte 13 la 2 si se obt ¸ine c atul 6 si restul 1 (deci b0 = 1)

(2) se ımparte 6 la 2 si se obt¸ine c atul 3 si restul 0 (deci b1 = 0)

(3) se ımparte 3 la 2 si se obt¸ine c atul 1 si restul 1 (deci b2 = 1)

(4) se ımparte 1 la 2 si se obt¸ine c atul 0 si restul 1 (deci b3 = 1).

Prin urmare (13) 10 = (1101) 2 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 18/518

6 CAPITOLUL 1. NOTIUNI FUNDAMENTALE

1.2.2 Conversia din baza 2 ın baza 10

Daca y = bn ...b1b0 este un num˘ar ın baza 2 , atunci reprezentareaın baza 10se obtine efectu and calculul (ın baza 10):

x = bn 2n + ... + b12 + b0 .

Exemplu . Fie y = 1100. Atunci reprezentarea ın baza 10 va

x = 1 ·23 + 1 ·22 + 0 ·21 + 0 ·20 = 12 .

1.2.3 Conversii ıntre bazele 2 si 2r

Pentru conversia unui num˘ ar din baza p ın baza q se poate converti num˘ aruldin baza p ın baza 10, iar acesta se converteste ın baza q.

In cazul conversiei unui num˘ ar din baza p = 2 ın baza q = 2 r se poate evitatrecerea prin baza 10 procedˆ andu-se ın modul urm˘ ator: se formeaz˘a grupuri decate r cifre pornind de la ultima cifr˘ a din dreapta, ınspre stˆ anga. Fiecare grup der cifre va convertit ıntr-o cifr˘ a a bazei q.

Fie, spre exemplu: p = 2, q = 16 = p4 si x = (1011010) 2 .Se obtin urm˘atoarele grupuri de cˆ ate 4 cifre binare:

(1010)2 = A16 si (0101) 2 = 5 16 .

Deci scrierea num˘arului x ın baza 16 este: (5 A)16 .Se observa ca a fost completat˘a cu 0, spre st anga, cea mai din stˆanga grup˘a,

pan a la formarea grupei complete de 4 cifre binare.In cazul conversiei unui num˘ ar din baza p = 2 r ın baza q = 2 se poate de

asemenea evita trecerea prin baza 10 procedˆ andu-se ın modul urm˘ ator: ecare cifr˘adin reprezentarea ın baza p = 2 r se ınlocuieste cu r cifre binare care reprezint˘ ascrierea respectivei cifre ın baza 2.

Fie, spre exemplu: p = 16 = 2 4 , q = 2 si x = (3 A)16 .Se fac urmatoarele ınlocuiri de cifre:

3 →0011, A →1010.

Deci scrierea num˘arului x ın baza 2 este: (111010) 2 .Se observa ca nu apar cifrele 0 din stˆanga scrierii brute (00111010) 2 obtinute

prin ınlocuiri.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 19/518

Capitolul 2

Structuri de date

Inainte de a elabora un algoritm, trebuie s˘ a ne gandim la modul ın carereprezent˘am datele.

2.1 Date si structuri de date

2.1.1 Date

Datele sunt entit˘ at i purt˘atoare de informat¸ie.ˆIn informatic˘a, o dat˘ a este unmodel de reprezentare a informat iei, accesibil unui anumit procesor (om, unitate

central a, program), model cu care se poate opera pentru a obt ¸ine noi informat¸iidespre fenomenele, procesele si obiectele lumii reale. In functie de modul lor deorganizare, datele pot : elementare (simple) sau structurate.

Datele elementare au caracter atomic, ın sensul c˘ a nu pot descompuse ınalte date mai simple. Astfel de date sunt cele care iau ca valori numere sau siruri de caractere . O dat˘ a elementar˘ a apare ca o entitate indivizibil˘ a at at din punct devedere al informat¸iei pe care o reprezint˘ a cat si din punct de vedere al procesoruluicare o prelucreaz˘a.

O dat˘ a elementar˘ a poate privit˘a la nivel logic (la nivelul procesorului uman)sau la nivel zic (la nivelul calculatorului).

Din punct de vedere logic, o dat˘ a poate denit˘a ca un triplet de forma

(identif icator, atribute,valori ).

Din punct de vedere zic, o dat˘ a poate denit˘a ca o zon˘ a de memorie de oanumit˘a lungime, situat˘a la o anumit˘a adres˘ a absolut a, ın care sunt memorate ıntimp si ıntr-o form˘ a specica valorile datei.

7

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 20/518

8 CAPITOLUL 2. STRUCTURI DE DATE

Identicatorul este un simbol asociat datei pentru a o distinge de alte date sipentru a o putea referi ın cadrul programului.

Atributele sunt propriet˘ at ii ale datei si precizeaz˘a modul ın care aceasta va tratat˘ a ın cadrul procesului de prelucrare. Dintre atribute, cel mai important esteatributul de tip care denestete apartenent ¸a datei la o anumit˘ a clas˘ a de date .

O clas˘ a de date este denit˘a de natura si domeniul valorilor datelor care facparte din clasa respectiv˘ a, de operat iile specice care se pot efectua asupra datelorsi de modelul de reprezentare intern˘ a a datelor. Astfel, exist˘ a date de tip ıntreg ,de tip real , de tip logic, de tip sir de caractere , etc.

O mult ime de date care au aceleasi caracteristici se numeste tip de date .Evident, un tip de date este o clas˘ a de date cu acelasi mod de interpretare logic˘ asi reprezentare zic˘ a si se caracterizeaz˘ a prin valorile pe care le pot lua datele siprin operat iile care pot efectuate cu datele de tipul respectiv.

De exemplu, tipul ıntreg se caracterizeaz˘a prin faptul c˘a datele care ıi apart ¸inpot lua doar valori ıntregi, si asupra lor pot efectuate operat ¸ii aritmetice clasice(adunare, sc˘adere, ınmult ¸ire, ımp˘ art ire ın mult ¸imea numerelor ıntregi, comparat ¸ii).

Se poate considera c˘a datele organizate sub forma tablourilor unidimensionaleformeaz a tipul vector iar datele organizate sub forma tablourilor bidimensionaleformeaz a tipul matrice .

In funct ie de natura elementelor care o compun, o structur˘ a de date poate :

• omogen˘ a , atunci c and toate elementele au acelasi tip ;

• neomogen˘ a , atunci c and elementele componente au tipuri diferite .

In functie de num˘arul datelor care o compun, o structur˘ a de date poate :

• static˘ a , atunci c and num arul de componente este xat;

• dinamic˘ a , atunci c and num arul de componente este variabil.Din punct de vedere al modului ın care sunt utilizate datele pot :

• Constante . Valoarea lor nu este si nu poate modicat˘ a ın cadrulalgoritmului, ind xat˘ a de la ınceputul acestuia. O constant˘ a esteo dat a care p astreaz a aceeasi valoare pe tot parcursul procesului deprelucrare. Pentru constantele care nu au nume, ıns˘ asi valoarea loreste cea prin care se identic˘ a. Constante care au nume (identicator)sunt init ializate cu o valoare ın momentul declar˘ arii.

• Variabile . Valoarea lor poate modicat˘ a ın cadrul algoritmului.In momentrul declar˘ arii lor, variabilele pot init ializate (li se atribuieo valoare) sau pot neinit ializate (nu li se atribuie nici o valoare).

O variabil˘ a este o dat a care nu p astreaz˘a neap arat aceeasi valoare peparcursul procesului de prelucrare.

Tipul unei date trebuie s˘ a e precizat, ın cadrul programului de prelucrare,printr-o declarat ie de tip ce precede utilizarea respectivei constante sau variabile.

Valorile datei pot numere, sau valori de adev˘ ar, sau siruri de caractere, etc.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 21/518

2.1. DATE SI STRUCTURI DE DATE 9

2.1.2 Structuri de date

Datele apar frecvent sub forma unor colect ¸ii de date de diferite tipuri, menitesa faciliteze prelucrarea ın cadrul rezolv˘ arii unei anumite probleme concrete.

Datele structurate , numite uneori si structuri de date , sunt constituite din maimulte date elementare (uneori de acelasi tip, alteori de tipuri diferite), grupate cuun anumit scop si dup˘ a anumite reguli.

Exemple .1. Un sir nit de numere reale a1 , a 2 ,...,a n poate reprezentat ca o dat˘ a

structurat˘ a (tablou unidimensional sau vector ).2. O matrice

a1,1 a1,2 · · · a1,n

a2,1 a2,2 · · · a2,n

· · · · · ·. . . · · ·am, 1 am, 1 · · · am,n

poate reprezentat˘ a ca o dat a structurat˘ a (tablou bidimensional ) specicınd ecareelement prin doi indici (de linie si de coloan˘ a).

O structur˘ a de date este deci o colectie de date, eventual de tipuri diferite,pe care s-a denit o anumit˘ a organizare si c˘areia ıi este specic un anumit mod deidenticare a elementelor componente. Componetele unei structuri de date pot identicate prin nume sau prin ordinea pe care o ocup a ın cadrul structurii.

Daca accesul la o anumit˘a component˘a a structurii de date se poate face f˘ ar asa tinem seama de celelalte componente, vom spune c˘ a structura de date este cu

acces direct .ˆIn schimb, dac˘a accesul la o component˘a a structurii de date se poateface numai t in and cont de alte cˆampuri ale structurii (ın conformitate cu ordinea

structurii, printr-un proces de traversare) atunci vom spune c˘ a structura este cuacces secvent ial .

Structurile de date pot create pentru a depozitate ın memoria intern˘ a (aceste structuri de date se numesc structuri interne ) sau ın memoria extern˘ a (senumesc structuri externe , sau siere ). Structurile interne au un caracter de datetemporare (ele dispar odat˘a cu ıncetarea activit˘ at ii de prelucrare) iar cele externeau un caracter de date permanente (mai bine spus, de lung˘a durat˘a).

Daca pe lang a componentele structurii se ınregistreaz˘ a pe suport si alte datesuplimentare care s˘ a materializeze relat ¸ia de ordonare, atunci structura de daterespectiv˘a este explicit˘ a , ın caz contrar este implicit˘ a . De exemplu, structura dedate de tip tablou este o structur˘ a implicit˘ a de date iar structura de date de tiplist˘ a liniar˘ a este o structur˘ a explicit˘ a de date.

Asupra structurilor de date se pot efectua operat ¸ii care se refer a structurarespectiv a sau la valorile datelor componente. Cele mai importante operat ¸ii sunt:

− operat ia de creare , care const a ın memorarea pe suportul de memorie astructurii de date ın forma sa init ¸ial a,

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 22/518

10 CAPITOLUL 2. STRUCTURI DE DATE

− operat ia de consultare , care const a ın accesul la elementele structurii ınvederea prelucr˘arii valorilor acestora, si

− operat ia de actualizare , care const a ın ad˘ augarea de noi elemente, saueliminarea elementelor care nu mai sunt necesare, sau modicarea valorilor unorcomponente ale structurii.

Toate structurile de date la fel organizate si pe care s-au denit aceleasioperat ii , poart a numele de tip de structur˘ a de date . Daca analiz am ıns a operat iilecare se efectueaz a asupra unei structuri de date, vom putea vedea c˘ a toate acestease reduc la executarea, eventual repetat˘ a, a unui grup de operat ¸ii specice numiteoperat ii de baz˘ a .

2.2 Structuri si tipuri de date abstracte

2.2.1 Structuri de date abstracte

Abstractizarea datelor reprezint˘a de fapt concentrarea asupra esent ialului ,ignor and detaliile (sau altfel spus, conteaz˘ a ”ce” nu ”cum”).

St ap anirea aplicat¸iilor complexe se obt ine prin descompunerea ın module .Un modul trebuie s a e simplu, cu complexitatea ascuns˘ aın interiorul lui, si s˘ a

aib a o interfat a simpl a care s a permit˘a folosirea lui far a a cunoaste implementarea.O structur˘ a de date abstract˘ a este un modul const and din date si operat ii .

Datele sunt ascunse ın interiorul modulului si pot accesate prin intermediuloperat iilor. Structura de date este abstract˘ a deoarece este cunoscut˘ a numai interfat a structurii, nu si implementarea (operat iile sunt date explicit, valorile sunt deniteimplicit, prin intermediul operat ¸iilor).

2.2.2 Tipuri de date abstracte

Procesul de abstractizare se refera la dou a aspecte:

• abstractizarea procedural˘ a , care separ a propriet˘at ile logice ale unei act iuni dedetaliile implement˘ arii acesteia

• abstractizarea datelor , care separ a propriet˘at ile logice ale datelor de detaliile

reprezent˘arii lorO structur˘ a de date abstracte are un singur exemplar (o singur a instant ˘ a ).

Pentru a crea mai multe exemplare ale structurii de date abstracte se deneste untip de date abstract . In Java, de exemplu, clasa asigur a un mod direct de denirea oricarui tip de date abstract .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 23/518

2.3. STRUCTURI DE DATE ELEMENTARE 11

2.3 Structuri de date elementare

2.3.1 Liste

O list˘ a este o colect ie de elemente de informat ie (noduri) aranjate ıntr-oanumit˘a ordine. Lungimea unei liste este num˘arul de noduri din list˘a. Structuracorespunzatoare de date trebuie s˘ a ne permit˘a sa determin˘am ecient care esteprimul/ultimul nod ın structur˘ a si care este predecesorul/succesorul unui nod dat(dac a exist a). Iat a cum arat˘a cea mai simpl a list a, lista liniar˘ a :

capullistei

coadalistei

Figura 2.1: List˘a liniar a

O list˘ a circular˘ a este o list a ın care, dup˘a ultimul nod , urmeaz a primul nod ,deci ecare nod are succesor si predecesor .

Cateva dintre operat iile care se efectueaz a asupra listelor sunt: inserarea (ad augarea) unui nod, extragerea (stergerea) unui nod, concatenarea unor liste,num ararea elementelor unei liste etc.

Implementarea unei liste se realizeaz˘ a ın dou˘a moduri: secvent ial si ın ant uit .Implementarea secvential˘ a se caracterizeaz˘a prin plasarea nodurilor ın locat ¸ii

succesive de memorie, ın conformitate cu ordinea lor ın list˘ a. Avantajele acestuimod de implementare sunt accesul rapid la predecesorul/succesorul unui nod sig˘ asirea rapid a a primului/ultimului nod. Dezavantajele sunt modalit˘ at ile relativcomplicate de inserarea/stergere a unui nod si faptul c˘a, ın general, nu se folosesteıntreaga memorie alocat˘ a listei.

Implementarea ınl˘ ant uit˘ a se caracterizeaz˘a prin faptul c˘a ecare nod cont inedoua part i: informat ia propriu-zis a si adresa nodului succesor. Alocarea memorieipentru ecare nod se poate face ın mod dinamic, ın timpul rul˘ arii programului.Accesul la un nod necesit˘a parcurgerea tuturor predecesorilor s˘ ai, ceea ce conducela un consum mai mare de timp pentru aceast˘ a operat ie. In schimb, operat¸iilede inserare/stergere sunt foarte rapide. Se consum˘ a exact atˆat spat iu de memoriecat este necesar dar, evident, apare un consum suplimentar de memorie pentruınregistrarea leg˘ aturii c atre nodul succesor. Se pot folosi dou˘ a adrese ın loc deuna, astfel ıncˆ at un nod s a contin a pe lang a adresa nodului succesor si adresanodului predecesor. Obt ¸inem astfel o list˘ a dublu inl˘ ant uit˘ a , care poate traversat˘ aın ambele direct ¸ii.

Listele ınl˘ant uite pot reprezentate prin tablouri. In acest caz, adreselenodurilor sunt de fapt indici ai tabloului.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 24/518

12 CAPITOLUL 2. STRUCTURI DE DATE

O alternativ˘ a este s a folosim doua tablouri val si next astfel: s a memor aminformat ia ecarui nod i ın locat ia val [i], iar adresa nodului s˘au succesor ın locat ¸ianext [i]. Indicele locat iei primului nod este memorat ın variabila p. Vom conveni ca,pentru cazul listei vide, s˘ a avem p = 0 si next [u] = 0 unde u reprezint˘a ultimul noddin list a. Atunci, val [ p] va contine informat¸ia primului nod al listei, next [ p] adresacelui de-al doilea nod, val [next [ p]] informatia din al doilea nod, next [next [ p]]adresa celui de-al treilea nod, etc. Acest mod de reprezentare este simplu darapare problema gestion˘ arii locat iilor libere. O solut¸ie este s a reprezent˘am locat iilelibere tot sub forma unei liste ınlant ¸uite. Atunci, stergerea unui nod din listainitial a implic a inserarea sa ın lista cu locat ¸ii libere, iar inserarea unui nod ın listainitial a implic a stergerea sa din lista cu locat ¸ii libere. Pentru implementarea listeide locat ii libere, putem folosi aceleasi tablouri dar avem nevoie de o alt˘ a variabil a,freehead , care sa contin a indicele primei locat ii libere din val si next . Folosimaceleasi convent¸ii: dac a freehead = 0 ınseamn˘ a ca nu mai avem locat¸ii libere, iarnext [ul ] = 0 unde ul reprezint˘a ultima locat¸ie liber a.

Vom descrie in continuare dou˘ a tipuri de liste particulare foarte des folosite.

2.3.2 Stive si cozi

O stiv˘ a este o list a liniar a cu proprietatea c˘ a operat iile de inserare/extragerea nodurilor se fac ın/din coada listei. Dac˘ a nodurile A, B, C sunt inserate ıntr-ostiv a ın aceast˘ a ordine, atunci primul nod care poate sters/extras este C. In modechivalent, spunem c˘a ultimul nod inserat este singurul care poate sters/extras.Din acest motiv, stivele se mai numesc si liste LIFO (Last In F irst O ut).

Cel mai natural mod de reprezentare pentru o stiv˘ a este implementarea

secvent ial a ıntr-un tablou S [1..n ], unde n este num arul maxim de noduri. Primulnod va memorat ın S [1], al doilea ın S [2], iar ultimul ın S [top], unde top esteo variabil a care cont ine adresa (indicele) ultimului nod inserat. Init ¸ial, c and stivaeste vid a, avem (prin convent ¸ie) top = 0.

O coad˘ a este o list a liniar a ın care inser˘arile se fac doar ın capul listei, iarstergerile/extragerile se fac doar din coada listei. Din acest motiv, cozile se mainumesc si liste FIFO (F irst In F irst O ut).

O reprezentare secvent ¸ial a pentru o coad˘a se obtine prin utilizarea unuitablou C [0..n −1], pe care ıl trat˘ am ca si cum ar circular: dup˘ a locat ia C [n −1]urmeaz a locat ia C [0]. Fie tail variabila care cont¸ine indicele locat iei predecesoareprimei locat ii ocupate si e head variabila care cont¸ine indicele locat iei ocupateultima oar˘a. Variabilele head si tail au aceeasi valoare atunci si numai atunci cˆ andcoada este vid a. Init ial, avem head = tail = 0.

Trebuie s˘a observ am faptul c a testul de coad˘a vid a este acelasi cu testul decoada plin a. Dac a am folosi toate cele n locat ii la un moment dat, atunci nu amputea distinge ıntre situat ¸ia de ”coad˘a plin a” si cea de ”coad˘a vida”, deoarece ınambele situat¸ii am avea head = tail . In consecint a, vom folosi efectiv, ın oricemoment, cel mult n −1 locatii din cele n ale tabloului C .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 25/518

2.3. STRUCTURI DE DATE ELEMENTARE 13

2.3.3 Grafuri

Un graf este o pereche G = < V, M > , unde V este o mult ime de varfuri , iarM ⊆V ×V este o mult ime de muchii . O muchie de la varful a la varful b estenotat˘a cu perechea ordonat˘ a ( a, b), dac a graful este orientat , si cu multimea a, b,dac a graful este neorientat .

Doua varfuri unite printr-o muchie se numesc adiacente . Un varf care esteextremitatea unei singure muchii se numeste varf terminal .

Un drum este o succesiune de muchii de forma

(a1 , a 2), (a2 , a 3),..., (an −1 , a n )

sau de forma

a

1, a

2,

a

2, a

3, ...,

an

−1, a n

dup a cum graful este orientat sau neorientat . Lungimea drumului este egal a cunum arul muchiilor care ıl constituie. Un drum simplu este un drum ın care nici unvarf nu se repet˘a. Un ciclu este un drum care este simplu , cu exceptia primului siultimului vˆarf, care coincid. Un graf aciclic este un graf f ar a cicluri.

Un graf neorientat este conex , daca ıntre oricare dou˘ a varfuri exist˘a un drum .Pentru grafuri orientate, aceast˘ a notiune este ınt˘ arit a: un graf orientat este tareconex , dac a ıntre oricare dou˘ a varfuri i si j exist a un drum de la i la j si un drum de la j la i.

Varfurilor unui graf li se pot atasa informat ii (numite valori ), iar muchiilorli se pot atasa informat ii numite uneori lungimi sau costuri .

Exist a cel put in trei moduri de reprezentare ale unui graf:

• Printr-o matrice de adiacent ˘ a A, ın care A[i, j ] = true daca varfurile i si jsunt adiacente , iar A[i, j ] = false ın caz contrar. O alt˘ a variant˘a este sa-i dam luiA[i, j ] valoarea lungimii muchiei dintre vˆ arfurile i si j , considerand A[i, j ] = + ∞atunci c and cele dou a varfuri nu sunt adiacente. Cu aceast˘ a reprezentare, putemverica usor dac˘a dou a varfuri sunt adiacente. Pe de alt˘ a parte, dac˘a dorim s aaam toate vˆarfurile adiacente unui vˆ arf dat, trebuie s˘ a analiz am o ıntreag˘ a liniedin matrice. Aceasta necesit˘ a n operat ii (unde n este num arul de v arfuri ın graf),independent de num˘ arul de muchii care conecteaz˘ a varful respectiv.

•Prin liste de adiacent ˘ a , adica prin atasarea la ecare vˆ arf i a listei de v arfuriadiacente (pentru grafuri orientate, este necesar ca muchia s˘ a plece din i). Intr-un graf cu m muchii, suma lungimilor listelor de adiacent˘ a este 2m, dac a grafuleste neorientat , respectiv m, dac a graful este orientat . Daca num arul muchiilor ıngraf este mic, aceast˘a reprezentare este preferabil˘ a din punct de vedere al memorieinecesare. Totusi, pentru a determina dac˘ a dou a varfuri i si j sunt adiacente, trebuiesa analiz am lista de adiacent˘ a a lui i (si, posibil, lista de adiacent˘ a a lui j ), ceea ceeste mai put in ecient decˆat consultarea unei valori logice ın matricea de adiacent ¸a.

• Printr-o list˘ a de muchii . Aceast a reprezentare este ecient˘ a atunci c andavem de examinat toate muchiile grafului.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 26/518

14 CAPITOLUL 2. STRUCTURI DE DATE

2.3.4 Arbori binari

Un arbore este un graf neorientat, aciclic si conex. Sau, echivalent, un arboreeste un graf neorientat ın care exist˘ a exact un drum ıntre oricare dou˘ a varfuri.

Un arbore reprezentat pe niveluri se numeste arbore cu r˘ ad˘ acin˘ a . Varfulplasat pe nivelul 0 se numeste r˘ ad˘ acina arborelui . Pe ecare nivel i > 0 suntplasate v arfurile pentru care lungimea drumurilor care le leag˘ a de r ad acina este i.

Varfurile de pe un nivel i > 0 legate de acelasi vˆarf j de pe nivelul i −1 senumesc descendent ii direct i (ii) varfului j iar varful j se numeste ascendent direct (tat˘ a) al acestor v arfuri.

Daca exist a un drum de la un vˆarf i de pe nivelul ni la un v arf j de pe nivelulnj > ni , atunci v arful i se numeste ascendent al lui j , iar v arful j se numestedescendent al lui i.

Un varf terminal (sau frunz˘ a ) este un v arf far a descendent i. V arfurile carenu sunt terminale se numesc neterminale .Un arbore ın care orice vˆ arf are cel mult doi descendent ¸i se numeste arbore

binar .Intr-un arbore cu r˘ ad acin a (reprezentat pe niveluri), adancimea unui v arf

este lungimea drumului dintre r˘ ad acin a si acest v arf iar ın alt ¸imea unui v arf estelungimea celui mai lung drum dintre acest vˆ arf si un v arf terminal.

In˘ alt ¸imea arborelui este ın˘alt imea r ad acinii.Intr-un arbore binar, num˘ arul maxim de vˆarfuri aate pe nivelul k este 2k .

Un arbore binar de ın˘ altime k are cel mult 2 k +1 −1 varfuri, iar dac˘a are exact2k+1 −1 varfuri, se numeste arbore plin .

Varfurile unui arbore plin se numeroteaza ın ordinea nivelurilor. Pentru acelasinivel, numerotarea se face ın arbore de la stˆ anga la dreapta.

nivelul 0

nivelul 1

nivelul 2

nivelul 3

1

2 3

4 5 6 7

8 9 10 11 12 13 14 15

Figura 2.2: Arbore binar plin

Un arbore binar cu n varfuri si de ın˘ altime k este complet , dac a se obtinedin arborele binar plin de ın˘ altime k, prin eliminarea, dac˘a este cazul, a v arfurilornumerotate cu n + 1, n + 2, ..., 2 k+1 −1.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 27/518

2.3. STRUCTURI DE DATE ELEMENTARE 15

Acest tip de arbore se poate reprezenta secvent ¸ial folosind un tablou T ,pun and v arfurile de ad ancime k, de la st anga la dreapta, ın pozit ¸iile T [2k ], T [2k +1],..., T [2k+1 −1] (cu posibila except ie a ultimului nivel care poate incomplet).

nivelul 0

nivelul 1

nivelul 2

nivelul 3

1

2 3

4 5 6 7

8 9 10 11 12

Figura 2.3: Arbore binar complet

Tat˘al unui v arf reprezentat ın T [i], i > 0, se aa ın T [i/ 2]. Fiii unui v arf reprezentat ın T [i] se aa, dac a exist a, ın T [2i] si T [2i + 1].

2.3.5 Heap-uri

Un max-heap (heap=”gramad˘ a ordonat˘a”, ın traducere aproximativ˘ a) esteun arbore binar complet, cu urm˘ atoarea proprietate: valoarea ecarui vˆ arf estemai mare sau egal˘a cu valoarea ec arui u al s au.

Un min-heap este un arbore binar complet ın care valoarea ecarui vˆ arf estemai mic a sau egal a cu valoarea ec arui u al s au.

nivelul 0

nivelul 1

nivelul 2

nivelul 3

2

34 56

7 9

10

11

7

7

7

Figura 2.4: Max-heap

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 28/518

16 CAPITOLUL 2. STRUCTURI DE DATE

Acelasi heap poate reprezentat secvent ¸ial prin urm˘atorul tablou:

11 7 10 7 7 9 2 4 6 5 7 3

Caracteristica de baz˘ a a acestei structuri de date este c˘ a modicarea valoriiunui v arf se face foarte ecient, p˘astr andu-se proprietatea de heap.

De exemplu, ıntr-un max-heap, dac˘ a valoarea unui vˆarf creste, astfel ıncˆ atdep aseste valoarea tat˘ alui, este sucient s˘a schimb am ıntre ele aceste dou˘ a valorisi sa continu˘am procedeul ın mod ascendent, pˆ an a cand proprietatea de heap esterestabilit˘a. Dac a, dimpotriv˘a, valoarea vˆarfului scade, astfel ıncˆ at devine mai mic˘adecat valoarea cel put¸in a unui u, este sucient s˘ a schimb am intre ele valoareamodicat˘a cu cea mai mare valoare a iilor, apoi s˘ a continu˘am procesul ın moddescendent, pan˘ a cand proprietatea de heap este restabilit˘ a.

Heap-ul este structura de date ideal˘ a pentru extragerea maximului/minimului

dintr-o mult¸ime, pentru inserarea unui vˆ arf, pentru modicarea valorii unui vˆ arf.Sunt exact operat ¸iile de care avem nevoie pentru a implementa o list˘ a dinamic˘ a de priorit˘ at i : valoarea unui vˆarf va da prioritatea evenimentului corespunzator.

Evenimentul cu prioritatea cea mai mare/mic˘ a se va aa mereu la radacinaheap-ului, iar prioritatea unui eveniment poate modicat˘ a ın mod dinamic.

2.3.6 Structuri de mult ¸imi disjuncte

Sa presupunem c˘a avem N elemente, numerotate de la 1 la N . Numerele careidentic a elementele pot , de exemplu, indici intr-un tablou unde sunt memoratevalorile elementelor. Fie o partitie a acestor N elemente, format˘a din submult¸imidoua cate dou a disjuncte: S 1, S 2, ... . Presupunem c˘a ne intereseaz˘a reuniunea adoua submult imi, S i∪S j .

Deoarece submult¸imile sunt dou˘a cate dou a disjuncte, putem alege ca etichet˘ apentru o submult ¸ime oricare element al ei. Vom conveni ca elementul minim al uneimult imi s a e eticheta mult¸imii respective. Astfel, multimea 3, 5, 2, 8va numit a”multimea 2”.

Vom aloca tabloul set [1..N ], ın care ec arei locatii set [i] i se atribuie etichetasubmult imii care cont ine elementul i. Avem atunci proprietatea: set [i] ≤ i, pentru1 ≤ i ≤N . Reuniunea submult ¸imilor etichetate cu a si b se poate realiza astfel:

procedure reuniune (a, b)i ←a; j ←bif i > j

then interschimb˘a i si jfor k ←j to N do

if set [k] = jthen set [k] ←i

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 29/518

Capitolul 3

Algoritmi

3.1 Etape ın rezolvarea problemelor

Principalele etape care se parcurg ın rezolvarea unei probleme sunt:

(a) Stabilirea datelor initiale si a obiectivului (ce trebuie determinat).(b) Alegerea metodei de rezolvare.(c) Aplicarea metodei pentru date concrete.

Exemplu.Sa presupunem c˘a problema este rezolvarea, ın R , a ecuat iei x2 −3x + 2 = 0.

(a) Datele init iale sunt reprezentate de c˘ atre coecient ii ecuat iei iarobiectivul este determinarea r˘ ad acinilor reale ale ecuat¸iei.(b) Vom folosi metoda de rezolvare a ecuat¸iei de gradul al doilea avˆandforma general a ax 2 + bx + c = 0. Aceast˘a metod a poate descris˘ a astfel:Pasul 1. Se calculeaz˘a discriminantul: ∆ = b2 −4ac.Pasul 2. Dac˘a ∆ > 0

atunci ecuat ia are dou˘a r ad acini reale distincte: x1,2 = −b±√∆2a

altfel , dac˘a ∆ = 0atunci ecuat ia are o r ad acina real a dubl a: x1,2 = −b

2a

altfel ecuat ia nu are r˘adacini reale.(c) Aplicarea metodei pentru datele problemei ( a = 1 , b = −3, c = 2)conduce la rezultatul: x1 = 1, x2 = 2.

17

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 30/518

18 CAPITOLUL 3. ALGORITMI

3.2 Algoritmi

3.2.1 Ce este un algoritm?Un algoritm este o succesiune de operat ii aritmetice si/sau logice care,aplicate asupra unor date , permit obt inerea rezultatului unei problemedin clasa celor pentru care a fost conceput.

Sa observ am ca nu apare ın denit ¸ie cuv antul ”calculator”; algoritmii nu auneap arat leg atur˘a cu calculatorul. Totusi, ın acest curs ne vom concentra aproapeexclusiv pe algoritmi care pot implementat ¸i rezonabil pe calculator. Altfel spus,ecare pas din algoritm trebuie astfel gˆ andit ıncˆ at ori este suportat direct de c˘ atre

limbajul de programare favorit (operat ¸ii aritmetice, cicluri, recursivitate, etc) orieste asem anator cu ceva ınv˘ atat mai ınainte (sortare, c˘ autare binar˘ a, parcurgereın adˆancime, etc).

Secvent a de pasi prin care este descris˘ a metoda de rezolvare a ecuat ¸iei degradul al doilea (prezentat˘ a ın sect¸iunea anterioar˘ a) este un exemplu de algoritm.Calculul efectuat la Pasul 1 este un exemplu de operat ¸ie aritmetic˘a, iar analizasemnului discriminantului (Pasul 2) este un exemplu de operat ¸ie logica.

Descrierea unui algoritm presupune precizarea datelor initiale si descrierea prelucr˘ arilor efectuate asupra acestora. Astfel, se poate spune c˘ a:

algoritm = date + prelucr˘ ari

Al-Khwarizmi a fost cel care a folosit pentru prima dat˘ a reguli precise si clarepentru a descrie procese de calcul (operat¸ii aritmetice fundamentale) ın lucrareasa ”Scurt˘a carte despre calcul algebric”. Mai tˆ arziu, aceast˘a descriere apare subdenumirea de algoritm ın ”Elementele lui Euclid”. Algoritmul lui Euclid pentrucalculul celui mai mare divizor comun a dou˘ a numere naturale este, se pare, primulalgoritm cunoscut ın matematic˘ a.

In matematic˘a notiunea de algoritm a primit mai multe denit ¸ii: algoritmulnormal al lui A. A. Markov, algoritmul operat ¸ional al lui A. A. Leapunov, masinaTuring, funct¸ii recursive, sisteme POST. S-a demonstrat c˘ a aceste denit ii suntechivalente din punct de vedere matematic.

In informatic˘a exist a de asemenea mai multe denit ¸ii pentru not¸iunea dealgoritm . De exemplu, ın [35] not iunea de algoritm se deneste astfel:

Un algoritm este sistemul virtual

A = ( M,V,P,R,Di,De,Mi,Me )constituit din urm˘ atoarele elemente:

M - memorie intern˘ a format a din locat ii de memorie si utilizat˘a pentrustocarea temporar˘ a a valorilor variabilelor;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 31/518

3.2. ALGORITMI 19

V - multime de variabile denite ın conformitate cu rat ionamentul R,care utilizeaz˘a memoria M pentru stocarea valorilor din V ;

P - proces de calcul reprezentat de o colect ¸ie de instruct¸iuni/comenziexprimate ıntr-un limbaj de reprezentare (de exemplu, limbajulpseudocod); folosind memoria virtual˘ a M si mult imea de variabileV , instruct iunile implementeaz˘ a/codic˘a tehnicile si metodele careconstituie rat ionamentul R; executia instruct¸iunilor procesului decalcul determin˘a o dinamic a a valorilor variabilelor; dup˘ a execut iatuturor instruct ¸iunilor din P , solutia problemei se a˘a ın anumitelocat ii de memorie corespunz˘atoare datelelor de iesire De ;

R - rat ionament de rezolvare exprimat prin diverse tehnici si metodespecice domeniului din care face parte clasa de probleme supuserezolvarii (matematic˘ a, zica, chimie etc.), care ımbinate cu tehnici

de programare corespunz˘ atoare realizeaz˘a actiuni/procese logice,utiliz and memoria virtual˘ a M si mult imea de variabile V ;

Di - date de intrare care reprezint˘a valori ale unor parametri carecaracterizeaz˘a ipotezele de lucru/st˘ arile init iale ale problemei sicare sunt stocate ın memoria M prin intermediul instruct ¸iunilorde citire/intrare care utilizeaz˘ a mediul de intrare Mi ;

De - date de iesire care reprezint˘a valori ale unor parametri carecaracterizeaz˘a solut ia problemei/st˘ arile nale; valorile datelor deiesire sunt obt¸inute din valorile unor variabile generate de execut ¸iainstruct¸iunilor din procesul de calcul P , sunt stocate ın memoria M ,si ınregistrate pe un suport virtual prin intermediul instruct ¸iunilorde scriere/iesire care utilizeaz˘ a mediul de iesire Me; ;

Mi - mediu de intrare care este un dispozitiv virtual de intrare/citirepentru preluarea valorilor datelor de intrare si stocarea acestora ınmemoria virtual˘ a M ;

Me - mediu de iesire care este un dispozitiv virtual de iesire/scrierepentru preluarea datelor din memoria virtual˘ a M si ınregistrareaacestora pe un suport virtual (ecran, hˆ artie, disc magnetic, etc.).

Un limbaj este un mijloc de transmitere a informat ¸iei.Exist a mai multe tipuri de limbaje: limbaje naturale (engleza, rom an a, etc),

limbaje stiint ice (de exemplu limbajul matematic), limbaje algoritmice, limbajede programare (de exemplu Pascal, C, Java), etc.

Un limbaj de programare este un limbaj articial, riguros ıntocmit,care permite descrierea algoritmilor astfel ıncˆat s a poat a transmisicalculatorului cu scopul ca acesta s˘ a efectueze operat¸iile specicate.

Un program este un algoritm tradus ıntr-un limbaj de programare .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 32/518

20 CAPITOLUL 3. ALGORITMI

3.2.2 Proprietat ¸ile algoritmilor

Principalele propriet˘ at i pe care trebuie s˘a le aiba un algoritm sunt:

• Generalitate . Un algoritm trebuie s˘a poat a utilizat pentru o clas˘ a ıntreag˘ a de probleme, nu numai pentru o problem˘ a particular˘a. Dinaceast a cauz a, o metod a de rezolvare a unei ecuat¸ii particulare nu poate considerat˘a algoritm .

• Finitudine . Orice algoritm trebuie s˘ a permit˘a obtinerea rezultatuluidup a un num˘ ar nit de prelucr ari (pasi). Din aceast˘ a cauz a, o metod acare nu asigur˘a obtinerea rezultatului dup˘ a un num ar nit de pasi nupoate considerat˘a algoritm .

• Determinism . Un algoritm trebuie s˘ a prevad a, far a ambiguit˘ati si

far a neclarit˘at i, modul de solut¸ionare a tuturor situat ¸iilor care pot s˘aapar a ın rezolvarea problemei. Dac˘ a ın cadrul algoritmului nu intervinelemente aleatoare, atunci ori de cˆ ate ori se aplic a algoritmul aceluiasiset de date de intrare trebuie s˘ a se obtin a acelasi rezultat.

3.2.3 Tipuri de prelucrariPrelucr˘arile care intervin ıntr-un algoritm pot simple sau structurate .

• Prelucr˘ arile simple sunt atribuiri de valori variabilelor, eventual prinevaluarea unor expresii;

• Prelucr˘ arile structurate pot de unul dintre tipurile:

−Liniare . Sunt secvent e de prelucr˘ari simple sau structuratecare sunt efectuate ın ordinea ın care sunt specicate;

−Alternative . Sunt prelucr˘ari caracterizate prin faptul c˘ a ınfunct ie de realizarea sau nerealizarea unei condit ¸ii se alegeuna din dou˘a sau mai multe variante de prelucrare;

− Repetitive . Sunt prelucr˘ari caracterizate prin faptul c˘ aaceeasi prelucrare (simpl˘ a sau structurat a) este repetat˘ a cattimp este ındeplinit˘ a o anumit˘a condit ie.

3.3 Descrierea algoritmilor

Algoritmii nu sunt programe , deci ei nu trebuie specicat¸i ıntr-un limbaj deprogramare. Detaliile sintactice, de exemplu din Pascal, C/C++ sau Java, nu aunici o important¸ a ın elaborarea/proiectarea algoritmilor.

Pe de alt a parte, descrierea ın limba romˆ an a (ca si ın limba englez˘ a [15]) ınmod uzual nu este o idee mai bun˘ a. Algoritmii au o serie de structuri - ın special

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 33/518

3.3. DESCRIEREA ALGORITMILOR 21

condit ionale, repetitive, si recursivitatea - care sunt departe de a putea descriseprea usor ın limbaj natural . La fel ca orice limba vorbit a, limba rom ana este plin˘ade ambiguit˘ati, subınt ¸elesuri si nuant ¸e de semnicat ie, iar algoritmii trebuie s˘ a edescrisi cu o acuratet ¸e maxim posibil˘a.

Cea mai bun˘a metod a de a descrie un algoritm este utilizarea limbajului pseudocod . Acesta foloseste structuri ale limbajelor de programare si matematiciipentru a descompune algoritmul ın pasi elementari (propozit ii simple), dar carepot scrise folosind matematica, romˆ ana curat˘a, sau un amestec al celor dou˘ a.

Modul exact de structurare a pseudocodului este o alegere personal˘ a.O descriere foarte bun˘a a algoritmului arat˘ a structura intern˘ a a acestuia,

ascunde detaliile care nu sunt semnicative, si poate implementat˘ a usor decatre orice programator competent ın orice limbaj de programare, chiar dac˘ a elnu ınt¸elege ce face acel algoritm. Un pseudocod bun, la fel ca si un cod bun, facealgoritmul mult mai usor de ınt ¸eles si analizat; el permite de asemenea, mult maiusor, descoperirea greselilor.

Pe de alt a parte, proba clar˘ a se poate face numai pe baza unui programcare s a dea rezultatele corecte! Oamenii sunt oameni! Cineva poate s˘ a insiste c aalgoritmul lui este bun desi ... nu este! Si atunci ... program˘ am!

3.3.1 Limbaj natural

Exemple .1. Algoritmul lui Euclid . Permite determinarea celui mai mare divizor comun

(cmmdc) a dou˘a numere naturale a si b. Metoda de determinare a cmmdc poate descrisa ın limbaj natural dup a cum urmeaz˘a.

Se ımparte a la b si se ret ine restul r . Se consider a ca nou deımp˘art it vechiulımp˘art itor si ca nou ımpart ¸itor restul obt ¸inut la ımp˘ art irea anterioar˘ a. Operat iade ımp˘art ire continu˘a pan a se obtine un rest nul. Ultimul rest nenul (care a fostsi ultimul ımp˘ art itor) reprezint˘ a rezultatul.

Se observa ca metoda descris˘a ındeplineste propriet˘ at ile unui algoritm: poate aplicat a oricarei perechi de numere naturale iar num˘ arul de prelucr˘ari este nit(dup a un num ar nit de ımp˘art iri se ajunge la un rest nul).

De asemenea se observ˘a ca prelucrarea principal˘ a a algoritmului este unarepetitiv˘a, condit ia utilizat˘a pentru a analiza dac˘ a s-a terminat prelucrarea indegalitatea cu zero a restului.

2. Schema lui Horner . Permite determinarea cˆ atului si restuluiımp˘ art irii unuipolinom P [X ] = an X n + an −1X n −1 + ... + a1X + a0 = 0 la un binom de formaX

−b.O modalitate simpl˘ a de a descrie metoda de rezolvare este schema urm˘ atoare:

an an −1 ... ak ... a2 a1 a0b an bcn −1 + an −1 ... bck + ak ... bc2 + a2 bc1 + a1 bc0 + a0

⇓ ⇓ ... ⇓ ... ⇓ ⇓ ⇓cn −1 cn −2 ... ck−1 ... c1 c0 P [b]

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 34/518

22 CAPITOLUL 3. ALGORITMI

Valorile cn −1 , cn −2 ,...,c 1 , c0 reprezint˘a coecientii catului, iar ultima valoarecalculat a reprezint˘a valoarea restului (valoarea polinomului calculat˘ a ın b).

Siın acest caz prelucrarea principal˘ a este una repetitiv˘ a const and ın evaluareaexpresiei bck + ak pentru k luand, ın aceast˘ a ordine, valorile n −1, n −2, ..., 2, 1, 0.

3.3.2 Scheme logice

Scrierea unui program pornind de la un algoritm descris ıntr-un limbaj maimult sau mai put¸in riguros, ca ın exemplele de mai sus, este dicil˘ a ıntrucˆat nusunt pusi ın evident ¸ a foarte clar pasii algoritmului.

Modalit at i intermediare de descriere a algoritmilor, ıntre limbajul naturalsau cel matematic si un limbaj de programare, sunt schemele logice si limbajelealgoritmice .

Schemele logice sunt descrieri grace ale algoritmilor ın care ec˘ aruipas i se ataseaz˘a un simbol grac, numit bloc, iar modul de ınl˘ant uirea blocurilor este specicat prin segmente orientate.

Schemele logice au avantajul c˘ a sunt sugestive dar si dezavantajul c˘ a potdeveni dicil de urm˘arit ın cazul unor prelucr˘ ari prea complexe. Acest dezavantaj,dar si evolut¸ia modului de concepere a programelor, fac ca schemele logice s˘ a edin ce ın ce mai put¸in folosite (ın favoarea limbajelor algoritmice).

3.3.3 Pseudocod

Un limbaj algoritmic este o notat ie care permite exprimarea logicii algorit-milor ıntr-un mod formalizat f˘ ar a a necesare reguli de sintax˘a riguroase, ca ıncazul limbajelor de programare.

Un limbaj algoritmic mai este denumit si pseudocod . Un algoritm descrisın pseudocod cont ¸ine atˆat enunt¸uri care descriu operat ¸ii ce pot traduse directıntr-un limbaj de programare (unui enunt ¸ ın limbaj algoritmic ıi corespunde oinstruct¸iune ın program) cˆ at si enunt¸uri ce descriu prelucr˘ ari ce urmeaz a a detaliate abia ın momentul scrierii programului.

Nu exist a un anumit standard ın elaborarea limbajelor algoritmice, ecareprogramator putˆ and s a conceap a propriul pseudocod, cu condit ¸ia ca acesta s˘apermit˘a o descriere clar a si neambigu˘a a algoritmilor. Se poate folosi sintaxa lim-bajului de programare preferat, ın care apar enunt ¸uri de prelucr˘ari. De exemplu:

for ecare v arf v din V

culoare[v] = alb;distanta[v] = innit;predecesor[v]=-1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 35/518

3.4. LIMBAJ ALGORITMIC 23

3.4 Limbaj algoritmic

In continuare prezent˘ am un exemplu de limbaj algoritmic.

3.4.1 Declararea datelor

Datele simple se declar a sub forma:

< tip > < nume > ;

unde < tip > poate lua una dintre valorile: byte , short , int , long , oat , double ,boolean , char .

Tablourile unidimensionale se declar˘ a sub forma:< tip > < nume > [n1 ..n2];

Elementele vectorului pot accesate cu ajutorul unui indice, care poate luavalori ıntre n1 si n2 , sub forma:

< nume > [i]

unde i poate lua orice valoare ıntre n1 si n2 .In cazul tablourilor bidimensionale, o declarat ¸ie de forma:

< tip > < nume > [m1 ..m2][n1 ..n2];

specica o matrice cu m2 −m1 + 1 linii si n2 −n1 + 1 coloane. Fiecare element sespecica prin doi indici:

< nume > [i][j]

unde i reprezint˘a indicele liniei si poate avea orice valoare ıntre m1 si m2 iar jreprezint˘a indicele coloanei si poate avea orice valoare ıntre n1 si n2 .

3.4.2 Operat ¸ii de intrare/iesire

Preluarea valorilor pentru datele de intrare este descris˘ a sub forma:

read v1 , v2 , ...;unde v1 , v2 , ... sunt nume de variabile.

Asarea rezultatelor este descris˘ a sub forma:

write e1 , e2 , ...;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 36/518

24 CAPITOLUL 3. ALGORITMI

unde e1 , e2 , ... sunt expresii (ın particular pot constante sau variabile).Operat ¸ia de atribuire . Operat ia de atribuire a unei valori c˘ atre o variabil˘a

se descrie prin:

v = < expresie > ;

unde v este un nume de variabil˘ a, < expresie > desemneaz a o expresie aritmetic˘asau logica, iar ”=” este operatorul de atribuire . Pentru acesta din urm˘ a pot folosite si alte simboluri, ca de exemplu ”:=” sau ” ←”. Expresiile pot descriseconform regulilor utilizate ın matematic˘ a.

3.4.3 Prelucrari liniare

O secvent a de prelucr ari se descrie ın modul urm˘ ator:

< prel 1> ;< prel 2> ;

...< prel n> ;

sau

< prel 1> ; < prel 2> ; ... < prel n> ;

O astfel de scriere indic˘a faptul c a ın momentul execut ¸iei prelucr arile seefectueaz a ın ordinea ın care sunt specicate.

3.4.4 Prelucrari alternative

O prelucrare alternativ˘ a complet˘ a (cu dou a ramuri) este descris˘ a prin:

if < condit ie> < prel 1> else < prel 2> ;

sau sub forma

if < condit ie> then < prel 1> else < prel 2> ;

unde < condit ie> este o expresie relat ional˘ a . Aceast a prelucrare trebuie ınt ¸eleas aın modul urm˘ ator: dac˘a condit ia este adev˘ arat˘ a atunci se efectueaz˘a prelucrarea< prel 1> , altfel se efectueaz a < prel 2> .

O prelucrare alternativ˘ a cu o singur˘ a ramur˘ a se descrie prin:

if < condit ie> < prel> ;

sau

if < condit ie> then < prel> ;

iar execut ia ei are urm˘atorul efect: dac˘ a condit ia este satisfacut˘ a atunci se efectueaz˘aprelucrarea specicat˘ a, altfel nu se efectueaz a nici o prelucrare ci se trece laurm atoarea prelucrare a algoritmului.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 37/518

3.4. LIMBAJ ALGORITMIC 25

3.4.5 Prelucrari repetitive

Prelucr˘arile repetitive pot de trei tipuri:

• cu test init ial ,

• cu test nal si

• cu contor .Prelucrarea repetitiv˘ a cu test init ial se descrie prin: Prelucrarea repetitiv˘ a cu

test init ial se descrie prin:

while < condit ie> < prel> ;

sau

while < condit ie> do < prel> ;In momentul execut¸iei, at at timp c at condit ia este adevarat˘ a , se va executa

instruct¸iunea. Dac˘a condit ia nu este la ınceput satisf˘ acut a, atunci instruct ¸iuneanu se efectueaz a niciodat˘a.

Prelucrarea repetitiv˘ a cu test nal se descrie prin:

do < prel> while < condit ie> ;

Prelucrarea se repet˘ a p an a cand condit ia specicat˘a devine fals a. In acest cazprelucrarea se efectueaz˘ a cel put in o dat˘a, chiar dac˘a condit ia nu este satisfacut˘ ala ınceput.

Prelucrarea repetitiv˘ a cu contor se caracterizeaz˘a prin repetarea prelucr˘ arii

de un num ar prestabilit de ori si este descris˘ a prin:for i = i1 , i2 ,...,i n < prel> ;

sau

for i = i1 , i2 ,...,i n do < prel> ;

unde i este variabila contor care ia, pe rˆ and, valorile i1 , i2 ,...,i n ın aceast˘aordine, prelucrarea ind efectuat˘ a pentru ecare valoare a contorului.

Alte forme utilizate sunt:

for i = vi to vf do < prel> ;

ın care contorul ia valori consecutive cresc˘ atoare ıntre vi si vf , si

for i = vi downto vf do < prel> ;

ın care contorul ia valori consecutive descresc˘ atoare ıntre vi si vf .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 38/518

26 CAPITOLUL 3. ALGORITMI

3.4.6 Subalgoritm

In cadrul unui algoritm poate s˘ a apar a necesitatea de a specica de maimulte ori si ın diferite locuri un grup de prelucr˘ ari. Pentru a nu le descrie ınmod repetat ele pot constitui o unitate distinct˘ a, identicabil˘a printr-un nume,care este numit˘a subalgoritm . Ori de c ate ori este necesar˘a efectuarea grupuluide prelucr ari din cadrul subalgoritmului se specic˘ a numele acestuia si, eventual,datele curente asupra c˘ arora se vor efectua prelucrarile. Aceast˘ a actiune se numesteapel al subalgoritmului , iar datele specicate al˘ aturi de numele acestuia si asupracarora se efectueaz˘a prelucrarile se numesc parametri .

In urma traducerii ıntr-un limbaj de programare un subalgoritm devine unsubprogram.

Un subalgoritm poate descris ın felul urm˘ ator:

< nume subalg > (< tip > < nume p1 > , < tip > < nume p2 > , ... )

.../* prelucr˘ari specice subalgoritmului */...return < nume rezultat > ;

unde < nume subalg > reprezint˘a numele subalgoritmului iar nume p1, nume p2,

... reprezint˘a numele parametrilor. Ultimul enunt ¸, prin care se returneaz˘ a rezultatulcalculat ın cadrul subalgoritmului, este optional.

Modul de apel depinde de modul ın care subalgoritmul returneaz˘ a rezultatelesale. Dac a subalgoritmul returneaz˘ a efectiv un rezultat, printr-un enunt ¸ de forma

return < nume rezultat > ;

atunci subalgoritmul se va apela ın felul urm˘ ator:

v= < nume subalg > (nume p1, nume p2, ...);

Acesti subalgoritmi corespund subprogramelor de tip funct ie.Daca ın subalgoritm nu apare un astfel de enunt ¸, atunci el se va apela prin:

< nume subalg > (nume p1, nume p2, ...);

variant˘a care corespunde subprogramelor de tip procedur˘ a .Observat ie . Prelucr˘arile care nu sunt detaliate ın cadrul algoritmului sunt

descrise ın limbaj natural sau limbaj matematic . Comentariile suplimentare vor cuprinse ıntre /* si */. Dac˘ a pe o linie a descrierii algoritmului apare simbolul //atunci tot ce urmeaz˘ a dup a acest simbol, pe aceeasi linie cu el, este interpretat caind un comentariu (deci, nu reprezint˘ a o prelucrare a algoritmului).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 39/518

3.4. LIMBAJ ALGORITMIC 27

3.4.7 Probleme rezolvate

1. Algoritmului lui Euclid.Descrierea ın pseudocod a algoritmului lui Euclid este urm˘ atoarea:

int a, b, d, i, r;read a, b;if (a< b) d=a; i=b; else d=b; i=a; ;r = d % i;while (r ! = 0) d=i; i=r; r=d % i; ;write i;

2. Schema lui Horner.Descrierea ın pseudocod a schemei lui Horner este urm˘ atoarea:

int n, a, b, i;read n, a, b;int a[0..n], c[0..n-1];for i=n,0,-1 read a[i];c[n-1]=b*a[n];for i=1,n-1 c[n-i-1]=b*c[n-i]+a[n-i];val:=b*c[1]+a[1];write val;

3. Conversia unui num˘ ar natural din baza 10 ın baza 2.Fie n un num ar ıntreg pozitiv. Pentru a determina cifrele reprezentarii ın

baza doi a acestui num˘ ar se poate folosi urm˘atoarea metod˘ a:Se ımparte n la 2, iar restul va reprezenta cifra de rang 0. Cˆ atul obt inut la

ımpartirea anterioar˘ a se ımparte din nou la 2, iar restul obt ¸inut va reprezenta cifrade ordin 1 s.a.m.d. Secvent ¸a de ımp˘art iri continu˘a pın˘a la obt inerea unui cˆat nul.

Descrierea ın pseudocod a acestui algoritm este:int n, d, c, r;read n;d = n;c = d / 2; /* cˆatul ımp˘ art irii ıntregi a lui d la 2 */r = d % 2; /* restul ımp˘ art irii ıntregi a lui d la 2 */write r;while (c != 0) d = c;

c = d / 2; /* cˆatul ımp˘ art irii ıntregi a lui d la 2 */r = d % 2; /* restul ımp˘ art irii ıntregi a lui d la 2 */write r;

4. Conversia unui num˘ ar ıntreg din baza 2 ın baza 10.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 40/518

28 CAPITOLUL 3. ALGORITMI

Daca bk bk−1 ...b1b0 reprezint˘a cifrele num arului ın baza 2, atunci valoarea ınbaza 10 se obtine efectuınd calculul:

(bk bk−1 ...b1b0)10 = bk 2k + bk−12k−1 + ... + b12 + b0

Desi calculul de mai sus este similar cu evaluarea pentru X = 2 a polinomului

P [X ] = bk X k + bk−1X k−1 + ... + b1X + b0

prelucrare pentru care ar putea folosit algoritmul corespunz˘ ator schemei luiHorner, ın continuare prezent˘ am o alt a variant˘a de rezolvare a acestei probleme,care foloseste un subalgoritm pentru calculul puterilor unui num˘ ar ıntreg:

int k, i, s;read k;int b[0..k];read b;s = 0;for i=0,k s = s+b[i] * putere (2,i);write s;

putere (int a, int n)

int i, p;p = 1;for i=2,n p = p*a;return p;

5. Sa se scrie un algoritm pentru determinarea tuturor divizorilor naturali ai

unui num ar ıntreg.Rezolvare . Fie n num arul ai c arui divizori trebuie determinat ¸i. Evident 1 si

|n| sunt divizori ai lui n. Pentru a determina restul divizorilor este sucient caacestia s˘a e cautat¸i printre elementele mult ¸imii 2, 3,..., [|n|]cu [x] desemnandpartea ıntreag˘ a a lui x.

Algoritmul poate descris ın modul urm˘ ator:int n , d;read n;write 1; /* asarea primului divizor */for d = 2 , [|n |/ 2]

if (d divide pe n) then write d;write |n| /* asarea ultimului divizor */

6. Sa se scrie un algoritm pentru determinarea celui mai mare element dintr-un sir de numere reale.

Rezolvare . Fie x1 , x2 ,...,x n sirul analizat. Determinarea celui mai mare ele-ment const˘a ın init ializarea unei variabile de lucru max (care va cont ine valoareamaximului) cu x1 si compararea acesteia cu ecare dintre celelalte elemente alesirului. Dac˘a valoarea curent˘ a a sirului, xk , este mai mare decˆat valoarea variaa-bilei max atunci acesteia din urm˘ a i se va da valoarea xk . Astfel, dup a a k −1comparat ie variabila max va cont ine valoarea maxim˘ a din subsirul x1 , x2 ,...,x k .

Algoritmul poate descris ın modul urm˘ ator:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 41/518

3.4. LIMBAJ ALGORITMIC 29

int k, n;read n;double x[1..n], max; /* vectorul si variabila de lucru */read x; /* preluarea elementelor sirului */max = x[1];for k = 2, n

if (max < x[k]) then max = x[k];write max;

7. Sa se aproximeze, cu precizia ε, limita sirului

sn =n

k=0

1k!

.

Rezolvare . Calculul aproximativ (cu precizia ε) al limitei sirului sn const a ıncalculul sumei nite sk , unde ultimul termen al sumei, tk = 1

k ! , are proprietateatk < ε . Intrucˆat tk+1 = t k

k+1 , aceast a relat ie va folosit a pentru calculul valoriitermenului curent (permit ¸and micsorarea num˘ arului de calcule).

double eps, t, s;int k;k=1; /* init ¸ializare indice */t=1; /* init ¸ializare termen */s=1; /* init¸ializare suma */do s=s+t; /* ad˘ augarea termenului curent */

k=k+1;t=t/k; /* calculul urm˘ atorului termen */

while (t ≥ eps);s=s+t; (* ad˘ augarea ultimului termen *)write s;

8. Fie A o matrice cu m linii si n coloane, iar B o matrice cu n linii si p coloane,ambele av and elemente reale. S˘a se determine matricea produs C = A ×B .

Rezolvare . Matricea C va avea m linii si p coloane, iar ecare element sedetermin˘a efectu and suma:

ci,j =n

k=1

a i,k

·bk,j , 1

≤i

≤m, 1

≤j

≤p.

In felul acesta calculul elementelor matricei C se efectueaz a prin trei cicluriimbricate (unul pentru parcurgerea liniilor matricei C , unul pentru parcurgereacoloanelor matricei C , iar unul pentru efectuarea sumei specicate mai sus).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 42/518

30 CAPITOLUL 3. ALGORITMI

int m, n, p; /* dimensiunile matricelor */read m, n, p;double a[1..m][1..n], b[1..n][1..p], c[1..m][1..p]; /* matrice */int i, j, k; /* indici */read a; /* citirea matricei a */read b; /* citirea matricei b */for i=1,m

for j=1,p c[i,j]=0;for k=1,n c[i][j]=c[i][j]+a[i][k]*b[k][j];

write c;

3.4.8 Probleme propuse

1. Fie D o dreapt˘a de ecuat ie ax + by+ c = 0 si (C) un cerc de centru O(x0 , y0)si raz a r . Sa se stabileasc a pozit ia dreptei fat¸a de cerc.

Indicat ie . Se calculeaza distant¸a de la centrul cercului la dreapta D utiliz andformula:

d = |ax 0 + by0 + c|√a2 + b2.

Daca d ≥r + ε atunci dreapta este exterioar˘ a cercului, dac a d ≤r−ε atunci dreaptaeste secant˘a, iar dac a r −ε < d < r + ε atunci este tangent˘ a (la implementareaegalitatea ıntre dou˘ a numere reale ...).

2. Sa se genereze primele n elemente ale sirurilor ak si bk date prin relat ¸iilede recurent a:

ak +1 =5ak + 3ak + 3

, bk =ak + 3ak + 1

, k ≥0, a 0 = 1 .

3. Sa se determine r˘ad acina p atrat˘a a unui num˘ur real pozitiv a cu preciziaε = 0 .001, folosind relat ia de recurent¸ a:

xn +1 =12

xn +a

xn, x1 = a.

Precizia se consider˘a atins a cand |xn +1 −xn | < ε .

4. Fie A o matrice p atratic˘a de dimensiune n. Sa se transforme matricea A,prin interrschimb˘ ari de linii si de coloane, astfel ıncˆ at elementele de pe diagonalaprincipal a sa e ordonate cresc˘ator.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 43/518

3.4. LIMBAJ ALGORITMIC 31

5. Sa se determine cel mai mare divizor comun al unui sir de numere ıntregi.

6. Sa se calculeze coecient ii polinomului

P [X ] = (aX + b)n , a, b∈Z , n∈

N .

7. Fie A o matrice p atratic˘a. Sa se calculeze suma elementelor din ecare zon˘ a(diagonala principal˘ a, diagonala secundar˘ a, etc.) marcat˘ a ın gura urm˘atoare:

a. b. c.

Figura 3.1: Zone ın matrice p˘ atratic˘a

8. Fie x1 , x2 ,...,x n ∈Z rad acinile unui polinom cu coecient¸i ıntregi:

P [X ] = an X n + an −1X n −1 + ... + a1X + a0 .

Sa se determine coecient¸ii polinomului.

9. Sa se determine toate r˘ adacinile rat ionale ale polinomului P [X ] care arecoecienti ıntregi.

140. Fie [P 1 , P 2 ,...,P n ] un poligon convex dat prin coordonatele cartezieneale varfurilor sale (ın ordine trigonometric˘ a). Sa se calculeze aria poligonului.

11. Fie f : [a, b] →R o functie continu˘a cu proprietatea c˘ a exist a un unic ξ∈(a, b) care are proprietatea c˘ a f (ξ) = 0. S a se aproximeze ξ cu precizia ε = 0 .001utiliz and metoda bisect¸iei.

12. Fie P si Q polinoame cu coecient iıntregi. S˘ a se determine toate r˘ adacinilerat ionale comune celor dou˘a polinoame.

13. Sa se determine toate numerele prime cu maxim 6 cifre care r˘ aman primesi dup˘a ”r asturnarea” lor (r˘ asturnatul num˘ arului abcdef este fedcba ).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 44/518

32 CAPITOLUL 3. ALGORITMI

3.5 Instruct ¸iuni corespondente limbajului algorit-

mic

3.5.1 Declararea datelor

Datele simple se declar a sub forma:

< tip > < nume > ;

sau

< tip > < nume > = literal ;unde < tip > poate lua una dintre urm˘ atoarele valori: byte , short , int , long , oat ,double , boolean , char . In exemplul urm˘ator sunt prezentate cˆ ateva modalit˘ atide declarare pentru diferite tipuri de variabile.

class Literali

public static void main(String args[])

long l1 = 5L;long l2 = 12l;int i1hexa = 0x1;

int i2hexa = 0X1aF;int i3octal = 01;long i4octal = 012L;long i5LongHexa = 0xAL;float f1 = 5.40F;float f2 = 5.40f;float f3 = 5.40e2f;float f4 = 5.40e+12f;float f5 = 5.40; // da eroare, trebuie castdouble d1 = 5.40; // implicit este double !double d2 = 5.40d;double d3 = 5.40D;double d4 = 5.40e2;double d5 = 5.40e+12d;char c1 = ’r’;char c2 = ’\u4567’;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 45/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 33

Java deneste mai multe tipuri primitive de date. Fiecare tip are o anumit˘ adimensiune, care este independent˘ a de caracteristicile masinii gazd˘ a. Astfel, spredeosebire de C/C++, unde unıntreg poate reprezentat pe 16, 32 sau 64 de bit i,ınfunct ie de arhitectura masinii, o valoare de tip ıntreg ın Java va ocupa ıntotdeauna32 de biti, indiferent de masina pe care ruleaz˘ a. Aceast a consecvent a este esent ial adeoarece o aceeasi aplicat ¸ie va trebui s˘a ruleze pe masini cu arhitectur˘ a pe 16, 32sau 64 de biti si s a produc a acelasi rezultat pe ecare masin˘ a ın parte.

Tip Dimensiune Valoare Valoare Valoare Cifre(octet i) minima maxima initiala semnicative

byte 1 −27 27 −1 0short 2 −215 215 −1 0int 4 −231 231 −1 0long 8

−263 263

−1 0

oat 4 +-1.4E-45 +-3.4E+38 0 6-7double 8 +-4.94E-324 +-1.79E+308 0 14-15boolean 1 falsechar 2 null

Tabelul 3.1: Tipurile primitive de date ın Java

Variabilele pot init ializate la declararea lor sau ın momentul utiliz˘ arii lorefective. Dac a valoarea nu este specicat˘ a explicit atunci variabila se init ¸ializeaz˘acu o valoare init ial a implicit a. Tabelul anterior prezint˘ a cateva exemple ın acestsens.

Conversiile ıntre diferitele tipuri sunt permise (acolo unde au semnicat ¸ie).Se vede din tabel c a unele tipuri de variabile au posibilitatea s˘ a reprezinte unspectru mai mare de numere decˆ at altele.

In afara tipurilor de baz˘ a, limbajul Java suport˘ a si tipuri de date createde utilizator, de pild˘ a variabile de tip clas˘ a , interfat ˘ a sau tablou . Ca si celelaltevariabile, dac˘a nu sunt explicit init ¸ializate, valoarea atribuit˘ a implicit este null .

Modicatorul static este folosit pentru a specica faptul c˘ a variabila areo singur a valoare, comun˘a tuturor instant ¸elor clasei ın care ea este declarat˘ a.Modicarea valorii acestei variabile din interiorul unui obiect face ca modicareasa e vizibila din celelalte obiecte. Variabilele statice sunt init ializate la ınc arcarea codului specic unei clase si exist˘a chiar si dac˘a nu exist a nici o instant a a claseirespective. Din aceast˘ a cauz a, ele pot folosite de metodele statice .

Tablourile unidimensionale se declar˘ a sub forma:

< tip > [ ] < nume > =new < tip > [n];

sau

< tip > < nume > [ ] =new < tip > [n];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 46/518

34 CAPITOLUL 3. ALGORITMI

Elementele vectorului pot accesate cu ajutorul unui indice, sub forma:

< nume > [i]

unde i poate lua orice valoare ıntre 0 si n −1.In cazul tablourilor bidimensionale, o declarat ¸ie de forma:

< tip > [ ] [ ] < nume > = new < tip > [m][n];

sau

< tip > < nume > [ ] [ ] = new < tip > [m][n];

specica o matrice cu m linii si n coloane. Fiecare element se specic˘a prin doiindici:

< nume > [i][j]

unde i reprezint˘a indicele liniei si poate avea orice valoare ıntre 0 si m −1 iar jreprezint˘a indicele coloanei si poate avea orice valoare ıntre 0 si n −1.

3.5.2 Operat ¸ii de intrare/iesire

Preluarea unei valori de tip int de la tastatur˘ a se poate face sub forma:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

int vi=Integer.parseInt(br.readLine());

iar dintr-un sier (de exemplu fis.in ), sub forma:

StreamTokenizer st = new StreamTokenizer(new BufferedReader(new FileReader("fis.in")));

st.nextToken(); int vi = (int) st.nval;

Scrierea valorii unei variabile v pe ecran se poate face sub forma:

System.out.print(v);

iar ıntr-un sier (de exemplu fis.out ), sub forma:

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("fis.out")));

out.print(v);out.close();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 47/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 35

3.5.3 Prelucrari liniare

O secvent a de prelucr ari se descrie ın modul urm˘ ator:

< instr 1 > ;< instr 2 > ;

...< instr n > ;

sau

< instr 1 > ; < instr 2 > ; ... < instr n > ;

O astfel de scriere indic˘a faptul c a ın momentul execut ¸iei instruct¸iunile seefectueaz a ın ordinea ın care sunt specicate.

3.5.4 Prelucrari alternative

O prelucrare alternativ˘ a complet˘ a (cu dou a ramuri) este descris˘ a prin:

if (< condit ie> ) < instr 1 > else < instr 2 > ;

unde < condit ie> este o expresie relat ional˘ a . Aceast a prelucrare trebuie ınt ¸eleas aın modul urm˘ ator: dac˘a condit ia este adev˘ arat˘ a atunci se efectueaz˘a prelucrarea< instr 1 > , altfel se efectueaz a < instr 2 > .

O prelucrare alternativ˘ a cu o singur˘ a ramur˘ a se descrie prin:

if (< condit ie> ) < instr > ;

iar execut ia ei are urm˘atorul efect: dac˘ a condit ia este satisfacut˘ a atunci se efectueaz˘ainstruct¸iunea specicat˘a, altfel nu se efectueaz˘a nici o prelucrare ci se trece laurm atoarea prelucrare a algoritmului.

3.5.5 Prelucrari repetitive

Prelucr˘arile repetitive pot de trei tipuri:

• cu test init ial ,

• cu test nal si

• cu contor .Prelucrarea repetitiv˘ a cu test init ial se descrie prin:

while (< condit ie> ) < instr > ;In momentul execut¸iei, at at timp c at condit ia este adevarat˘ a , se va executa

prelucrarea. Dac˘ a condit ia nu este la ınceput satisf˘ acut a, atunci prelucrarea nu seefectueaz a niciodat˘a.

Prelucrarea repetitiv˘ a cu test nal se descrie prin:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 48/518

36 CAPITOLUL 3. ALGORITMI

do < instr > while (< condit ie> );

Instruct¸iunea se repet˘a pan a cand condit ia specicat˘a devine fals a. In acestcaz prelucrarea se efectueaz˘ a cel put in o dat˘a, chiar dac˘a condit ia nu este satisfa-cut a la ınceput.

Prelucrarea repetitiv˘ a cu contor se caracterizeaz˘a prin repetarea prelucr˘ ariide un num ar prestabilit de ori si este descris˘ a prin:

for (< instr1 > ; < conditie > ; < instr2 > ) < instr3 > ;

In general <instr1> reprezint˘a etapa de init¸ializare a contorului, <instr2>reprezint˘a etapa de incrementare a contorului, <instr3> reprezint˘a instruct¸iuneacare se execut a ın mod repetat cˆ at timp condit¸ia <conditie> are valoarea true .

3.5.6 Subprograme

In cadrul unui program poate s˘ a apar a necesitatea de a specica de mai multeori si ın diferite locuri un grup de prelucr˘ ari. Pentru a nu le descrie ın mod repetatele pot constitui o unitate distinct˘ a, identicabil˘a printr-un nume, care este numit˘ asubprogram sau, mai precis, funct ie (dac a returneaz˘a un rezultat) sau procedur˘ a (dac a nu returneaz˘a nici un rezultat). In Java funct iile si procedurile se numescmetode . Ori de cate ori este necesar˘a efectuarea grupului de prelucr˘ ari din cadrulprogramului se specic˘a numele acestuia si, eventual, datele curente asupra c˘ arorase vor efectua prelucrarile. Aceast˘ a actiune se numeste apel al subprogramului ,iar datele specicate al˘ aturi de numele acestuia si asupra c˘ arora se efectueaz˘aprelucrarile se numesc parametri .

Un subprogram poate descris ın felul urm˘ ator:< tipr > < nume sp > (< tipp1 > < numep1 > , < tipp2 > < numep2 > , ... )

.../* prelucr˘ari specice subprogramului */...return < nume rezultat > ;

unde < tipr > reprezint˘a tipul rezultatului returnat ( void daca subprogramul nureturneaz˘a nici un rezultat), < nume sp > reprezint˘a numele subprogramului, iarnumep1, numep2, ... reprezint˘ a numele parametrilor. Ultimul enunt ¸, prin care sereturneaz˘a rezultatul calculat ın cadrul subprogramului, trebuie pus numai dac˘ a< tipr > nu este void .

Modul de apel depinde de modul ın care subprogramul returneaz˘ a rezultatelesale. Dac a subprogramul returneaz˘ a efectiv un rezultat, printr-un enunt ¸ de forma

return < nume rezultat > ;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 49/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 37

atunci subprogramul se va apela ın felul urm˘ ator:

v= < nume sp > (nume p1, nume p2, ...);Aceste subprograme corespund subprogramelor de tip funct ie .Daca ın subprogram nu apare un astfel de enunt ¸, atunci el se va apela prin:

< nume sp > (nume p1, nume p2, ...);

variant˘a care corespunde subprogramelor de tip procedur˘ a .Observat ie . Prelucr˘arile care nu sunt detaliate ın cadrul algoritmului sunt

descrise ın limbaj natural sau limbaj matematic . Comentariile suplimentare vor cuprinse ıntre /* si */. Dac˘ a pe o linie a descrierii algoritmului apare simbolul //atunci tot ce urmeaz˘ a dup a acest simbol, pe aceeasi linie cu el, este interpretat caind un comentariu (deci, nu reprezint˘ a o prelucrare a programului).

3.5.7 Probleme rezolvate

1. Descompunere Fibonacci . Sa se descompun a un num ar natural, de cel mult18-19 cifre, ın sum a de cat mai put ini termeni Fibonacci.

Rezolvare : Programul urm˘ator calculeaz˘a si aseaz˘a primii 92 de termenidin sirul Fibonacci (mai mult nu este posibil f˘ ar a numere mari !), si descompunenum arul x introdus de la tastatur˘ a. Metoda static int maxFibo ( long nr )returneaz˘a indicele celui mai mare element din sirul lui Fibonacci care este maimic sau egal cu parametrul nr .

import java.io.*;

class DescFibostatic int n=92;static long[] f=new long[n+1];

public static void main (String[]args) throws IOException

long x,y;int iy, k, nrt=0;

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.print("x = ");x=Long.parseLong(br.readLine());f[0]=0; f[1]=1; f[2]=1;for(k=3;k<=n;k++) f[k]=f[k-1]+f[k-2];for(k=0;k<=n;k++) System.out.println(k+" : "+f[k]);System.out.println(" "+Long.MAX_VALUE+" = Long.MAX_VALUE");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 50/518

38 CAPITOLUL 3. ALGORITMI

System.out.println("x = "+x);while(x>0)

iy=maxFibo(x);y=f[iy];nrt++;System.out.println(nrt+" : "+x+" f["+iy+"] = "+y);x=x-y;

static int maxFibo(long nr)

int k;for(k=1;k<=n;k++) if (f[k]>nr) break;return k-1;

De exemplu, pentru x = 5678 pe ecran apare:

1 : 5678 f[19] = 4182 : 1497 f[16] = 9873 : 510 f[14] = 3774 : 133 f[11] = 895 : 44 f[9] = 346 : 10 f[6] = 87 : 2 f [3] = 2

2. Fie S n = xn1 + xn

2 unde x1 si x2 sunt r ad acinile ecuat iei cu coecient i ıntregiax 2 + bx + c = 0 (vom considera a = 1!). S a se aseze primii 10 termeni ai siruluiS n si sa se precizeze ın dreptul ec˘ arui termen dac˘ a este num ar prim, iar dac˘a nueste num ar prim s a se aseze descompunerea ın factori.

Rezolvare :

class e02

public static void main(String[] args)

int a, b, c, nnp=0, s, p, n=10, k;long[] ss=new long[n+1];

a=1;b=1;c=2;s=-b/a;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 51/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 39

p=c/a;ss[1]=s;ss[2]=s*s-2*p;for(k=3;k<=n;k++) ss[k]=s*ss[k-1]-p*ss[k-2];for(k=1;k<=n;k++)

if(esteprim(Math.abs(ss[k])))System.out.println(k+" : "+ss[k]+" PRIM "+(++nnp));

else

System.out.print(k+" : "+ss[k]+" = ");descfact(Math.abs(ss[k]));

System.out.println("nnp = "+nnp);

// main

static void descfact(long nr)

long d=2;if((nr==0)||(nr==1))System.out.println(); return;while(nr%d==0)System.out.print(d+""); nr=nr/d;d=3;while((d*d<=nr)&&(nr!=1))

while(nr%d==0)System.out.print(d+" "); nr=nr/d;d=d+2;

if(nr!=1) System.out.println(nr);else System.out.println();

static boolean esteprim(long nr)

if((nr==0)||(nr==1)) return false;if((nr==2)||(nr==3)) return true;if(nr%2==0) return false;long d=3;while((nr%d!=0)&&(d*d<=nr)) d=d+2;if(nr%d==0) return false; else return true;

// class

Pe ecran apar urm˘ atoarele rezultate:

1 : - 1 =2 : -3 PRIM 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 52/518

40 CAPITOLUL 3. ALGORITMI

3 : 5 PRIM 24 : 1 =5 : -11 PRIM 36 : 9 = 3 37 : 13 PRIM 48 : -31 PRIM 59 : 5 PRIM 610 : 57 = 3 19nnp = 6Press any key to continue...

3. Se consider a funct ia f (x) = P (x)eαx unde P (x) este un polinom de grad ncu coecienti ıntregi. S˘ a se aseze toate derivatele pˆ an a la ordinul m ale funct iei f ,si, ın dreptul coecient ¸ilor polinoamelor care apar ın aceste derivate, s˘ a se precizezedaca respectivul coecient este num˘ ar prim, iar dac˘a nu este num˘ar prim s a seaseze descompunerea ın factori. De asemenea, s˘ a se aseze care este cel mai marenum ar prim care apare, si care este ordinul derivatei ın care apare acest cel maimare num˘ar prim.

Rezolvare : Derivata funct¸iei f are forma Q(x)eαx unde Q este un polinom deacelasi grad cu polinomul P . Toat˘a rezolvarea problemei se reduce la determinareacoecient ilor polinomului Q ın funct ie de coecient ii polinomului P .

class e03

static long npmax=1,pmax=0;

public static void main(String[] args)

int n=7, m=10, alfa=1, k;long[] p=new long[n+1];p[7]=1; p[3]=1; p[0]=1;afisv(p,0);for(k=1;k<=m;k++)

System.out.print("derivata = "+k);p=deriv(p,alfa);afisv(p,k);

System.out.println(npmax+" "+pmax);System.out.println("GATA!!!");

static long[] deriv(long[] a,int alfa)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 53/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 41

int n=a.length-1, k;long[] b=new long[n+1];b[n]=a[n]*alfa;for(k=0;k<=n-1;k++) b[k]=(k+1)*a[k+1]+a[k]*alfa;return b;

static void afisv(long[] x,int ppp)

int n=x.length-1;int i;System.out.println();for(i=n;i>=0;i--)if(esteprim(Math.abs(x[i])))

System.out.println(i+" : "+x[i]+" PRIM ");if(npmax<Math.abs(x[i]))

npmax=Math.abs(x[i]);pmax=ppp;

else

System.out.print(i+" : "+x[i]+" = ");

descfact(Math.abs(x[i]));System.out.println();

static void descfact(long nr)

long d=2;if((nr==0)||(nr==1))

System.out.println();return;

while(nr%d==0)

System.out.print(d+" ");nr=nr/d;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 54/518

42 CAPITOLUL 3. ALGORITMI

d=3;while((d*d<=nr)&&(nr!=1))

while(nr%d==0)

System.out.print(d+" ");nr=nr/d;

d=d+2;

if(nr!=1) System.out.println(nr);

else System.out.println();

static boolean esteprim(long nr)

if((nr==0)||(nr==1)) return false;if((nr==2)||(nr==3)) return true;if(nr%2==0) return false;long d=3;while((nr%d!=0)&&(d*d<=nr)) d=d+2;if(nr%d==0) return false; else return true;

// class

4. Rad acini rat ionale. S a se determine toate r˘ ad acinile rat ionale ale uneiecuat ii cu coecient i ıntregi.Rezolvare : Se caut a rad acini rat ionale formate din fract ¸ii ın care num˘ ar atorul

este divizor al termenului liber iar numitorul este divizor al termenului dominant.Programul care urmeaz˘ a genereaz a coecientii ecuat iei, plec and de la fract ii date(ca r ad acini), si apoi determin˘ a rad acinile rat ionale

class RadaciniRationale // generez p_i/q_i

static int k=0;

public static void main(String[] args)

int[] p=1,1,2,3, 3, 1, q=2,3,3,2,-2,-1;int[] a=genPol(p,q);int n=a.length-1,alfa,beta;int moda0=Math.abs(a[0]),modan=Math.abs(a[n]);for(alfa=1;alfa<=moda0;alfa++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 55/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 43

if(moda0%alfa!=0) continue;for(beta=1;beta<=modan;beta++)

if(modan%beta!=0) continue;if(cmmdc(alfa,beta)!=1) continue;if (f(a,alfa,beta)==0)

System.out.println("x["+(++k)+"] = "+alfa+"/"+beta+" ");if (f(a,-alfa,beta)==0)

System.out.println("x["+(++k)+"] = -"+alfa+"/"+beta+" ");// for beta

// for alfa// main

static int[] genPol(int[] a, int[] b) // X-a_i/b_i==>b_i X - a_i

int n=a.length;int[] p=-a[0],b[0],//p=b[0] X -a[0]q=13,13; // q initializat "aiurea" - pentru dimensiune !afisv(p);for(int k=1;k<n;k++)

q[0]=-a[k];q[1]=b[k];p=pxq(p,q);afisv(p);

return p;// genPol()

static int[] pxq(int[] p,int[] q)

int gradp=p.length-1, gradq=q.length-1;int gradpq=gradp+gradq;int[] pq=new int[gradpq+1];int i,j,k;for(k=0;k<=gradpq;k++) pq[k]=0;for(i=0;i<=gradp;i++)

for(j=0;j<=gradq;j++) pq[i+j]+=p[i]*q[j];return pq;

static int f(int[]a,int alfa, int beta)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 56/518

44 CAPITOLUL 3. ALGORITMI

int n=a.length-1,k,s=0;for(k=0;k<=n;k++) s+=a[k]*putere(alfa,k)*putere(beta,n-k);return s;

static int putere(int a, int n)

int p=1;for(int k=1;k<=n;k++) p*=a;return p;

static int cmmdc(int a, int b)

int d,i,c,r;if (a>b) d=a; i=b; else d=b; i=a;r=123; // ca sa inceapa while !!!while (r > 0)c=d/i; r=d%i; d=i; i=r;return d;

static void afisv(int[] a)

for(int i=a.length-1;i>=0;i--) System.out.print(a[i]+" ");System.out.println();

// afisv()

// class

5. Sa se aseze frecvent a cifrelor care apar ın

f (n) =n

k=0

12k C nn + k

netin and cont de faptul c˘a f (n) are o expresie mult mai simpl˘a, si anume 2 n . Sumatrebuie calculat˘ a simul and operat¸iile de adunare, ınmult ire si ımp˘ art ire la 2, cunumere mari.

Rezolvare : Funct ia se pune sub forma:

f (n) = 12n

n

k =02n −k C nn + k

Se calculeaz a suma, si apoi se fac n ımp˘art iri succesive la 2.

class e05

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 57/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 45

public static void main (String[]args)

int n, k;int[] s;int[] p;for(n=10;n<=12;n++)

s=nrv(0);for(k=0;k<=n;k++)

p=inm(comb(n+k,n),putere(2,n-k));s=suma(s,p);

afisv(s);for(k=1;k<=n;k++) s=impartLa2(s);System.out.print(n+" : ");afisv(s);fcifre(s);

System.out.println("GATA");

//main()

static int[] impartLa2(int[] a)

int na,nb,k,t=0;

na=a.length-1;if(a[na]==1) nb=na-1; else nb=na;int[] b=new int[nb+1];if(na==nb)for(k=na;k>=0;k--) a[k]+=10*t; b[k]=a[k]/2; t=a[k]%2;else

t=a[na];for(k=na-1;k>=0;k--)a[k]+=10*t; b[k]=a[k]/2; t=a[k]%2;

return b;

static void fcifre(int[] x)

int i;int[] f=new int[10];for(i=0;i<x.length;i++) f[x[i]]++;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 58/518

46 CAPITOLUL 3. ALGORITMI

System.out.println();for(i=0;i<=9;i++) System.out.println(i+" : "+f[i]);System.out.println();

static int[] suma(int[] x, int[] y)

int i, j, t, ncx=x.length, ncy=y.length, ncz;if(ncx>ncy) ncz=ncx+1; else ncz=ncy+1;int[] xx=new int[ncz];int[] yy=new int[ncz];int[] z=new int[ncz];for(i=0;i<ncx;i++) xx[i]=x[i];for(j=0;j<ncy;j++) yy[j]=y[j];t=0;for(i=0;i<ncz;i++)z[i]=xx[i]+yy[i]+t; t=z[i]/10; z[i]=z[i]%10;if(z[ncz-1]!= 0) return z;else

int[]zz=new int[ncz-1];for(i=0;i<=ncz-2;i++) zz[i]=z[i];return zz;

static int[] inm(int[]x,int[]y)

int t, n=x.length, m=y.length, i, j;int[][]a=new int[m][n+m];int[]z=new int[m+n];for(j=0;j<m;j++)

t=0;for(i=0;i<n;i++)

a[j][i+j]=y[j]*x[i]+t;t=a[j][i+j]/10;a[j][i+j]=a[j][i+j]%10;

a[j][i+j]=t;

t=0;for(j=0;j<m+n;j++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 59/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 47

z[j]=0;for(i=0;i<m;i++) z[j]=z[j]+a[i][j];z[j]=z[j]+t;t=z[j]/10;z[j]=z[j]%10;

if(z[m+n-1]!= 0) return z;else

int[]zz=new int[m+n-1];for(i=0;i<=m+n-2;i++)zz[i]=z[i];return zz;

static void afisv(int[]x)

int i;for(i=x.length-1;i>=0;i--) System.out.print(x[i]);System.out.print(" *** "+x.length);System.out.println();

static int[] nrv(int nr)

int nrrez=nr, nc=0;while(nr!=0) nc++; nr=nr/10;int[]x=new int [nc];nr=nrrez;nc=0;while(nr!=0)x[nc]=nr%10; nc++; nr=nr/10;return x;

static int[] putere (int a, int n)

int[] rez;int k;rez=nrv(1);for(k=1;k<=n;k++) rez=inm(rez,nrv(a));return rez;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 60/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 61/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 49

dimensiuni (numerele devin foarte mari, asa c˘ a elementul S i,j trebuie s a contin avectorul cifrelor valorii sale).

class e06

public static void main(String[] args)

int n=50, m=40, i, j;int[][][] s=new int[n+1][m+1][1];for(i=1;i<=n;i++)

if(i<=m) s[i][i]=nr2v(1);s[i][1]=nr2v(1);for(j=2;j<=min(i,m);j++)

s[i][j]=suma(s[i-1][j-1],inm(nr2v(j),s[i-1][j]));if(i<=m) s[i][i]=nr2v(1);for(i=1;i<=m;i++)

System.out.print("\n"+i+" : "+s[n][i].length+" ");afissumac(s[n][i]);afisv(s[n][i]);

static int[] suma(int[] x,int[] y)...static int[] nr2v(int nr)...static int[] inm(int[]x, int[]y)...static void afisv(int[]x)...

static void afissumac(int[]x)

int i,s=0;for(i=x.length-1;i>=0;i--) s+=x[i];System.out.print(s+" ");

static int min(int a, int b) return (a<b)?a:b; // class

Pe ecran apar urm˘ atoarele valori (numerele devin foarte mari!):

1 : 1 1 12 : 15 64 562949953421311

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 62/518

50 CAPITOLUL 3. ALGORITMI

3 : 24 102 1196496640523588113737304 : 29 138 528186553598452245619078825055 : 33 150 7400958643682530162711881395876256 : 37 170 11218727630940119874547782377128166877 : 39 172 3557160592927524647970650380131376862808 : 41 163 350417311326100987713326915256638659028509 : 43 189 138502250979595618460190708970073050968019510 : 44 205 2615471651586288129201277739657799378172701111 : 45 177 26723575409002161865117527704693137105019478012 : 46 205 161933094493627977915438174581642803644128641013 : 46 232 623890127627578481149286179482673756388928823014 : 47 205 1613280927006649437612532298803569198115849093015 : 47 162 2922645700196513908979385321312651027002430000016 : 47 216 3840082536549554482384780798853607181578005094017 : 47 198 3764524179160090680487108081862503772624751904518 : 47 225 2818933281349345414189997673550179832227753616519 : 47 165 1644399365192507435251240222090095001921709700020 : 46 237 759792160686098690045446939409927714699875530021 : 46 198 282025502856350614965795295463781304817272338022 : 45 189 85122188307735663424162227664625917075162638023 : 45 198 21109249414994737119560869609964510716814640024 : 44 192 4339774380024789483355657097743228516243140025 : 43 168 745380215327320008337962623483762546591250026 : 43 186 107668960159767280165071265420977257432821227 : 42 189 13154662736580840581381485825646536945608028 : 41 155 13660054661277961013613328658015172843800

29 : 40 165 121054668665490016901058884043096338772030 : 38 185 9186094386763064250116425497886796175231 : 37 155 598512338555162508509000779383136256032 : 36 164 33550607916361474458148864887018752033 : 35 153 1620425138488415893267785661790511034 : 33 144 67483341642571152248238137954496035 : 32 126 2423553631854612450150176769375036 : 30 135 75013568829210188677056801079537 : 29 141 1998320998350751454752489603538 : 27 132 45714934748917557373734424539 : 25 114 895177974349641231494700040 : 24 93 149377949042637543000150

7. Sa se aseze B1 , B 2 ,...,B n stiind c˘a

Bn +1 =n

k =0

C kn Bk , B 0 = 1 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 63/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 64/518

52 CAPITOLUL 3. ALGORITMI

d=cmmdc(y[j],x[i]);y[j]=y[j]/d;x[i]=x[i]/d;if(y[j]==1) break;

rez=nr2v(1);for(i=1;i<=k;i++) rez=inm(rez,nr2v(x[i]));return rez;

static int cmmdc(int a,int b) ...

3.5.8 Probleme propuse

1. Fie S n = xn1 + xn

2 + xn3 unde x1 , x2 si x3 sunt r ad acinile ecuat iei cu coecient i

ıntregi ax 3 + bx2 + cx+ d = 0 (vom considera a = 1!). S a se aseze primii 10 termeniai sirului S n si sa se precizezeın dreptul ec˘ arui termen dac˘a este num ar prim, iardaca nu este num˘ar prim s a se aseze descompunerea ın factori.

2. Sa se aseze frecvent a cifrelor care apar ın

f (n) =

n −1

k=0 C kn −1n

n

−1

−k

(k + 1)!

netin and cont de faptul c˘a f (n) are o expresie mult mai simpl˘ a, si anume n n . Sumatrebuie calculat˘ a simul and operat¸iile cu numere mari.

3. Sa se aseze frecvent a cifrelor care apar ın

f (n) = n n −1 +n −1

k=1

C kn kk−1(n −k)n −k

netin and cont de faptul c˘a f (n) are o expresie mult mai simpl˘ a, si anume n n . Sumatrebuie calculat˘ a simul and operat¸iile cu numere mari.

4. Sa se calculeze

f (n) = n 1 −1

p11 −

1 p2

... 1 −1

pm

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 65/518

3.5. INSTRUCTIUNI CORESPONDENTE LIMBAJULUI ALGORITMIC 53

unde n = pi 11 pi 2

2 ...p i mm reprezint˘a descompunerea ın factori primi a lui n .

5. Sa se calculeze

φ(n) = card k∈N / 1 ≤k ≤n, cmmdc (k, n ) = 1 .

6. Sa se calculezef (n) =

d|nφ(n)

unde φ este funct ia de la exercit iul anterior, net ¸in and cont de faptul c˘a f (n) are oexpresie mult mai simpl˘a, si anume n.

7. Sa se calculezef (n) = n! 1 −

11!

+12! −... +

(−1)n

n!.

8. Sa se calculeze

f (m,n,λ 1 , λ 2 ,...,λ n ) =m

k=1

(−1)m −k C km C 1kλ 1 C 2k +1

λ 2 ... C nk + n −1λ n .

9. Sa se calculeze

g(m,n,λ 1 , λ 2 ,...,λ n ) = C 1m λ 1 C 2m +1λ 2 ... C nm + n −1

λ n

implementˆand operat¸iile cu numere mari.

10. Sa se calculeze

f (n) =1

2n (2n)! −C 1n 2(2n −1)! + C 2n 22(2n −2)! −... + ( −1)n 2n n! .

11. Sa se calculezeC n =

1n + 1

C n2n

implementˆand operat¸iile cu numere mari.

12. Sa se aseze P (100, 50) (inclusiv suma cifrelor si num˘ arul cifrelor) stiindca

P (n + k, k) = P (n, 1) + P (n, 2) + ... + P (n, k )

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 66/518

54 CAPITOLUL 3. ALGORITMI

siP (n, 1) = P (n, n ) = 1 ,

n

≥k

≥1.

Se vor implementa operat ¸iile cu numere mari.

13. Sa se determine cel mai mic num˘ ar natural r , astfel ıncˆat pr = e, unde peste o permutare dat˘ a si e este permutarea identic˘ a.

14. Sa se aseze C 100 stiind c˘a

C n =n

k =1

C k−1C n −k , C 0 = 1 .

Se vor implementa operat ¸iile cu numere mari.

15. Sa se aseze E 100 stiind c˘a

En = E 2E n −1 + E 3E n −2 + ... + E n −1E 2 , E 1 = E 2 = 1 .

Se vor implementa operat ¸iile cu numere mari.

16. Sa se calculeze

S (n, m ) =1

m!

m −1

k=0

(−1)k C km (m −k)n

17. Sa se aseze C 100 stiind c˘a

C n =n

k =1

C kn F k .

unde F k este termen Fibonacci. Se vor implementa operat ¸iile cu numere mari.

18. Sa se aseze C 100 stiind c˘a

C n =n

k=1

C kn 2k F k .

unde F k este termen Fibonacci. Se vor implementa operat ¸iile cu numere mari.

19. Sa se determine puterea a zecea a unui polinom dat.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 67/518

Capitolul 4

Analiza complexitat ¸iialgoritmilor

4.1 Scopul analizei complexitat ¸ii

In general exist˘a mai multi algoritmi care rezolv˘ a aceeasi problem˘a. Dorimsa exprim am ecient a algoritmilor sub forma unui criteriu care s˘ a ne permit˘a saalegem din mai mult¸i algoritmi pe cel optim. Exist˘ a mai multe moduri ın careputem exprima ecient a : prin timpul necesar pentru execut ¸ia algoritmului sauprin alte resurse necesare (de exemplu memoria). In ambele cazuri ıns˘ a, avem odependent¸a de dimensiunea cazului studiat.

Se pune problema de alegere a unei unit˘ at i de m asur a pentru a exprimaecienta teoretic˘a a unui algoritm. O important ¸ a deosebit a ın rezolvarea acesteiprobleme o are principiul invariant ¸ei . Acesta ne arat˘a ca nu este necesar s˘a folosimo astfel de unitate.

Principiul invariant ¸ei : dou˘ a implement˘ ari diferite ale aceluiasi algoritm nu difer˘ a ın ecient ˘ a cu mai mult de o constant˘ a multiplicativ˘ a .

Implementarea unui algoritm presupune elementele legate de calculatorulfolosit, de limbajul de programare si ındemˆ anarea programatorului (cu condit ¸ia caacesta s a nu modice algoritmul). Datorit˘ a principiului invariant ¸ei vom exprimaecienta unui algoritm ın limitele unei constante multiplicative.

Un algoritm este compus din mai multe instruct iuni , care la r andul lor suntcompuse din mai multe operat ii elementare . Datorit˘a principiului invariant ¸ei nu

ne intereseaz˘a timpul de execut ie a unei operat ii elementare , ci numai num˘ arul lor ,dar ne intereseaz˘a care si ce sunt operat iile elementare .

Denit ¸ia 1 O operat ie elementar˘ a este o operat ie al c˘ arui timp de execut ie poate m˘ arginit superior de o constant˘ a care depinde numai de particularitatea imple-ment˘ arii (calculator, limbaj de programare etc).

55

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 68/518

56 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

Deoarece ne intereseaz˘a timpul de executie ın limita unei constante multi-plicative, vom considera doar num˘ arul operat¸iilor elementare executate ıntr-unalgoritm, nu si timpul exact de execut ¸ie al operat iilor respective.

Este foarte important ce anume denim ca operat ie elementar˘ a . Este adunareao operat ie elementara? Teoretic nu este, pentru c˘ a depinde de lungimea celor doioperanzi. Practic, pentru operanzi de lungime rezonabil˘ a putem s a consider am caadunarea este o operat ie elementar˘ a . Vom considera ın continuare c˘ a adun arile,scaderile, ınmult ¸irile, ımp˘art irile, operat¸iile modulo (restul ımp˘ aart irii ıntregi),operat iile booleene, comparat ¸iile si atribuirile sunt operat ii elementare .

Uneori ecient a difer a dac a tinem cont numai de unele operat ¸ii elementare sile ignoram pe celelalte (de exemplu la sortare: comparat ¸ia si interschimbarea). Deaceeaın analiza unor algoritmi vom considera o anumit˘ a operat ie elementar˘a, careeste caracteristic˘ a algoritmului, ca operat ¸ie barometru, neglijˆ andu-le pe celelalte.

De multe ori, timpul de executie al unui algoritm poate varia pentru cazuride marime identic˘a. De exemplu la sortare, dac˘ a introducem un sir de n numeregata sortat, timpul necesar va cel mai mic dintre timpii necesari pentru sortareaoricarui alt sir format din n numere. Spunem c˘a avem de-a face cu cazul cel mai favorabil . Daca sirul este introdus ın ordine invers˘ a, avem cazul cel mai defavorabil si timpul va cel mai mare dintre timpii de sortare a sirului de n numere.

Exist a algoritmi ın care timpul de execut ¸ie nu depinde de cazul considerat.Daca dimensiunea problemei este mare, ımbun˘ at atirea ordinului algoritmului

este esent ial a, ın timp ce pentru timpi mici este sufcient˘ a performant¸a hardware.Elaborarea unor algoritmi ecient ¸i presupune cunostint ¸e din diverse domenii

(informatic˘a, matematic˘ a si cunostiint ¸e din domeniul c˘aruia ıi apart ¸ine problemapractic˘a a carui model este studiat, atunci cˆ and este cazul).

Exemplul 1 Elaborat i un algoritm care returneaz˘ a cel mai mare divizor comun (cmmdc) a doi termeni de rang oarecare din sirul lui Fibonacci.

Sirul lui Fibonacci, f n = f n −1 + f n −2 , este un exemplu de recursivitate ıncascad a si calcularea efectiv˘ a a celor doi termeni f m f n , urmat˘a de calculul celuimai mare divizor al lor, este total neindicat˘ a. Un algoritm mai bun poate obt ¸inutdaca tinem seama de rezultatul descoperit de Lucas ın 1876:

cmmdc (f m , f n ) = f cmmdc (m,n )

Deci putem rezolva problema calculˆ and un singur termen al sirului lui Fibonacci.Exist a mai mult i algoritmi de rezolvare a unei probleme date. Prin urmare,

se impune o analiz a a acestora, ın scopul determin˘ arii ecient ei algoritmilor derezolvare a problemei si pe cˆat posibil a optimalit˘ atii lor. Criteriile ın funct ¸iede care vom stabili ecient¸a unui algoritm sunt complexitatea spat iu (memorieutilizat˘a) si complexitatea timp (num arul de operat¸iilor elementare).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 69/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 70/518

58 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

4.2 Notat ¸ia asimptotica

4.2.1 Denire si proprietat ¸i

Denit ¸ia 2 Numim ordinul lui f , mult imea de funct ii

O(f ) = t : N →R + |∃c > 0,∃n0∈N a.ı. t(n) ≤cf (n),∀n > n 0 (4.2.1)

Rezult a ca O(f ) este mult imea tuturor funct ¸iilor m arginite superior de unmultiplu real pozitiv al lui f , pentru valori sucient de mari ale argumentului.

Daca t(n)∈O(f ) vom spune c a t este de ordinul lui f sau ın ordinul lui f .

Fie un algoritm dat si o funct ¸ie t : N →R + , astfel ıncˆat o anumit˘a imple-mentare a algoritmului s˘ a necesite cel mult t(n) unit at i de timp pentru a rezolvaun caz de marime n.

Principiul invariant ¸ei ne asigur a ca orice implementare a algoritmului necesit˘ aun timp ın ordinul lui t. Mai mult, acest algoritm necesit˘ a un timp ın ordinul luif pentru orice functie f : N →R + pentru care t ∈O(f ). In particular t∈O(t).Vom c auta s a gasim cea mai simpl a functie astfel ıncˆat t∈O(f ).

Pentru calculul ordinului unei funct ¸ii sunt utile urm˘ atoarele propriet˘ at i:

Proprietatea 1 O(f ) = O(g)⇐⇒f ∈O(g) si g∈O(f )

Proprietatea 2 O(f )⊂O(g)⇐⇒f ∈O(g) si g /∈O(f )

Proprietatea 3 O(f + g) = O(max( f, g ))Pentru calculul mult ¸imilor O(f ) si O(g) este util a proprietatea urm˘ atoare:

Proprietatea 4 Fie f, g : N →R + . Atunci

limn →∞

f (n)g(n) ∈

R +⇒O(f ) = O(g)

limn →∞

f (n)g(n)

= 0⇒O(f )⊂O(g).

Reciproca nu este ın general valabil˘ a.Fie de exemplu, t(n) = n2 + 3 n + 2, atunci

limn →∞

n2 + 3 n + 2n2 = 1 =⇒O(n2 + 3 n + 2) = O(n2)

limn →∞

n2 + 3 n + 2n3 = 0 =⇒O(n2 + 3 n + 2) ⊂O(n3)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 71/518

4.2. NOTATIA ASIMPTOTIC ˘ A 59

limn

→∞

ln(n)

√n

= limn

→∞

1n1

2√n

= limn

→∞

2

√n

= 0 =

O(ln( n))

O(√n)

dar O(√n)⊂O(ln( n)Daca p este un polinom de gradul m ın variabila n , atunci O( p) = O(nm ).Notat ia asimptotic˘ a deneste o relat¸ie de ordine part¸ial a ıntre funct ¸ii.Pentru f, g : N →R∗not am f ≺g daca O(f )⊆O(g).Aceast a relat ie are propriet˘ atile corespunz˘atoare unei relat ¸ii de ordine, adic˘a:a) reexivitate: f ≺f b) antisimetrie: dac˘ a f ≺g si g≺f atunci f = gc) tranzitivitate: f ≺g si g≺h, implica f ≺h.Dar nu este o relat¸ie de ordine! Exist˘a si funct ii astfel ıncˆ at f ≺g (f /∈O(g))

si g≺f (g /∈O(f )). De exemplu f (n) = n, g(n) = n1+sin( n ) .Putem deni si o relat ¸ie de echivalent a: f

≡g, dac a O(f ) = O(g). In

mult imea O(f ) putem ınlocui orice funct ¸ie cu o funct ie echivalent˘a cu ea. Deexemplu: ln( n) ≡log(n) ≡log2(n).

Not and cu O(1) mult imea funct iilor m arginite superior de o constant˘ a siconsider and m∈N , m ≥2, obtinem ierarhia:

O(1)⊂O(log(n))⊂O(√n)⊂O(n)⊂O(n ·log(n))⊂O(nm )⊂O(2n )⊂O(n!)

si evident O(n2)⊂O(n3)⊂...⊂O(nm ) pentru m ≥4.Aceast a ierarhie corespunde ierarhiei algoritmilor dup˘ a criteriul performant ¸ei.

Pentru o problem˘ a dat a, dorim sa realiz˘am un algoritm cu un ordin situat cˆ at maiın stˆanga ın aceast˘ a ierarhie.

Notatia O(f ) este pentru a delimita superior timpul necesar unui algoritm.Not am T

A(n) timpul necesar execut ¸iei algoritmului A.

Fie f : N →R∗+ o functie arbitrar˘ a. Spunem c a algoritmul este de ordinul lui f (n) (si not˘am T A (n)∈O(f (n))), dac a si numai dac˘a exist a c > 0 si n0∈

N ,astfel ıncˆat T A (n) ≤c ·f (n), ∀n ≥n0 .

De exemplu:a) Dac a T A (n) = 3 n +2, atunci T A (n)∈O(n), pentru c˘a 3n +2 ≤4n,∀n ≥2.Mai general, dac˘a T A (n) = a ·n + b, a > 0, atunci T A (n)∈O(n) pentru c˘a

exist a c = a + 1 > 0 si n0 = b∈N , astfel ıncˆat a ·n + b ≤(a + 1) ·n,∀n ≥b.

b) Dac a T A (n) = 10 n2 + 4 n + 2, atunci T A (n) ∈O(n2), pentru c˘a 10n2 +4n + 2 ≤11n2 ,∀n ≥5.

Mai general, dac˘a T A(n) = an 2 + bn + c, a > 0, atunci T A(n) ∈O(n2),pentru c˘a an 2 + bn + c ≤(a + 1) n2 ,∀n ≥max (b, c) + 1.

c) Dac a T A (n) = 6

·2n + n2 , atunci T A(n)

O(2n ), pentru c˘a T A (n)

≤7 ·2n ,∀n ≥4.Daca T A (n) = ak nk + ak−1n k−1 + ... + a1n + a0 , atunci T A(n) ∈O(nk ).

Aceasta rezult˘a din: T A (n) = |T A (n)| = |ak nk + ak−1nk−1 + ... + a1n + a0| ≤|ak |n k + |ak−1|n k−1 + ... + |a1|n + |a0| ≤(|ak |+ |ak−1|+ ... + |a1|+ |a0|)nk ,∀n ≥1si aleg and c = |ak |+ |ak−1|+ ... + |a1|+ |a0| si n = 1 rezult˘a T A (n)∈O(nk ).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 72/518

60 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

4.2.2 Clase de complexitate

Notat ia O ofera o limit a superioar a a timpului de execut¸ie a unui algoritm.Un algoritm cu T A (n) ∈O(1) necesit a un timp de execut¸ie constant. Un

algoritm cu T A (n) ∈O(n) se numeste liniar . Daca T A (n)∈O(n2) algoritmul senumeste p˘ atratic , iar dac a T A (n)∈O(n3), cubic. Un algoritm cu T A (n)∈O(nk )se numeste polinomial , iar dac a T A (n)∈O(2n ) algoritmul se numeste exponent ial .

Tabelul urm˘ator ilustreaz˘a comportarea a cinci din cele mai importantefunct ii de complexitate.

O(log(n)) O(n) O(n.log (n)) O(n2) O(n3) O(2n )(logaritmic) (liniar) (log-liniar) (p˘ atratic) cubic (exponent ¸ial)

0 1 0 1 1 21 2 2 4 8 42 4 8 16 64 163 8 24 64 512 2564 16 64 256 4096 655365 32 160 1024 32768 4294967296

Tabelul 4.1: Funct ¸ii de complexitate

Daca T A (n)∈O(2n ), pentru n = 40, pe un calculator care face 10 9 de operat iipe secund a, sunt necesare aproximativ 18 minute. Pentru n = 50, acelasi programva rula 13 zile pe acest calculator, pentru n = 60, vor necesari peste 310 ani, iarpentru n = 100 aproximativ 4 .1013 ani.

Utilitatea algoritmilor polinomiali de grad mare este de asemenea limitat˘ a.

De exemplu, pentru O(n10

), pe un calculator care execut˘ a 109

operat ii pe secund asunt necesare 10 secunde pentru n = 10, aproximativ 3 ani pentru n = 100 si circa3.1013 ani pentru n = 1000.

Uneori este util s˘a determin˘am si o limit a inferioar a pentru timpul de execut ¸iea unui algoritm. Notat ¸ia matematic˘ a este Ω.

Denit ¸ie: Spunem c a T A (n)∈Ω(f (n)) dac a si numai dac˘a ∃c > 0 si n0∈N

astfel ıncˆat T A (n) ≥c ·f (n), ∀n ≥n0 .De exemplu:a) dac a T A (n) = 3 n +2, atunci T A (n)∈Ω(n), pentru c˘a 3n +2 ≥3n,∀n ≥1;b) dac a T A (n) = 10 n2 +4 n+2, atunci T A (n)∈Ω(n), pentru c˘a 10n2 +4 n +2 ≥n2,∀n ≥1;c) dac a T A (n) = 6 ·2n + n2 , atunci T A (n)∈Ω(2n ), pentru c˘a 6·2n + n2 ≥2n ,

n

≥1.Exist a funct ii f care constituie atˆ at o limit a superioar˘a cat si o limit˘a infe-

rioar a a timpului de execut¸ie a algoritmului. De exemplu, dac˘ a T A (n) = ak nk +ak−1nk−1 + ... + a1n + a0 , ak > 0 atunci T A (n)∈Ω(n k ).

Denit ¸ie : Spunem c a T A (n)∈Θ(f (n)) dac a si numai dac˘a ∃c1 , c2 > 0 sin0∈

N astfel ıncˆat c1 ·f (n) ≤T A (n) ≤c2 ·f (n), ∀n ≥n0 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 73/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 74/518

62 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

4.2.4 Analiza asimptotica a structurilor fundamentale

Consider am problema determin˘ arii ordinului de complexitate ın cazul cel maidefavorabil pentru structurile algoritmice: secvent ¸ial a, alternativ˘ a si repetitiv˘ a.

Presupunem c˘a structura secvent ¸ial a este constituit˘ a din prelucr˘arile A1 , A2 ,..., Ak si ecare dintre acestea are ordinul de complexitate O(gi (n)) , 1 ≤ i ≤ n.Atunci structura va avea ordinul de complexitate O(max g1(n),...,g k (n)).

Daca condit ia unei structuri alternative are cost constant iar prelucr˘ arilecelor dou a variante au ordinele de complexitate O(g1(n)) respectiv O(g2(n)) atuncicostul structurii alternative va O(max g1(n), g2(n)).

In cazul unei structuri repetitive pentru a determina ordinul de complexitateın cazul cel mai defavorabil se consider˘ a num arul maxim de iterat ¸ii. Dac a acestaeste n iar ın corpul ciclului prelucr˘ arile sunt de cost constant atunci se obt ¸ineordinul O(n).

4.3 Exemple

4.3.1 Calcularea maximului

Fiind date n elemente a1 , a 2 ,...,a n , sa se calculeze max a1 , a 2 ,...,a n .

max = a[1];for i = 2 to n do

if a[i] > maxthen max = a[i];

Vom estima timpul de execut ¸ie al algoritmului ın funct ¸ie de n, num arul dedate de intrare. Fiecare iterat ¸ie a ciclului for o vom considera operat¸ie elementar˘a.Deci complexitatea algoritmului este O(n), at at ın medie cˆat si ın cazul cel maidefavorabil.

4.3.2 Sortarea prin select ¸ia maximuluiSort am cresc ator vectorul a, care are n componente.

for j=n,n-1,...,2

max=a[1];pozmax=1;for i=2,3,...,j

if a[i]>max a[i]=max; pozmax=i;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 75/518

4.3. EXEMPLE 63

a[pozmax]=a[j];a[j]=max;

Estim am complexitatea algoritmului ın funct ¸ie de n, dimensiunea vectorului.La ecare iterat¸ie a ciclului for exterior este calculat max a1 , a 2 ,...,a j si plasatpe pozit ia j , elementele de la j +1 la n ind deja plasate pe pozit ¸iile lor denitive.

Conform exemplului anterior, pentru a calcula max a1 , a 2 ,...,a j sunt nece-sare j −1 operat ii elementare, ın total 1 + 2 + ... + ( n −1) = n(n −1)/ 2. Decicomplexitatea algoritmului este de O(n2). Sa observ am ca timpul de execut¸ie esteindependent de ordinea init ¸ial a a elementelor vectorului.

4.3.3 Sortarea prin insert ¸ieEste o metod˘a de asemenea simpl˘a, pe care o utiliz am adesea c and ordon˘am

cart ile la jocuri de c art i.

for i=2,3,...,n

val=a[i];poz=i;while a[poz-1]>val

a[poz]=a[poz-1];poz=poz-1;

a[poz]=val;

Analiz am algoritmul ın funct ¸ie de n, dimensiunea vectorului ce urmeaz˘ a a sortat. La ecare iterat ¸ie a ciclului for elementele a1 , a 2 ,...,a i−1 sunt deja ordonatesi trebuie s˘a inser am valorea a[i] pe pozitia corect˘aın sirul ordonat. In cazul cel maidefavorabil, c and vectorul este init ¸ial ordonat descresc˘ ator, ecare element a[i] va plasat pe prima pozit ¸ie, deci ciclul while se execut˘a de i−1 ori. Consider and dreptoperat ie elementar˘a comparat¸ia a[ poz−1] > val urmat˘a de deplasarea elementuluide pe pozit ia poz −1, vom avea ın cazul cel mai defavorabil 1 + 2 + ... + ( n −1) =n(n −1)/ 2 operat ii elementare, deci complexitatea algoritmului este de O(n2).

Sa analiz am comportarea algoritmului ın medie. Consider˘ am ca elementelevectorului sunt distincte si c˘ a orice permutare a lor are aceeasi probabilitate deaparit ie. Atunci probabilitatea ca valoarea a

isa e plasat a pe pozit ia k ın sirul

a1 , a2 ,...,a i , k ∈ 1, 2,....,i este 1/i . Pentru i xat, num˘arul mediu de operat ¸iielementare este:

i

k=1

1i ·(k −1) =

1i ·

i

k=1

(k −1) =1i

i(i + 1)2 −i =

i + 12 −1 =

i −12

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 76/518

64 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

Pentru a sorta cele n elemente sunt necesare

n

i =2

i −12

= 12

n(n + 1)2 −1 −(n −1) = n

2(n + 1)

2 −1 = n(n −1)4

operat ii elementare. Deci complexitatea algoritmului ın medie este tot O(n2).

4.3.4 Sortarea rapida (quicksort)Acest algoritm a fost elaborat de C.A.R. Hoare ın 1960 si este unul dintre cei

mai utilizat i algoritmi de sortare.

void quicksort(int st, int dr)

int m;if st<dr

m=divide(st, dr);quicksort(st, m-1);quicksort(m+1, dr);

Init ial apel am quicksort(1,n) .Funct ia divide are rolul de aplasa primul element (a[st]) pe pozit ¸ia sa corect˘a

ın sirul ordonat. In st anga sa se vor g asi numai elemente mai mici, iar ın dreaptanumai elemente mai mari decˆ at el.

int divide(int st, int dr)

int i, j, val;val=a[st];i=st; j=dr;while(i<j)

while((i<j) && (a[j] >= val)) j=j-1;a[i]=a[j];while((i<j) && (a[i] <= val)) i=i+1;a[j]=a[i];

a[i]=val;return i;

Observat¸ie : Vectorul a este considerat variabil˘ a global a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 77/518

4.3. EXEMPLE 65

In cazul cel mai defavorabil, cˆand vectorul a era init ial ordonat, se fac n −1apeluri succesive ale procedurii quicksort , cu parametrii (1 , n ), (1, n

−1), ..., (1 , 2)

(dac a vectorul a era init¸ial ordonat descresc˘ ator) sau (1 , n ), (2, n ), ..., ( n −1, n )(dac a vectorul a era ordonat cresc˘ator).

La ecare apel al procedurii quicksort este apelat˘a funct ia divide(1,i)(respectiv divide(i, n) ) care efectueaz a i −1, (respectiv n − i −1) operat iielementare. In total num˘arul de operat¸ii elementare este ( n −1)+( n −2)+ ... +1 =n(n −1)/ 2. Complexitatea algoritmului ın cazul cel mai defavorabil este de O(n2).

Sa analiz am comportarea algoritmului ın medie. Vom consider˘ am ca oricepermutare a elementelor vectorului are aceeasi probabilitate de aparit ¸ie si not˘amcu T n num arul de operat¸ii elementare efectuate pentru a sorta n elemente.

Probabilitatea ca un element al vectorului s˘ a e plasat pe pozit ia k ın vectorulordonat, este de 1 /n .

T n =0, daca n = 0 sau n = 11n

nk=1 (T k−1 + T n −k ) + ( n −1), dac a n > 1

(pentru a ordona cresc˘ ator n elemente, determin˘ am pozit ia k ın vectorul ordonat aprimului element, ceea ce necesit˘ a n −1 operat ii elementare, sort˘ am elementele dinst anga, ceea ce necesit˘a T k−1 operat ii elementare, apoi cele din dreapta, necesitˆ andT n −k operat ii elementare).

Problema se reduce la a rezolva relat ¸ia de recurent¸a de mai sus. Mai ıntˆaiobserv am ca

T 0 + T 1 + ... + T n −1 = T n −1 + ... + T 1 + T 0 .

Deci,

T n = n −1 + 2n

n

k =1

T k−1

Inmult im ambii membri ai acestei relat ¸ii cu n. Obt inem:

nT n = n(n −1) + 2n

k =1

T k−1

Scazand din aceast˘a relat ie, relat ia obt inut˘a pentru n −1, adic a

(n −1)T n −1 = ( n −1)(n −2) + 2n −1

k=1

T k−1

obtinemnT n −(n −1)T n −1 = n(n −1) −(n −1)(n −2) + 2 T n −1

de unde rezult˘anT n = 2( n −1) + ( n + 1) T n −1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 78/518

66 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

Imp art ind ambii membri cu n(n + 1) obt inem

T nn + 1

=T n −1

n+

2(n −1)n(n + 1)

=T n −2

n −1+

2(n −1)n(n + 1)

+2(n −2)(n −1)n

= ... =T 23

+2n

k=3

k −1k(k + 1)

Deci

T nn + 1

=T 23

+2n

k=3

1k + 1 −

1k

+1

k + 1=

T 23

+2

n + 1+2

n

k =3

1k ≈2

n

k=1

1k ≈2 ln n

Deci, ın medie, complexitatea algoritmului este de O(n log n).

4.3.5 Problema celebrit˘ at iiNumim celebritate o persoan a care este cunoscut˘a de toat˘a lumea, dar nu

cunoaste pe nimeni. Se pune problema de a identica o celebritate, dac˘ a exist a,ıntr-un grup de n persoane pentru care relat ¸iile dintre persoane sunt cunoscute.

Putem reformula problema ın limbaj de grafuri astfel: ind dat un digraf cun varfuri, vericat¸i dac a exist a un v arf cu gradul exterior 0 si gradul interior n −1.

Reprezent˘am graful asociat problemei prin matricea de adiacent ¸a an ×n

a i,j =1, daca persoana i cunoaste persoana j ;0, altfel .

O prim a solut ie ar s a calcul am pentru ecare persoan˘ a p din grup num˘arul

de persoane pe care p le cunoaste ( out ) si num arul de persoane care cunosc per-soana p (in ). Cu alte cuvinte, pentru ecare vˆ arf din digraf calcul˘am gradul interiorsi gradul exterior. Dac˘ a gasim o persoan a pentru care out = 0 si in = n−1, aceastava celebritatea c˘autat˘a.

celebritate=0;for p=1,2,...,n

in=0; out=0;for j=1,2,...,n

in=in+a[j][p];out=out+a[p][j];

if (in=n-1) and (out = 0) celebritate=p;

if celebritate=0 writeln(’Nu exista celebritati !’)

else writeln(p, ’ este o celebritate.’);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 79/518

4.4. PROBLEME 67

Se poate observa cu usurint ¸a ca algoritmul este de O(n2). Putem ımbun˘ at at ialgoritmul f acand observat¸ia c a atunci c and test˘am relat iile dintre persoanele x siy apar urm˘atoarele posibilit˘atii:

a[x, y] = 0 si ın acest caz y nu are nici o sans˘a sa e celebritate, saua[x, y] = 1 si ın acest caz x nu poate celebritate.Deci la un test elimin˘am o persoan a care nu are sanse s˘a e celebritate.Facand succesiv n −1 teste, ın nal vom avea o singur˘ a persoan a candidat

la celebritate. R˘amane sa calcul am num arul de persoane cunoscute si num˘ arul depersoane care ıl cunosc pe acest candidat, singura celebritate posibil˘ a.

candidat=1;for i=2,n

if a[candidat][i]=1 candidat=i;out=0;

in=0;for i=1,n

in=in+a[i][candidat];out=out+a[candidat][i];

if (out=0) and (in=n-1) write(candidat, ’ este o celebritate .’)

else write(’Nu exista celebritati.’);

In acest caz algoritmul a devenit liniar.

4.4 Probleme

4.4.1 Probleme rezolvate

Problema 1 Care armat ii sunt adevarate:a) n2∈O(n3)

b) n3∈O(n2)

c) 2n +1∈O(2n )

d) (n + 1)! ∈O(n!)e)

f : N

→R∗, f

O(n) =

f 2

O(n2) f )∀f : N →R∗, f ∈O(n) =⇒2f

∈O(2n )

Rezolvare:a) Armat ia este adevarat˘ a pentru c˘a: limn →∞

n 2

n 3 = 0 =⇒n2∈O(n3).

b) Armat ia este fals a pentru c˘a: limn →∞n 3

n 2 = ∞

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 80/518

68 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

c) Armat ia este adevarat˘ a pentru c˘a: limn →∞2n +1

2n = 2 =⇒O(2n +1 ) =O(2n ).

d) Armat ia este fals a pentru c˘a: limn →∞(n +1)!

n ! = lim n →∞n +1

1 = ∞e) Armat ia este adevarat˘ a pentru c˘a: f ∈O(n) =⇒ ∃c > 0 si ∃n0 ∈N

astfel ıncˆat f (n) < c ·n, ∀n > n 0 . Rezult a ca ∃c1 = c2 astfel ıncˆa f 2(n) < c 1 ·n2 ,

∀n > n 0 , deci f 2∈O(n2).e) Armat ia este adevarat˘ a pentru c˘a: f ∈O(n) =⇒ ∃c > 0 si ∃n0∈

N astfelınc at f (n) < c ·n,∀n > n 0 . Rezult a ca ∃c1 = 2 c astfel ıncˆa 2f (n ) < 2c·n = 2 c ·2n =c1 ·2n ,∀n > n 0 , deci 2f

∈O(2n ).

Problema 2 Ar˘ atat i c˘ a log n∈O(√n) dar √n /∈O(log n).

Indicat ie: Prelungim domeniile funct ¸iilor pe R + , pe care sunt derivabile, si aplic˘ amrelula lui L’H ospital pentru log n/ √n.

Problema 3 Demonstrat i urm˘ atoarele armat ii:

i) loga ∈Θ(log b n), pentru oricare a,b > 1

ii )n

i=1

ik∈Θ(nk+1 ), pentru oricare k∈

N

iii )n

i=1

1i ∈

Θ(n log n)

iv) log n!∈Θ(n log n)

Indicat ii: La punctul iii ) se tine cont de relat¸ia

i =1

1i ≈γ + ln n

unde γ ≈0.5772 este constanta lui Euler.La punctul iv) din n! < n n , rezult a log n! < n log n, deci log n!∈O(n log n).

Trebuie s˘a gasim si o margine inferioar˘a. Pentru 0 ≤ i ≤ n −1 este adev arat arelat ia

(n −i)( i + 1) ≥n

Deoarece

(n!)2 = ( n ·1)(( n −1) ·2)(( n −2) ·3)...(2 ·(n −1))(1 ·n) ≥nn

rezult a 2log n! ≥n log n, adic a log n! ≥0.5n log n, deci log n!∈Ω(n log n).Relat ia se poate demonstra si folosind aproximarea lui Stirling

n! ≈√2πnne

n(1 + Θ(1 /n ))

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 81/518

4.4. PROBLEME 69

4.4.2 Probleme propuse

1. Aratat i ca:a) n3 + 10 6n∈Θ(n3)b) n2n

+ 6 ·2n∈Θ()( n2n

)c) 2n2 + n log n∈Θ(n2)d) nk + n + nk log n∈Θ(nk log n), k ≥1e) loga n∈Θ(log b n), a,b > 0, a = 1 , b = 1.2. Pentru oricare doua functii f, g : N →R∗demonstrat¸i ca

O(f + g) = O(max( f, g )) (4.4.1)

unde suma si maximul se iau punctual.3. Fie f, g : N

→R + Demonstrat¸i ca:

i) limn →∞

f (n)g(n) ∈

R +⇒O(f ) = O(g), ii ) lim

n →∞f (n)g(n)

= 0 ⇒O(f )⊂O(g)

Observat¸ie: Implicat iile inverse nu sunt ın general adev˘ arate, deoarece sepoate ıntampla ca limitele s˘ a nu existe.

4. Demonstrat¸i prin induct¸ie ca pentru a determina maximul a n numere suntnecesare n −1 comparat ii.

5. Care este timpul de execut ¸ie a algoritmului quicksort pentru un vectorcu n componente egale?

6. Sa consider am urm atorul algoritm de sortare a unui vector a cu n compo-nente:

do

ok=true;for i=1,n-1

if a[i]>a[i+1] aux=a[i]; a[i]=a[i+1]; a[i+1]= aux; ok=false;

while !ok;

Analizat i algoritmul ın medie si ın cazul cel mai defavorabil.7. Analizat i complexitatea algoritmului de interclasare a doi vectori ordonat ¸i,

a cu n componente, respectiv b cu m componente :

i=1; j=1; k=0;while (i <= n) and (j <= m)

k=k+1;if a[i] < b[j] c[k]=a[i]; i=i+1;

else c[k]=b[j]; j=j+1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 82/518

70 CAPITOLUL 4. ANALIZA COMPLEXIT ˘ ATII ALGORITMILOR

for t=i,n k=k+1; c[k]=a[t]; for t=j,m k=k+1; c[k]=b[t];

8. Fiind dat a, un vector cu n componente distincte, vericat ¸i dac a o valoaredat a x se gaseste sau nu ın vector. Evaluat ¸i complexitatea algoritmului ın cazulcel mai defavorabil si ın medie.

9. Se da a un vector cu n componente. Scriet¸i un algoritm liniar care s˘ adetermine cea mai lung˘ a secvent a de elemente consecutive de valori egale.

10. Fie T un text. Vericat¸iın timp liniar dac˘ a un text dat T ′ este o permutarecircular a a lui T .

11. Fie X = ( x1 , x2 ,...,x n ) o secvent a de numere ıntregi. Fiind dat x, vomnumi multiplicitate a lui x ın X num arul de aparit¸ii ale lui x ın X . Un element senumeste majoritar dac˘ a multiplicitatea sa este mai mare decˆ at n/ 2. Descriet i un

algoritm liniar care s˘a determine elementul majoritar dintr-un sir, dac˘ a un astfelde element exist˘a.12. Fie a1 , a 2 ,...,a n si b1 , b2 ,...,bm , dou a mult imi de numere ıntregi,

nenule ( m < n ). Sa se determine x1 , x2 ,...,x m , o submult ime a mult imii a1 , a 2 ,...,a n pentru care funct ¸ia f (x1 , x2 ,...,x m ) = a1x1 + a2x2 + ... + an xm ia valoare maxim˘a,prin doi algoritmi de complexitate diferit˘ a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 83/518

Capitolul 5

Recursivitate

Denit iile prin recurent ¸ a sunt destul de curente ın matematic˘ a: progresiaaritmetic˘a, progresia geometric˘a, sirul lui Fibonacci, limite de siruri, etc.

5.1 Funct ¸ii recursive

5.1.1 Funct ¸ii numerice

Pentru calculul termenilor sirului lui Fibonacci, a transcriere literal˘ a a for-mulei este urm˘atoarea:

static int fib(int n) if (n <= 1)

return 1;else

return fib(n-1) + fib(n-2);

fib este o funct ie care utilizeaz˘a propriul nume ın denit ¸ia proprie. De asemenea,daca argumentul n este mai mic dec at 1 returneaz˘ a valoarea 1 iar ın caz contrarreturneaz˘a f ib (n −1) + f ib (n −2).

In Java este posibil, ca de altfel ın multe alte limbaje de programare (Fortran,Pascal, C, etc), s˘a denim astfel de funct¸ii recursive . Dealtfel, toate sirurile deniteprin recurent¸a se scriu ın aceast˘a manier a ın Java, cum se poate observa dinurm atoarele dou˘a exemple numerice: factorialul si triunghiul lui Pascal.

71

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 84/518

72 CAPITOLUL 5. RECURSIVITATE

static int fact(int n) if (n != 1)

return 1;else

return n * fact (n1);

fibo(4)

fibo(0)

fibo(3) fibo(2)

fibo(2) fibo(1)

fibo(1)

fibo(1)

fibo(0)

fact(4)

fact(3)

fact(2)

fact(1)

static int comb(int n, int p) if ((p == 0) | | (p == n))

return 1;else

return comb(n-1, p) + comb(n-1, p-1);

comb(4,2)

comb(3,2)

comb(2,2)

comb(3,1)

comb(2,1) comb(2,0)

comb(1,1) comb(1,0)

comb(2,1)

comb(1,1) comb(1,0)

Ne putem ıntreba cum efectueaz˘ a Java calculul funct¸iilor recursive. Putemsa raspundem prin urm˘ arirea calculelor ın cazul calculului lui fibo (4). Reamintimca argumentele sunt transmise prin valoare ın acest caz, iar un apel de funct ¸ieconst a ın evaluarea argumentului, apoi lansarea ın execut ¸ie a funct iei cu valoarea

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 85/518

5.1. FUNCTII RECURSIVE 73

argumentului. Deci

fibo(4) → fibo(3) + fibo(2)

→ (fibo (2) + fibo (1)) + fibo (2)

→ (( fibo (1) + fibo (1)) + fibo(1)) + fibo (2)

→ ((1 + fibo(1)) + fibo (1)) + fibo (2)

→ ((1 + 1) + fibo (1)) + fibo (2)

→ (2 + fibo (1)) + fibo(2)

→ (2 + 1) + fibo(2)

→ 3 + fibo(2)

→ 3 + ( fibo (1) + fibo (1))

→3 + (1 + fibo (1))

→ 3 + (1 + 1)

→ 3 + 2

→ 5

Exist a deci un num ar semnicativ de apeluri succesive ale funct ¸iei f ib (9apeluri pentru calculul lui fibo(4)). S a not am prin Rn num arul apelurilor funct ¸ieifibo pentru calculul lui fibo(n). Evident R0 = R1 = 1, si Rn = 1 + Rn −1 + Rn −2pentru n > 1. Pun and R ′n = Rn +1, obt inem c a R ′n = R ′n −1 + R ′n −2 pentru n > 1,si R ′1 = R ′0 = 2. Rezult˘a R ′n = 2 ·fibo (n) si de aici obt inem c a Rn = 2 ·fibo (n)−1.Num arul de apeluri recursive este foarte mare! Exist˘ a o metod a iterativ˘a simpl acare permite calculul lui fibo(n) mult mai repede.

fibo(n)fibo(n −1) = 1 1

1 0 × fibo (n −1)fibo (n −2) = ... = 1 1

1 0

n

× 10

uv = 1 1

1 0 ×u0v0

static int fibo(int n) int u, v;int u0, v0;int i;u = 1 ; v = 1 ;for (i = 2; i <= n; ++i)

u0 = u; v0 = v;u = u0 + v0;v = v0;

return u;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 86/518

74 CAPITOLUL 5. RECURSIVITATE

Se poate calcula si mai repede folosind ultima form˘ a si calcul and putereamatricei ...

Pentru a rezuma, o regul˘ a bun a este s a nu ıncerc˘am sa intr am ın meandreledetaliilor apelurilor recursive pentru a ınt ¸elege sensul unei funct¸ii recursive. Ingeneral este sufucient s˘a ınt elegem sintetic funct ¸ia. Funct¸ia lui Fibonacci este uncaz particular ın care calculul recursiv este foarte lung. Cam la fel se ıntˆ ampl a(dac a nu chiar mai r˘au!) si cu triunghiul lui Pascal. Dar nu aceasta este situat ¸iaın general. Nu numai c˘ a scrierea recursiv˘a se poate dovedi ecace, dar ea estetotdeauna natural˘ a si deci cea mai estetic˘a. Ea nu face dec at s a respecte denit¸iamatematic˘a prin recurent¸a. Este o metod˘a de programare foarte puternic˘ a.

5.1.2 Funct ¸ia lui Ackerman

Sirul lui Fibonacci are o crestere exponent ¸ial a. Exist a funct ii recursive care auo crestere mult mai rapid˘ a. Prototipul este funct ¸ia lui Ackerman. In loc sa denimmatematic aceast˘ a funct ie, este de asemenea simplu s˘ a dam denit ia recursiv˘a ınJava.

static int ack(int m, int n) if (m == 0)

return n+1;else

if (n == 0)return ack (m-1, 1);

elsereturn ack(m-1, ack(m, n-1));

Se poate verica c a ack (0, n ) = n + 1, ack(1, n ) = n + 2, ack (2, n ) ≈ 2n,ack (3, n ) ≈2n , ack(5, 1) ≈ack(4, 4) ≈265536 > 1080 , adic a num arul atomilor dinunivers [11].

5.1.3 Recursii imbricate

Funct ia lui Ackerman cont¸ine dou a apeluri recursive imbricate ceea ce deter-mina o crestere rapid˘ a. Un alt exemplu este ”funct ia 91” a lui MacCarty [11]:

static int f(int n) if (n > 100)

return n-10;else

return f(f(n+11));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 87/518

5.2. PROCEDURI RECURSIVE 75

Pentru aceast˘ a funct ie, calculul lui f (96) d a

f (96) = f (f (107)) = f (97) = ... = f (100) = f (f (111)) = f (101) = 91 .

Se poate ar ata c a aceast a funct ie va returna 91 dac˘ a n ≤ 100 si n −10 dacan > 100. Aceast a funct ie anecdotic˘a, care foloseste recursivitatea imbricat˘ a, esteinteresant˘a pentru c˘nu este evident c˘a o astfel de denit ie d a da acelasi rezultat.

Un alt exemplu este funct ¸ia lui Morris [11] care are urm˘atoarea form˘a:

static int g(int m, int n) if (m == 0)

return 1;else

return g(m-1, g(m, n));

Ce valoare are g(1, 0)? Efectul acestui apel de funct ¸ie se poate observa din

denit ia ei: g(1, 0) = g(0, g(1, 0)). Se declanseaz˘a la nesfarsit apelul g(1, 0). Deci,calculul nu se va termina niciodat˘ a!

5.2 Proceduri recursive

Procedurile, la fel ca si funct ¸iile, pot recursive si pot suporta apeluri recur-sive. Exemplul clasic este cel al turnurilor din Hanoi. Pe 3 tije din fat ¸a noastr˘a,numerotate 1, 2 si 3 de la stˆ anga la dreapta, sunt n discuri de dimensiuni diferite

plasate pe tija 1 formˆand un con cu discul cel mai mare la baz˘ a si cel mai mic ınvarf. Se doreste mutarea discurilor pe tija 3, mutˆ and numai cˆate un singur disc sineplas and niciodat˘a un disc mai mare peste unul mai mic. Un rat ¸ionament recur-siv permite scrierea solut¸iei ın cˆateva r anduri. Dac˘a n ≤1, problema este trivial˘ a.Presupunem problema rezolvat˘ a pentru mutarea a n −1 discuri de pe tija i petija j (1 ≤ i, j ≤3). Atunci, exist˘a o solutie foarte simpl˘a pentru mutarea celor ndiscuri de pe tija i pe tija j :

1. se mut a primele n−1 discuri (cele mai mici) de pe tija i pe tija k = 6 −i− j ,2. se mut a cel mai mare disc de pe tija i pe tija j ,3. se mut a cele n −1 discuri de pe tija k pe tija j .

static void hanoi(int n, int i, int j) if (n > 0)

hanoi (n-1, i, 6-(i+j));System.out.println (i + " -> " + j);hanoi (n-1, 6-(i+j), j);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 88/518

76 CAPITOLUL 5. RECURSIVITATE

Aceste c ateva linii de program arat˘ a foarte bine cum generalizˆ and problema,adic a mutarea de pe oricare tij˘ a i pe oricare tij˘a j , un program recursiv de cˆatevalinii poate rezolva o problem˘a apriori complicat˘ a. Aceasta este fort¸a recursivit˘at iisi a rat ionamentului prin recurent ¸a.

A B C A B C

A B CA B C

a) b)

c)d)

pasul 1

pasul 2

pasul 3

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 89/518

Capitolul 6

Analiza algoritmilorrecursivi

Am vazut ın capitolul precedent cˆ at de puternic˘a si util a este recursivitateaın elaborarea unui algoritm. Cel mai important cˆ astig al exprim˘ arii recursive estefaptul c a ea este natural˘ a si compact˘a.

Pe de alt a parte, apelurile recursive trebuie folosite cu discern˘ amant, deoarecesolicit a si ele resursele calculatorului (timp si memorie).

Analiza unui algoritm recursiv implic˘ a rezolvarea unui sistem de recurent ¸e.Vom vedea ın continuare cum pot rezolvate astfel de recurent ¸e.

6.1 Relat ¸ii de recurent ¸a

O ecuat ie ın care necunoscutele sunt termenii xn , xn +1 ,...x n + k ai unui sirde numere se numeste relat ie de recurent ˘ a de ordinul k. Aceast a ecuat ie poate satisf acut a de o innitate de siruri. Ca s˘ a putem rezolva ecuat ¸ia (relat¸ia derecurent a) mai avem nevoie si de condit¸ii init iale, adic a de valorile termenilorx0 , x1 ,...,x k−1 . De exemplu relat ia de recurent¸a

(n + 2) C n +1 = (4 n + 2) C n , pentru n ≥0, C 0 = 1

este de ordinul 1.

Daca un sir xn de numere satisface o formul˘a de formaa0xn + a1xn +1 + ... + ak xn + k = 0 , k ≥1, a i ∈

R , a 0 , a k = 0 (6.1.1)

atunci ea se numeste relat ie de recurent ˘ a de ordinul k cu coecient i constant i .Coecient ii sunt constant ¸i ın sensul c˘a nu depind de valorile sirului xn .

77

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 90/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 91/518

6.1. RELATII DE RECURENT ˘ A 79

este o solut ie a relat iei de recurent¸ a. Acest lucru se mai poate demonstra usor dac˘ atinem cont de faptul c˘ a o rad acin a multipl a de ordinul p a unui polinom P (x) esterad acin a si a polinoamelor derivate P ′(x), P ′′(x),...,P ( p−1) (x).

Solutia general˘a este suma dintre solut ¸ia general˘a corespunz atoare r˘ad acinilorsimple ale ecuat iei caracteristice si solut ¸ia general˘a corespunz atoare r˘ad acinilormultiple.

Daca ecuat ia caracteristic˘ a are r ad acinile simple r 1 , r 2 ,...,r s si r ad acinile mul-tiple r s 1 , r s +2 ,...,r s + t de multiplicitate p1 , p2 ,...,p t (s+ p1 + p2 + ... + pt = k), atuncisolut ia general˘a a relat iei de recurent¸ a este

xn = c1r n1 + c2r n

2 + ... + cs r ns +

c(1)1 + c(1)

2 n + ... + c(1) p1 −1n p1 −1 +

...

c( t )1 + c

( t )2 n + ... + c

(1) pt −1n

pt

−1

+

unde c1 ,...,c s , c(1)1 ,...,c (1)

p1 −1 ,...,c ( t )1 ,...,c ( t )

pt −1 sunt constante, care se pot determinadin condit iile init iale.

• Ecuat ¸ia caracteristica admite rad˘ acini complexe simpleFie r = ae ib = a(cos b + i sin b) o rad acin a complex a. Ecuat ia caracteristic˘ a

are coecient i reali, deci si conjugata ¯r = ae−ib = a(cos b −i sin b) este r ad acin apentru ecuat¸ia caracteristic˘ a. Atunci solut¸iile corespunz˘atoare acestora ın sistemulfundamental de solut ¸ii pentru recurent ¸a liniar˘a si omogen a sunt

x(1)n = an cos bn, x (2)

n = an sin bn.

• Ecuat ¸ia caracteristic˘ a admite rad˘ acini complexe multiple Dacaecuat ia caracteristic˘ a admite perechea de r˘ ad acini complexe

r = ae ib , r = ae−ib b = 0

de ordin de multiplicitate k, atunci solut iile corespunz˘atoare acestora ın sistemulfundamental de solut ¸ii sunt

x(1)n = an cos bn, x (2)

n = na n cos bn, ..., x (k )n = n k−1an cos bn,

x(k+1)n = an sin bn, x (k+2)

n = na n sin bn, ..., x (2 k )n = nk−1an sin bn,

Pentru a obt¸ine solut ia general˘a a recurent ei omogene de ordinul n cu coecient iconstant i se procedeaz a astfel:

1. Se determin a rad acinile ecuat iei caracteristice

2. Se scrie contribut¸ia ec arei r ad acini la solut ia general˘a.3. Se ınsumeaz˘a si se obt ine solut ia general˘a ın funct¸ie de n constantearbitrare.4. Daca sunt precizate condit ¸iile init iale atunci se determin˘ a constantelesi se obt ine o solut ie unic a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 92/518

80 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

6.2 Ecuat ¸ii recurente neomogene

6.2.1 O form˘ a simpl˘a

Consider am acum recurent¸e de urm atoarea form˘a mai general a

a0 tn + a1 tn −1 + ... + ak tn −k = bn p(n)

unde b este o constant˘a, iar p(n) este un polinom ın n de grad d. Ideea general aeste sa reducem un astfel de caz la o form˘a omogen a.

De exemplu, o astfel de recurent ¸a poate :

tn −2tn −1 = 3n

In acest caz, b = 3 si p(n) = 1. Inmult im recurent¸a cu 3, si obt¸inem

3tn −6tn −1 = 3 n +1

Inlocuind pe n cu n + 1 ın recurent ¸a init ial a, avem

tn +1 −2tn = 3 n +1

Scadem aceste dou˘a ecuat ii

tn +1 −5tn + 6 tn −1 = 0

Am obt inut o recurent ¸a omogen a. Ecuat ia caracteristic˘ a este:x2 −5x + 6 = 0

adic a (x −2)(x −3) = 0. Intuitiv, observ˘ am ca factorul ( x −2) corespunde p˘art iist angi a recurent¸ei init iale, ın timp ce factorul ( x −3) a ap arut ca rezultat alcalculelor efectuate pentru a sc˘ apa de partea dreapt˘ a.

Generaliz and acest procedeu, se poate ar˘ ata c a, pentru a rezolva ecuat ¸iainitial a, este sucient s a luam urm atoarea ecuat¸ie caracteristic˘ a:

(a0xk + a1xk−1 + + ak )(x −b)d+1 = 0

Odat˘a ce s-a obtinut aceast˘ a ecuat ie, se procedeaz˘a ca ın cazul omogen.Vom rezolva acum recurent ¸a corespunzatoare problemei turnurilor din Hanoi:

tn = 2 tn −1 + 1 , n = 1

iar t0 = 0. Rescriem recurent ¸a astfel

tn −2tn −1 = 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 93/518

6.2. ECUATII RECURENTE NEOMOGENE 81

care este de forma general˘a prezentat˘a la ınceput, cu b = 1 si p(n) = 1. Ecuat¸iacaracteristic˘a este atunci ( x

−2)(x

−1) = 0, cu solut iile 1 si 2. Solut ia general˘a a

recurent ei este:tn = c11n + c22n

Avem nevoie de dou˘a condit ii init iale. Stim c˘a t0 = 0; pentru a g˘asi cea de-adoua condit ie calcul am

t1 = 2 t0 + 1 = 1 .

Din condit iile init iale, obt inem

tn = 2 n −1.

Daca ne intereseaz˘a doar ordinul lui tn , nu este necesar s a calcul am efectivconstantele ın solut ¸ia general˘a. Dac a stim c˘a tn = c11n + c22n , rezult a tn

O(2n ).

Din faptul c a num arul de mut˘ari a unor discuri nu poate negativ sauconstant, deoarece avem ın mod evident tn ≥n, deducem c a c2 > 0. Avem atuncitn ∈Ω(2n ) si deci, tn ∈Θ(2n ). Putem obt¸ine chiar ceva mai mult. Substituindsolut ia general˘a ınapoi ın recurent ¸a init ial a, gasim

1 = tn −2tn −1 = c1 + c22n −2(c1 + c22n −1) = −c1

Indiferent de condit¸ia init ial a, c1 este deci −1.

6.2.2 O form˘ a mai generala

O ecuat ie recurent˘a neomogen a de forma mai general a este:

k

j =0

a j T n − j = bn1 · pd 1 (n) + bn

2 · pd2 (n) + ...

ın care pd (n) = nd + c1nd−1 + ... + cd

Ecuat ia caracteristic˘ a complet a este:

k

j =0

a j ·r k−j ·(r −b1)d 1 +1·(r −b2)d 2 +1

·... = 0

Exemplul 3: T n = 2 T (n −1) + n + 2 n , n ≥1, T 0 = 0 .Acestui caz ıi corespund b1 = 1, p1(n) = n, d1 = 1 si b2 = 2, p2(n) = 1,

d2 = 0, iar ecuat¸ia caracteristic˘ a complet a este:

(r −2)( r −1)2(r −2) = 0

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 94/518

82 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

cu solutia:

T (n) = c1 ·1n + c2 ·n ·2n + c3 ·2n + c4 ·n ·2n

T (0) = 0T (1) = 2 T (0) + 1 + 2 1 = 3T (2) = 2 T (1) + 2 + 2 2 = 12T (3) = 2 T (2) + 3 + 2 3 = 35

c1 + c3 = 0c1 + c2 + 2 c3 + 2 c4 = 3c1 + 2 c2 + 4 c3 + 8 c4 = 12c1 + 3 c2 + 8 c3 + 24 c4 = 35

c1 = −2c2 = −1c3 = 2c4 = 1

Deci

T (n) = −2 −n + 2 n +1 + n ·2n = O(n ·2n ).

6.2.3 Teorema master

De multe ori apare relat ¸ia de recurent¸ a de forma

T (n) = aT (n/b ) + f (n) (6.2.6)

unde a si b sunt constante iar f (n) este o funct ie (aplicarea metodei Divide et Impera conduce de obicei la o astfel de ecuat¸ie recurent˘a). Asa numita teorem˘ aMaster d a o metod a general a pentru rezolvarea unor astfel de recurent ¸e cand f (n)este un simplu polinom. Solut ¸ia dat˘a de teorema master este:

1. dac a f (n) = O n log b (a −ε ) cu ε > 0 atunci T (n) = Θ n log b a

2. dac a f (n) = Θ n log b a atunci T (n) = Θ n log b a lg n

3. daca f (n) = Ω n log b (a + ε ) si a ·f nb ≤c·f (n) cu c < 1 atunci T (n) = Θ ( f (n)).

Din p acate, teorema Master nu funct ¸ioneaz˘a pentru toate funct ¸iile f (n), simulte recurent¸e utile nu sunt de forma (6.2.6). Din fericire ıns˘ a, aceasta este o

tehnic a de rezolvare a celor mai multe relat ¸ii de recurent¸ a provenite din metodaDivide et Impera .

Pentru a rezolva astfel de ecuat ¸ii recurente vom reprezenta arborele generatde ecuat ia recursiv˘a. R ad acina arborelui cont¸ine valoarea f (n), si ea are noduridescendente care sunt noduri r˘ ad acin a pentru arborele provenit din T (n/b ).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 95/518

6.2. ECUATII RECURENTE NEOMOGENE 83

Pe nivelul i se aa nodurile care cont¸in valoarea a i f (n/b i ). Recursivitatea seopreste cˆand se obt ine un caz de baz˘ a pentru recurent ¸a.

Presupunem c˘a T (1) = f (1).Cu aceast a reprezentare este foarte clar c˘ a T (n) este suma valorilor din

nodurile arborelui. Presupunˆ and c a ecare nivel este plin, obt¸inem

T (n) = f (n) + af (n/b ) + a2f (n/b 2) + a3f (n/b 3) + ... + ak f (n/b k )

unde k este ad ancimea arborelui de recursivitate. Din n/b k = 1 rezult˘a k = log b n.Ultimul termen diferit de zero ın sum˘ a este de forma ak = a log b n = n log b a (ultimaegalitate ind ıntˆ alnit a ın liceu!).

Acum putem usor enunt ¸a si demonstra teorema Master.

Teorema 1 ( Teorema Master ) Relat ia de recurent ˘ a T (n) = aT (n/b )+ f (n) areurm˘ atoarea solut ie:

• dac˘ a af (n/b ) = αf (n) unde α < 1 atunci T (n) = Θ( f (n)) ;

• dac˘ a af (n/b ) = βf (n) unde β > 1 atunci T (n) = Θ( n log b a );

• dac˘ a af (n/b ) = f (n) atunci T (n) = Θ( f (n)logb n);

Demonstrat ie : Daca f (n) este un factor constant mai mare decˆ at f (b/n ), atunciprin induct¸ie se poate ar˘ata c a suma este a unei progresii geometrice descresc˘ atoare.Suma ın acest caz este o constant˘ a ınmult¸it a cu primul termen care este f (n).

Daca f (n) este un factor constant mai mic decˆ at f (b/n ), atunci prin induct ¸iese poate ar ata c a suma este a unei progresii geometrice cresc˘ atoare. Suma ın acestcaz este o constant˘a ınmult¸it a cu ultimul termen care este n log b a .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 96/518

84 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

Daca af (b/n ) = f (n), atunci prin induct ¸ie se poate ar˘ata c a ecare din ceik + 1 termeni din sum˘ a sunt egali cu f (n).

Exemple .

1. Selectia aleatoare: T (n) = T (3n/ 4) + n.Aici af (n/b ) = 3 n/ 4 iar f (n) = n, rezult a α = 3 / 4, deci T (n) = Θ( n).

2. Algoritmul de multiplicare al lui Karatsuba: T (n) = 3 T (n/ 2) + n.Aici af (n/b ) = 3 n/ 2 iar f (n) = n, rezult a α = 3 / 2, deci T (n) = Θ( n log 2 3).

3. Mergesort: T (n) = 2 T (n/ 2) + n.Aici af (n/b ) = n, iar f (n) = n, rezult a α = 1 deci T (n) = Θ( n log2 n).Folosind acceasi tehnic˘ a a arborelui recursiv, putem rezolva recurent ¸e pentru

care nu se poate aplica teorema Master.

6.2.4 Transformarea recurent ¸elor

La Mergesort am avut o relai¸e de recurent¸ a de forma T (n) = 2 T (n/ 2) + n siam obt inut solut¸ia T (n) = O(n log2 n) folosind teorema Master (metoda arboreluide recursivitate). Aceast˘ a modalitate este corect˘ a dac a n este o putere a lui 2, darpentru alte valori ale lui n aceast a recurent a nu este corect˘a. Cand n este impar,recurent a ne cere s a sort am un num ar elemente care nu este ıntreg! Mai r˘ au chiar,dac a n nu este o putere a lui 2, nu vom atinge niciodat˘ a cazul de baz a T (1) = 0.

Pentru a obt ¸ine o recurent¸a care s a e valid a pentru orice valori ıntregi alelui n , trebuie s a determin˘am cu atent¸ie marginile inferioar˘a si superioar˘a:

T (n) = T (

n/ 2

) + T (

n/ 2

) + n.

Metoda transform˘ arii domeniului rescrie funct ia T (n) sub forma S (f (n)),unde f (n) este o funct ie simpl a si S () are o recurent¸a mai usoar˘a.

Urm atoarele inegalit˘at i sunt evidente:

T (n) ≤2T (⌈n/ 2⌉) + n ≤2T (n/ 2 + 1) + n.

Acum denim o nou a funct ie S (n) = T (n + α), unde α este o constant˘anecunoscut˘a, aleas a astfel ıncˆat s a e satisf acut a recurent a din teorema MasterS (n) ≤ S (n/ 2) + O(n). Pentru a obt ¸ine valoarea corect˘ a a lui α , vom comparadoua versiuni ale recurent¸ei pentru funct ¸ia S (n + α):

S (n) ≤2S (n/ 2) + O(n) ⇒T (n + α) ≤2T (n/ 2 + α) + O(n)

T (n) ≤2T (n/ 2 + 1) + n ⇒T (n + α) ≤2T ((n + α)/ 2 + 1) + n + αPentru ca aceste dou˘ a recurent e sa e egale, trebuie ca n/ 2+ α = ( n + α)/ 2+1,

care implic a α = 2. Teorema Master ne spune acum c˘ a S (n) = O(n log n), deci

T (n) = S (n −2) = O((n −2) log(n −2) = O(n log n).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 97/518

6.2. ECUATII RECURENTE NEOMOGENE 85

Un argument similar d˘ a o ajustare a marginii inferioare T (n) = Ω( n log n).Deci, T (n) = Θ( n log n) este un rezultat ıntemeiat desi am ignorat marginile

inferioar a si superioar˘a de la ınceput!Transformarea domeniului este util˘ a pentru ınl˘ aturarea marginilor inferioar˘ a

si superioar˘a, si a termenilor de ordin mic din argumentele oric˘ arei recurent¸e carese potriveste un pic cu teorema master sau metoda arborelui de recursivitate.

Exist a ın geometria computat ¸ional a o structur˘a de date numit˘a arbore pliat ,pentru care costul operatiei de c˘ autare ındeplineste relat ¸ia de recurent¸a

T (n) = T (n/ 2) + T (n/ 4) + 1 .

Aceasta nu se potriveste cu teorema master, pentru c˘ a cele doua subproblemeau dimensiuni diferite, si utilizˆ and metoda arborelui de recursivitate nu obt ¸inemdecat niste margini slabe √n << T (n) << n .

Daca nu au forma standard, ecuat ¸iile recurente pot aduse la aceast˘ a formaprintr-o schimbare de variabil˘ a. O schimbare de variabil˘ a aplicabil a pentru ecuat¸iide recurent a de tip multiplicativ este:

n = 2 k⇔k = log n

De exemplu, e

T (n) = 2 ·T (n/ 2) + n ·log n, n > 1

Facem schimbarea de variabil˘ a t(k) = T (2k ) si obt inem:

t(k) −2 ·t(k −1) = k ·2k , deci b = 2 , p(k) = k, d = 1

Ecuat ia caracteristic˘ a complet a este:

(r −2)3 = 0

cu solut iat(k) = c1 ·2k + c2 ·k ·2k + c3 ·k2 ·2k

Deci

T (n) = c1 ·n + c2 ·n ·log n + c3 ·n ·log2 n∈O(n ·log2 n|n = 2 k )

Uneori, printr-o schimbare de variabil˘ a, putem rezolva recurent ¸e mult maicomplicate. In exemplele care urmeaz˘a, vom nota cu T (n) termenul general alrecurent ei si cu tk termenul noii recurent ¸e obt inute printr-o schimbare de variabil˘ a.

Presupunem pentru ınceput c˘ a n este o putere a lui 2.Un prim exemplu este recurenta

T (n) = 4 T (n/ 2) + n, n > 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 98/518

86 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

ın care ınlocuim pe n cu 2k , notam tk = T (2k ) = T (n) si obt inem

tk = 4 tk−1 + 2 k

Ecuat ia caracteristic˘ a a acestei recurent¸e liniare este

(x −4)(x −2) = 0

si deci, tk = c14k + c22k . Inlocuim la loc pe k cu log2 n

T (n) = c1n2 + c2n

Rezult a

T (n)

O(n2

|n este o putere a lui 2)

Un al doilea exemplu ıl reprezint˘ a ecuat ia

T (n) = 4 T (n/ 2) + n2 , n > 1

Proced and la fel, ajungem la recurenta

tk = 4 tk−1 + 4 k

cu ecuat ia caracteristic˘ a(x −4)2 = 0

si solut ia general˘a tk = c142 + c2k42 .Atunci,

T (n) = c1n2

+ c2n2

lg nsi obt inem

T (n)∈O(n2 log n |n este o putere a lui 2)

In sfarsit, s˘a consider am si exemplul

T (n) = 3 T (n/ 2) + cn, n > 1

c ind o constant˘a. Obt inem succesiv

T (2k ) = 3 T (2k−1) + c2k

tk = 3 tk−1 + c2k

cu ecuat ia caracteristic˘ a

(x −3)(x −2) = 0tk = c13k + c22k

T (n) = c13lg n + c2n

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 99/518

6.3. PROBLEME REZOLVATE 87

si, deoarecea lg b = blg a

obtinemT (n) = c1n lg 3 + c2n

deci,T (n)∈O(n lg 3 |n este o putere a lui 2)

Putem enunt ¸a acum o proprietate care este util˘ a ca retet a pentru analizaalgoritmilor cu recursivit˘ at i de forma celor din exemplele precedente.

Fie T : N −→R + o functie eventual nedescresc˘ atoare

T (n) = aT (n/b ) + cnk , n > n 0

unde: n0

≥1, b

≥2 si k

≥0 sunt ıntregi; a si c sunt numere reale pozitive; n/n 0

este o putere a lui b. Atunci avem

T (n)∈

Θ(nk ), pentru a < b k ;Θ(nk log n), pentru a = bk ;Θ(n log b a ), pentru a > b k ;

6.3 Probleme rezolvate

1. Sa se rezolve ecuat ia:

F n +2 = F n +1 + F n , F 0 = 0 , F 1 = 1 .

Ecuat aia caracteristic˘ a corespunz atoare

r 2 −r −1 = 0

are solut iile

r 1 =1 + √5

2, r2 =

1 −√52

.

Solutia general˘a este

F n = c11 + √5

2

n

+ c21 −√5

2

n

.

Determin˘am constantele c1 si c2 din condit iile init iale F 0 = 0 si F 1 = 1.Rezolvand sistemul

c1 + c2 = 0c1

1+ √52 + c2

1−√52 = 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 100/518

88 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

obtinem c1 = 1√5 si c1 = − 1√5 .

Deci, solut ia relat iei de recurent¸a care deneste numerele lui Fibonacci este:

F n =1√5

1 + √52

n

−1√5

1 −√52

n

2. Sa se rezolve relat ia de recurent¸a:

xn +3 = xn +2 + 8 xn +1 −12xn , x0 = 0 , x1 = 2 , x2 = 3 .

Ecuat ia caracteristic˘ a corespunz atoare este:

r 3 −r 2 −8r + 12 = 0

si are solut iile: r 1 = r 2 = 2 si r 3 = −3.Solutia general˘a este de forma:

xn = ( c1 + nc2)2n + c3(−3)n .

Din condit iile init iale rezult˘a constantele: c1 = 15 , c2 = 1

2 si c3 = −15 .

Solutia general˘a este:

xn =n2

+15

2n −15

(−3)n .

3. Sa se rezolve relat ia de recurent¸a:

xn +3 = 6 xn +2

−12xn +1 + 8 xn , x0 = 0 , x1 = 2 , x2 = 4 .

Ecuat ia caracteristic˘ a corespunz atoare este:

r 3 −6r 2 + 12 r −8 = 0

si are solut iile: r 1 = r 2 = r 3 = 2.Solutia general˘a este de forma:

xn = ( c1 + c2n + c3n2)2n .

Din condit iile init iale rezult˘a constantele: c1 = 0, c2 = 32 si c3 = −1

2 .Solutia general˘a este:

xn =32n −

12n

2

2n

= (3 n −n2

)2n

−1

.

4. Sa se rezolve relat ia de recurent¸a:

xn +2 = 2 xn +1 −2xn , x0 = 0 , x1 = 1 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 101/518

6.3. PROBLEME REZOLVATE 89

Ecuat ia caracteristic˘ a corespunz atoare este:

r 2 −2r + 2 = 0

si are solut iile: r 1 = 1 + i si r 2 = 1 −i care se pot scrie sub form˘a trigonometric˘aastfel:

r 1 = √2 cosπ4

+ i sinπ4

, r 2 = √2 cosπ4 −i sin

π4

.

Solutiile fundamentale sunt:

x(1)n = √2

ncos

nπ4

, x (2)n = √2

nsin

nπ4

.

Solutia general˘a este de forma:

xn = √2n

c1 cosnπ4 + c2 sin

nπ4 .

Din condit iile init iale rezult˘a constantele: c1 = 0 si c2 = 1.Solutia general˘a este:

xn = √2n

sinnπ4

.

5. Sa se rezolve relat ia de recurent¸a:

xn +3 = 4 xn +2 −6xn +1 + 4 xn , x0 = 0 , x1 = 1 , x2 = 1 .

Ecuat ia caracteristic˘ a corespunz atoare este:

r 3 −4r 2 + 6 r −4 = 0

si are solut iile: r 1 = 2, r 2 = 1 + i si r 3 = 1 −i.Solutia general˘a este de forma:

xn = c12n + c2 √2n

cosnπ4

+ c3 √2n

sinnπ4

.

Din condit iile init iale rezult˘a constantele: c1 = −12 , c2 = 1

2 si c3 = 32 .

Solutia general˘a este:

xn = −2n

−1

+

√2n

2 cosnπ4 + 3 sin

nπ4 .

6. Sa se rezolve relat ia de recurent¸a:

T (n) −3T (n −1) + 4 T (n −2) = 0 , n ≥2, T (0) = 0 , T (1) = 1 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 102/518

90 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

Ecuat ia caracteristic˘ a r 2 −3r + 4 = 0 are solut¸iile r 1 = −1, r 2 = 4, deci

T (n) = c1(−1)n + c24n

Constantele se determin˘ a din condit iile init iale:

c1 + c2 = 0

−c1 + 4 c2 = 1 ⇒c1 = −1

5c2 = 1

5

Solutia este:T (n) =

15

[4n −(−1)n ] .

7. Sa se rezolve relat ia de recurent¸a:

T (n) = 5 T (n −1)−8T (n −2)+4 T (n −3), n ≥3, cu T (0) = 0 , T (1) = 1 , T (2) = 2 .

Ecuat ia caracteristic˘ a:

r 3 −5r 2 + 8 r −4 = 0⇒r 1 = 1 , r 2 = r 3 = 2

deciT (n) = c11n + c22n + c3n2n

Determinarea constantelor

c1 + c2 = 0c1 + 2 c2 + 2 c3 = 1c1 + 4 c2 + 8 c3 = 2 ⇒

c1 = −2c2 = 2c3 = −1

2

DeciT (n) = −2 + 2 n +1 −

n2

2n = 2 n +1 −n2n −1 −2.

8. Sa se rezolve relat ia de recurent¸a:

T (n) = 4 T (n/ 2) + n lg n.

In acest caz, avem af (n/b ) = 2 n lg n −2n, care nu este tocmai dublul luif (n) = n lg n. Pentru n sucient de mare, avem 2 f (n) > af (n/b ) > 1.9f (n).

Suma este m arginit˘a si inferior si superior de c˘ atre serii geometrice cresc˘ atoare,

deci solut ia este T (n) = Θ( nlog

24) = Θ( n

2). Acest truc nu merge ın cazurile doi sitrei ale teoremei Master.

9. Sa se rezolve relat ia de recurent¸a:

T (n) = 2 T (n/ 2) + n lg n.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 103/518

6.3. PROBLEME REZOLVATE 91

Nu putem aplica teorema Master pentru c˘ a af (n/b ) = n/ (lg n −1) nu esteegala cu f (n) = n/ lg n, iar diferent a nu este un factor constant.

Trebuie s˘a calcul am suma pe ecare nivel si suma total˘ a ın alt mod. Sumatuturor nodurilor de pe nivelul i este n/ (lg n −i). In particular, aceasta ınseamn˘ aca ad ancimea arborelui este cel mult lg n −1.

T (n) =lg n −1

i=0

nlg n −i

=lg n

j =1

n j

= nH lg n = Θ( n lglg n).

10. (Quicksort aleator). S˘ a se rezolve relat ia de recurent¸a:

T (n) = T (3n/ 4) + T (n/ 4) + n.

In acest caz nodurile de pe acelasi nivel al arborelui de recursivitate au diferitevalori. Nodurile din orice nivel complet (adic a, deasupra oric˘arei frunze) au suman, deci este la fel ca ın ultimul caz al teoremei Master si orice frunz˘ a are nivelulıntre log 4 n si log4/ 3 n.

Pentru a obt¸ine o margine superioar˘ a, vom supraevalua T (n) ignor and cazurilede baz a si extinzˆand arborele ın jos c˘ atre nivelul celei mai adˆanci frunze.

Similar, pentru a obt ¸ine o margine inferioar˘ a pentru T (n), vom subevaluaT (n) contoriz and numai nodurile din arbore pˆ an a la nivelul frunzei care este ceamai put in ad anc a. Aceste observat¸ii ne dau marginile inferioar˘ a si superioar˘a:

n log4 n ≤T (n) ≤n log4/ 3 n.

Deoarece aceste margini difer a numai printr-un factor constant, avem c˘ aT (n) = Θ( n log n).

11. (Select ie determinist˘ a). Sa se rezolve relat ia de recurent¸a:

T (n) = T (n/ 5) + T (7n/ 10) + n.

Din nou, avem un arbore recursiv ”trunchiat”. Dac˘ a ne uit am numai lanivelurile complete ale arborelui, observ˘ am c a suma pe nivel formeaz˘a o seriegeometric a descresc atoare T (n) = n + 9 n/ 10+81 n/ 100+ ..., deci este ca ın primulcaz al teoremei Master. Putem s˘ a obtinem o margine superioar˘ a ignor and cazurilede baz a ın totalitate si crescˆ and arborele spre innit, si putem obt ¸ine o margineinferioar a contoriz and numai nodurile din nivelurile complete. In ambele situat¸ii,seriile geometrice sunt majorate de termenul cel mai mare, deci T (n) = Θ( n).

12. Sa se rezolve relat ia de recurent¸a:T (n) = 2 √n ·T (√n) + n.

Avem cel mult lg lg n niveluri dar acum avem nodurile de pe nivelul i careau suma 2 i n. Avem o serie geometric˘a crescatoare a sumelor nivelurilor, la fel ca

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 104/518

92 CAPITOLUL 6. ANALIZA ALGORITMILOR RECURSIVI

ın cazul doi din teorema Master, deci T (n) este majorat˘a de suma nivelurilor celemai ad anci. Se obt ine:

T (n) = Θ(2 lglg n n) = Θ( n log n).

13. Sa se rezolve relat ia de recurent¸a:

T (n) = 4 √n ·T (√n) + n.

Suma nodurilor de pe nivelul i este 4 i n. Avem o serie geometric˘a crescatoare,la fel ca ın cazul doi din teorema master, deci nu trebuie decˆ at s a avem grij a deaceste niveluri. Se obt¸ine

T (n) = Θ(4 lglg n n) = Θ( n log2 n).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 105/518

Capitolul 7

Algoritmi elementari

7.1 Operat ¸ii cu numere

7.1.1 Minim si maxim

Sa presupunem c˘a dorim s a determin˘am valorile minim˘a si maxim˘a dintru-unvector x[1..n . Proced am astfel:

vmin = x[1];vmax = x[1];for i=2, n

vmin = minim(vmin, x[i])vmax = maxim(vmax, x[i])

Evident se fac 2 n −2 comparat ii. Se poate mai repede? Da! Imp art im sirul ındoua si determin˘am vmin si vmax ın cele dou a zone. Compar˘am vmin 1 cu vmin 2si stabilim vminm . La fel pentru vmax . Prelucrarea se repet˘ a pentru cele dou˘azone (deci se foloseste recursivitatea). Apar cˆ ate dou a comparat¸ii ın plus de ecaredat a. Dar c ate sunt ın minus? Presupunem c˘ a n este o putere a lui 2 si T (n) estenum arul de comparat ¸ii. Atunci

T (n) = 2 T (n/ 2) + 2 si T (2) = 1 .

Cum rezolv am aceast˘a relat ie de recurent¸ a? Banuim c a solut ia este de formaT (n) = an + b. Atunci a si b trebuie s a satisfac a sistemul de ecuat¸ii

2a + b = 1an + b = 2( an/ 2 + b) + 2

93

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 106/518

94 CAPITOLUL 7. ALGORITMI ELEMENTARI

care are solut ia b = −2 si a = 3 / 2, deci (pentru n putere a lui 2), T (n) = 3 n/ 2−2,adic a 75% din algoritmul anterior. Se poate demonstra c˘ a num arul de comparat¸iieste 3 ⌈n/ 2⌉−2 pentru a aa minimum si maximum.

O idee similar a poate aplicat˘a pentru varianta secvent ¸ial a. Presupunem c˘asirul are un num˘ ar par de termeni. Atunci, algoritmul are forma:

vmin = minim(x[1],x[2])vmax = maxim(x[1],x[2])for(i=3;i<n;i=i+2)

cmin = minim(x[i],x[i+1])cmax = maxim(x[i],x[i+1])if cmin < vmin

vmin = cminif vmax > cmax

vmax = cmaxFiecare iterat¸ie necesit a trei comparat¸ii, iar init ializarea variabilelor necesit˘ a

o comparat ie. Ciclul se repet˘a de (n −2)/ 2 ori, deci avem un total de 3 n/ 2 −2comparat ii pentru n par.

7.1.2 Divizori

Fie n un num ar natural. Descompunerea ın facori primi

n = pα 11 · pα 2

2 ·... · pα kk (7.1.1)

se numeste descompunere canonic˘ a . Daca not am prin d(n) num arul divizorilor luin∈

N , atunci:d(n) = (1 + α 1)(1 + α 2)...(1 + α k ) (7.1.2)

Pentru calculul lui d(n) putem folosi urm˘atorul algoritm:

static int ndiv(int n)

int d,p=1,nd;

d=2;nd=0;while(n%d==0)nd++;n=n/d;p=p*(1+nd);

d=3;while(d*d<=n)

nd=0;while(n%d==0)nd++;n=n/d;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 107/518

7.2. ALGORITMUL LUI EUCLID 95

p=p*(1+nd);d=d+2;

if(n!=1) p=p*2;return p;

7.1.3 Numere prime

Pentru testarea primalit˘ at i unui num˘ar putem folosi urm˘atorul algoritm:

static boolean estePrim(int nr)

int d;if(nr<=1) return false;if(nr==2) return true;if(nr%2==0) return false;d=3;while((d*d<=nr)&&(nr%d!=0)) d=d+2;if(d*d>nr) return true; else return false;

7.2 Algoritmul lui Euclid

7.2.1 Algoritmul clasic

Un algoritm pentru calculul celui mai mare divizor comun ( cmmdc ) a dou anumere naturale poate descompunerea lorın factori si calculul produsului tuturordivizorilor comuni. De exemplu dac˘ a a = 1134 = 2 ∗3∗3∗3∗3∗7 si b = 308 =2∗2∗7∗11 atunci cmmdc (a, b) = 2 ∗7 = 14.

Descompunerea ın factori a unui num˘ ar natural n poate necesita ıncercareatuturor numerelor naturale din intervalul [2 , √n].

Un algoritm ecient pentru calculul cmmdc (a, b) este algoritmul lui Euclid.

static int cmmdc(int a, int b

int c;i f ( a < b ) c = a ; a = b ; b = c ; while((c=a%b) != 0) a = b; b = c;return b;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 108/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 109/518

7.3. OPERATII CU POLINOAME 97

si de asemenea, valorile pentru xk si yk :x3 = 0 , y3 = 1;x2 = 1 , y2 = 0 −1∗2 = −2;x1 = −2, y1 = 1 + 2 ∗1 = 3;x0 = 3 , y1 = −2 −3∗3 = −11.

Desigur relat ia 3∗1134 −11∗308 = 14 este corect˘a. Solut ia nu este unic˘a.Sa observ am ca (3 + k∗308)∗1134 −(11 + k∗1134)∗308 = 14, pentru orice k,ceea ce arat a ca valorile calculate pentru x = x0 si y = y0 nu sunt unice.

7.3 Operat ¸ii cu polinoame

Toate operat¸iile cu polinoame obisnuite se fac utilizˆ and siruri de numere

care reprezint˘a coecientii polinomului. Not˘am cu a si b vectorii coecient ilorpolinoamelor cu care se opereaz˘ a si cu m si n gradele lor. Deci

a(X ) = am X m + ... + a1X + a0 si b(X ) = bn X n + ... + b1X + b0 .

7.3.1 Adunarea a doua polinoame

Este asem an atoare cu adunarea numerelor mari.

static int[] sumap(int[] a, int[] b)

int m,n,k,i,j,minmn;

int[] s; m=a.length-1;n=b.length-1;if(m<n) k=n; minmn=m; else k=m; minmn=n;s=new int[k+1];for(i=0;i<=minmn;i++) s[i]=a[i]+b[i];if(minmn<m) for(i=minmn+1;i<=k;i++) s[i]=a[i];

else for(i=minmn+1;i<=k;i++) s[i]=b[i];i=k;while((s[i]==0)&&(i>=1)) i--;if(i==k) return s;

else

int[] ss=new int[i+1];for(j=0;j<=i;j++) ss[j]=s[j];return ss;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 110/518

98 CAPITOLUL 7. ALGORITMI ELEMENTARI

7.3.2 Inmult ¸irea a doua polinoame

Evident, gradul polinomului produs p = a ·b este m + n iar coecientul pk estesuma tuturor produselor de forma a i ·bj unde i + j = k, 0 ≤ i ≤m si 0 ≤ j ≤n.

static int[] prodp(int[] a, int[] b)

int m,n,i,j;int[] p; m=a.length-1;n=b.length-1;p=new int[m+n+1];for(i=0;i<=m;i++)

for(j=0;j<=n;j++)p[i+j]+=a[i]*b[j];return p;

7.3.3 Calculul valorii unui polinom

Valoarea unui polinom se calculeaz˘ a ecient cu schema lui Horner:

a(x) = ( ...((an ·x + an −1) ·x + an −2) ·x + ... + a1) ·x + a0

static int valp(int[] a, int x)

int m,i,val; m=a.length-1;val=a[m];for(i=m-1;i>=0;i--)

val=val*x+a[i];return val;

7.3.4 Calculul derivatelor unui polinom

Fie b(X ) = bn X n + bn −1X n −1 + ... + b1X + b0

derivata de ordinul 1 a polinomului

a(X ) = am X m + am −1X m −1 + ... + a1X + a0 .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 111/518

7.3. OPERATII CU POLINOAME 99

Dar

a ′(X ) = m ·am ·X m −1 + ( m −1) ·am −1 ·X m −2 + ... + 2 ·a2 ·X + a1 .

Rezult a can = m −1

sibi = ( i + 1) ·a i+1 pentru 0 ≤ i ≤n.

static int[] derivp(int[] a)

int m,n,i;int[] b; m=a.length-1;n=m-1;b=new int[n+1];for(i=0;i<=n;i++)

b[i]=(i+1)*a[i+1];return b;

Pentru calculul valorii v = a ′(x) a derivatei polinomului a ın x este sucientapelul

v=valp(derivp(a),x); .

Daca vrem s a calcul am derivata de ordinul k

≥0 a polinomului a, atunci

static int[] derivpk(int[] a,int k)

int i;int[] b; m=a.length-1;b=new int[m+1];for(i=0;i<=n;i++)

b[i]=a[i];for(i=1;i<=k;i++)

b=derivp(b);return b;

Pentru calculul valorii v = a (k ) (x) a derivatei de ordinul k a polinomului aın x este sucient apelul

v=valp(derivpk(a,k),x); .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 112/518

100 CAPITOLUL 7. ALGORITMI ELEMENTARI

7.4 Operat ¸ii cu mult ¸imi

O mult ime A se poate memora ıntr-un vector a , ale carui elemente suntdistincte. Folosind vectorii putem descrie operat ¸iile cu mult imi.

7.4.1 Apartenent ¸a la mult ¸ime

Testul de apartenent ¸ a a unui element x la o multime A, este prezentat ınalgoritmul urm˘ator:

static boolean apartine(int[] a, int x)

int i,n=a.length;boolean ap=false;for(i=0;i<n;i++)

if(a[i]==x) ap=true; break;return ap;

7.4.2 Diferent ¸a a doua mult ¸imi

Diferent a a dou a mult imi este dat˘a de mult imea

C = A −B = x|x∈A,x /∈BNot am card A = m.

static int[] diferenta(int[] a, int[] b)

int i, j=0, m=a.length;int[] c=new int[m];for(i=0;i<m;i++)

if(!apartine(b,a[i]) c[j++]=a[i];if(j==m) return c;

else

int[] cc=new int[j];for(i=0;i<j;i++) cc[i]=c[i];return cc;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 113/518

7.4. OPERATII CU MULTIMI 101

7.4.3 Reuniunea si intersect ¸ia a dou˘ a mult¸imi

Reuniunea a dou˘a mult imi este multimea:

C = A∪B = A∪(B −A).

Introducem ın C toate elementele lui A si apoi elementele lui B −A.

static int[] reuniune(int[] a, int[] b)

int i, j, m=a.length, n=b.length;int[] c=new int[m+n];for(i=0;i<m;i++) c[i]=a[i];j=m;for(i=0;i<n;i++) if(!apartine(a,b[i]) c[j++]=b[i];if(j==m+n) return c;

else

int[] cc=new int[j];for(i=0;i<j;i++) cc[i]=c[i];return cc;

Intersect ia a dou a mult imi este multimea:

C = A ∩B = x|x∈A si x∈Bstatic int[] reuniune(int[] a, int[] b)

int i, j, m=a.length;int[] c=new int[m];j=0;for(i=0;i<m;i++) if(apartine(b,a[i]) c[j++]=a[i];if(j==m) return c;

else

int[] cc=new int[j];for(i=0;i<j;i++) cc[i]=c[i];return cc;

7.4.4 Produsul cartezian a doua mult ¸imi

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 114/518

102 CAPITOLUL 7. ALGORITMI ELEMENTARI

Produs cartezian a doua multimi este multimea:

A ×B = (x, y )|x∈A si y∈BPutem stoca produsul cartezian sub forma unei matrice C cu dou a linii si

m ×n coloane. Fiecare coloan˘a a matricei cont¸ine c ate un element al produsuluicartezian.

static int[][] prodc(int[] a, int[] b)

int i, j, k, m=a.length, n=b.length;int[][] c=new int[2][m*n];k=0;for(i=0;i<m;i++)

for(j=0;j<n;j++)c[0][k]=a[i];c[1][k]=b[j];k++;

return c;

De exemplu, pentru A = 1, 2, 3, 4si B = 1, 2, 3, matricea C este

0 1 2 3 4 5 6 7 8 9 10 11linia 0 1 1 1 2 2 2 3 3 3 4 4 4

linia 1 1 2 3 1 2 3 1 2 3 1 2 3

7.4.5 Generarea submult ¸imilor unei mult ¸imi

Generarea submult ¸imilor unei multimi A = a1 , a 2 ,...,a n , este identic a cugenerarea submult ¸imilor mult¸imii de indici 1, 2,...,n .

O submult ime se poate memora sub forma unui vector cu n componente,unde ecare component˘ a poate avea valori 0 sau 1. Componenta i are valoarea 1daca elementul a i apart ine submult¸imii si 0 ın caz contrar. O astfel de reprezentarese numeste reprezentare prin vector caracteristic .

Generarea tuturor submult ¸imilor ınseamn˘ a generarea tuturor combinat ¸iilorde 0 si 1 care pot ret inute de vectorul caracteristic V , adic a a tuturor numerelorın baza 2 care se pot reprezenta folosind n cifre.

Pentru a genera adunarea ın binar, t ¸inem cont c˘a trecerea de la un ordin laurm atorul se face c and se obt ine suma egal˘a cu 2, adic a 1 + 1 = (10) 2 .

De exemplu, pentru n = 4, vom folosi un vector v pozitia 1 2 3 4valoarea · · · ·

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 115/518

7.4. OPERATII CU MULTIMI 103

initial 0 0 0 0 si adun˘am 1

obtinem 0 0 0 1 si adun˘am 1obtinem 0 0 0 2 care nu este permis, si trecem la ordinul urm˘ atorobtinem 0 0 1 0 si adun˘am 1obtinem 0 0 1 1 si adun˘am 1obtinem 0 0 1 2 care nu este permis, si trecem la ordinul urm˘ atorobtinem 0 0 2 0 care nu este permis, si trecem la ordinul urm˘ atorobtinem 0 1 0 0 si asa mai departeobtinem · · · · pan a candobtinem 1 1 1 1

Aceste rezultate se pot ret ¸ine ıntr-o matrice cu n linii si 2n coloane.

0 1 2 3 4 5 6 7 8 9 A B C D E Fa1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0a2 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 1a3 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 2a4 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 3

Ultima coloan˘a cont ine num˘arul liniei din matrice. Coloana 0 reprezint˘ amult imea vid a, coloana F reprezint˘ a ıntreaga mult ¸ime, si, de exemplu, coloana 5reprezint˘a submultimea a2 , a 4iar coloana 7 reprezint˘ a submultimea a2 , a 3 , a 4.

static int[][] submultimi(int n)

int i, j, nc=1;int[] v=new int[n+1];int[][] c;for(i=1;i<=n;i++) nc*=2;c=new int[n][nc];for(i=1;i<=n;i++) v[i]=0;j=0;while(j<nc)

v[n]=v[n]+1;i=n;while(v[i]>1) v[i]=v[i]-2; v[i-1]=v[i-1]+1; i--; for(i=1;i<=n;i++) c[j][i-1]=v[i];j++;

return c;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 116/518

104 CAPITOLUL 7. ALGORITMI ELEMENTARI

7.5 Operat ¸ii cu numere ıntregi mari

Operat iile aritmetice sunt denite numai pentru numere reprezentate pe 16,32 sau 64 biti. Dac a numerele sunt mai mari, operat ¸iile trebuie implementate deutilizator.

7.5.1 Adunarea si scaderea

Adunarea si sc˘aderea sunt directe: aplicˆ and metodele din scoala elementar˘ a.

static int[] suma(int[] x, int[] y)

int nx=x.length;int ny=y.length;int nz;if(nx>ny)

nz=nx+1;else

nz=ny+1;int[] z=new int[nz];int t,s,i;t=0;for (i=0;i<=nz-1;i++)

s=t;if(i<=nx-1)

s=s+x[i];if(i<=ny-1)

s=s+y[i];z[i]=s%10;t=s/10;

if(z[nz-1]!=0)

return z;else

int[] zz=new int[nz-1];for (i=0;i<=nz-2;i++) zz[i]=z[i];return zz;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 117/518

7.5. OPERATII CU NUMERE INTREGI MARI 105

7.5.2 Inmult irea si ımpartirea

Metoda ınv˘atat˘a ın soal˘a este corect a.

static int[] produs(int[]x,int[]y)

int nx=x.length;int ny=y.length;int nz=nx+ny;int[] z=new int[nz];int[] [] a=new int[ny][nx+ny];int i,j;int t,s;for(j=0;j<=ny-1;j++)

t=0;for(i=0;i<=nx-1;i++)

s=t+y[j]*x[i];a[j][i+j]=s%10;t=s/10;

a[j][i+j]=t;

t=0;for(j=0;j<=nz-1;j++)

s=0;for(i=0;i<=ny-1;i++)

s=s+a[i][j];s=s+t;z[j]=s%10;t=s/10;

if(z[nz-1]!=0)

return z;else

int[] zz=new int [nz-1];for(j=0;j<=nz-2;j++)

zz[j]=z[j];return zz;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 118/518

106 CAPITOLUL 7. ALGORITMI ELEMENTARI

7.5.3 Puterea

Presupunem c˘a vrem s a calcul am xn . Cum facem acest lucru? Este evidentca urm atoarea secvent¸a funct ioneaz˘a:

for (p = 1, i = 0; i < n; i++) p *= x;

Presupunˆand c a toate ınmult ¸irile sunt efectuate ıntr-o unitate de timp, acestalgoritm are complexitatea O(n). Totusi, putem s˘ a facem acest lucru mai repede!Presupunˆand, pentru ınceput, c˘ a n = 2 k , urm atorul algoritm este corect:

for (p = x, i = 1; i < n; i *= 2) p *= p;

Aici num arul de treceri prin ciclu este egal cu k = log 2 n.Acum, s a consider am cazul general. Presupunem c˘ a n are expresia binar˘ a

(bk , bk−1 ,...,b1 , b0). Atunci putem scrie

n =k

i=0 ,b i =1

2i .

Deci,

xn =k

i=0 ,b i =1

x2 i

.

int exponent_1(int x, int n)

int c, z;for (c = x , z = 1 ; n != 0 ; n = n / 2 )

if (n & 1) /* n este impar */z *= c;

c *= c;return z;

int exponent_2(int x, int n)

if (n == 0)return 1;

if (n & 1) /* n este impar */return x * exponent_2(x, n - 1);

return exponent_2(x, n / 2) * exponent_2(x, n / 2);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 119/518

7.6. OPERATII CU MATRICE 107

int exponent_3(int x, int n)

int y;if (n == 0)

return 1;if (n & 1) /* n este impar */

return x * exponent_3(x, n - 1);y = exponent_3(x, n / 2);return y * y;

7.6 Operat ¸ii cu matrice

7.6.1 Inmult ¸irea

O funct ie scris a ın C/C++:

void matrix_product(int** A, int** B, int** C)

for (i = 0; i < n; i++)for (j = 0; j < n; j++)

C[i][j] = 0;for (k = 0; k < n; k++)

C[i][j] += A[i][k] * B[k][j];

7.6.2 Inversa unei matrice

O posibilitate este cea din scoal˘ a. Aceasta presupune calculul unor determinant ¸i.Determinantul det (A) se deneste recursiv astfel:

det( A) =n

−1

i =0(−1)i+ j

∗a i,j ∗det( Ai,j ).

unde a i,j este element al matricei iar Ai,j este submatricea obt ¸inut˘a prin eliminarealiniei i si a coloanei j .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 120/518

108 CAPITOLUL 7. ALGORITMI ELEMENTARI

int determinant(int n, int[][] a)

if (n == 1)return a[0][0];

int det = 0;int sign = 1;int[][] b = new int[n - 1][n - 1];for (int i = 0; i < n; i++)

for (int j = 0; j < i; j++)for (int k = 1; k < n; k++)

b[j][k - 1] = a[j][k];for (int j = i + 1; j < n; j++)

for (int k = 1; k < n; k++)b[j - 1][k - 1] = a[j][k];

det += sign * a[i][0] * determinant(n - 1, b);sign *= -1;

Folosind determinant ¸i, inversa matricei se poate calcula folosind regula lui Cramer . Presupunem c˘a A este inversabil˘a si e B = ( bi,j ) matricea denit˘ a prin

bi,j = ( −1)i+ j∗det( Ai,j )/ det( A).

Atunci A−1 = B T , unde B T este transpusa matricei B .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 121/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 122/518

110 CAPITOLUL 8. ALGORITMI COMBINATORIALI

8.1.2 Num˘ arul funct ¸iilor surjective

Se dau mult imile X = x1 , x2 ,...,x m si Y = y1 , y2 ,...,y n .Fie S m,n num arul funct iilor surjective f : X −→Y .Fie A = f |f : X −→Y (mult imea tuturor funct ¸iilor denite pe X cu valori

ın Y ) si Ai = f |f : X −→Y, yi /∈f (X )(mult imea funct iilor pentru care yi nueste imaginea nici unui element din X ).

Atunci

S m,n = |A| − |n

i=1Ai |

Folosind principiul includerii si al excluderii, obt ¸inem

S m,n = |A| −n

i=1 |Ai |+ 1≤i<j ≤n |Ai ∩Aj | −... + ( −1)n

|A1 ∩A2 ∩... ∩An |Se poate observa usor c˘ a |A| = nm , |Ai | = ( n −1)m , |Ai ∩Aj | = ( n −2)m ,

etc.Din Y putem elimina k elemente ın C kn moduri, deci

1≤i 1 <i 2 <...<i k ≤n|

k

j =1

Ai j | = C kn (n −k)m

Rezult a:

S m,n = nm −C 1n (n −1)m + C 2n (n −2)m + ... + ( −1)n −1C n −1n

Observat¸ii:1. Deoarece A1 ∩A2 ∩... ∩An = ∅si pentru c˘a nu poate exista o funct¸ie care

sa nu ia nici o valoare, ultimul termen lipseste.2. Daca n = m atunci num˘arul funct iilor surjective este egal cu cel al funct ¸iilor

injective, deci S m,n = n! si se obtine o formul a interesant˘a:

n! =n −1

k=0

(−1)k C kn (n −k)n

class Surjectii

public static void main (String[]args)

int m, n=5, k, s;for(m=2;m<=10;m++)

s=0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 123/518

8.1. PRINCIPIUL INCLUDERII SI AL EXCLUDERII SI APLICATII 111

for(k=0;k<=n-1;k++)s=s+comb(n,k)*putere(-1,k)*putere(n-k,m);

System.out.println(m+" : "+s);System.out.println("GATA");

static int putere (int a, int n)

int rez=1, k;for(k=1;k<=n;k++) rez=rez*a;return rez;

static int comb (int n, int k)

int rez, i, j, d;int[] x=new int[k+1];int[] y=new int[k+1];for(i=1;i<=k;i++) x[i]=n-k+i;for(j=1;j<=k;j++) y[j]=j;for(j=2;j<=k;j++)

for(i=1;i<=k;i++)

d=cmmdc(y[j],x[i]);y[j]=y[j]/d;

x[i]=x[i]/d;if(y[j]==1) break;

rez=1;for(i=1;i<=k;i++) rez=rez*x[i];return rez;

static int cmmdc (int a,int b)

int d,i,c,r;if (a>b) d=a;i=b; elsed=b;i=a;while (i!=0) c=d/i; r=d%i; d=i; i=r; return d;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 124/518

112 CAPITOLUL 8. ALGORITMI COMBINATORIALI

8.1.3 Num˘ arul permutarilor f˘ ar a puncte xe

Fie X = 1, 2,...,n . Daca p este o permutare a elementelor mult ¸imii X ,spunem c a num arul i este un punct x al permut˘ arii p, dac a p(i) = i (1 ≤ i ≤n).

Se cere sa se determine num˘arul D (n) al permut˘arilor f ar a puncte xe, alemult imii X . Sa not am cu Ai mult imea celor ( n−1)! permut ari care admit un punctx ın i (dar nu obligatoriu numai acest punct x!). Folosind principiul includeriisi al excluderii, num˘arul permut˘arilor care admit cel put ¸in un punct x este egalcu:

|A1∪A2∪...∪An | =n

i=1|Ai | −

1≤i<j ≤n|Ai ∩Aj |+ ... + ( −1)n −1|

n

i=1Ai |.

Dar |Ai 1 ∩Ai 2 ∩... ∩Ai k | = ( n −k)!

deoarece o permutare din mult ¸imea Ai 1 ∩Ai 2 ∩... ∩Ai k are puncte xe ın pozit ¸iilei1 , i2 ,...,i k , celelalte pozit ii cont in and o permutare a celor n −k elemente r amase(care pot avea sau nu puncte xe!). Cele k pozit ii i1 , i2 ,...,i k pot alese ın C knmoduri, deci

|A1∪A2∪...∪An | = C 1n (n −1)! −C 2n (n −2)! + ... + ( −1)n −1C nn .

Atunci

D(n) = n!− |A1∪A2∪...∪An | =

= n!−C 1n (n −1)! + C

2n (n −2)! −+ ... + ( −1)

n

C nn

= n! 1 −11!

+12! −

13!

+ ... +(−1)n

n!.

De aici rezult a calim

n →∞D (n)

n!= e−1 ,

deci, pentru n mare, probabilitatea ca o permutare a n elemente, aleas˘a aleator,sa nu aib a puncte xe, este de e−1 ≈0.3678.

Se poate demonstra usor c˘ a:

D (n + 1) = ( n + 1) D(n) + ( −1)n +1

D (n + 1) = n (D(n) + D(n

−1)) .

class PermutariFixe

public static void main(String [] args)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 125/518

8.2. PRINCIPIUL CUTIEI LUI DIRICHLET SI APLICATII 113

long n=10,k,s=0L,xv,xn; // n=22 maxim pe long !if((n&1)==1) xv=-1L; else xv=1L;s=xv;for(k=n;k>=3;k--) xn=-k*xv; s+=xn; xv=xn; System.out.println("f("+n+") = "+s);

8.2 Principiul cutiei lui Dirichlet si aplicat ¸ii

Acest principiu a fost formulat prima dat˘ a de Dirichle (1805-1859).In forma cea mai simpl˘a acest principiu se enunt ¸ a astfel:

Dac˘ a n obiecte trebuie ımp˘ art ite ın mai put in de n mult imi, atunci exist˘ a cel put ¸in o mult ime ın care vor cel put in dou˘ a obiecte .

Mai general, principiul lui Dirichlet se poate enunt ¸a astfel:

Fiind date m obiecte, care trebuie ımp˘ art ite ın n mult imi, si un num˘ ar natural k astfel ıncˆat m > kn , atunci, ın cazul oric˘ arei ımp art iri, va exista cel put in o mult ime cu cel put in k + 1 obiecte.

Pentru k = 1 se obt ine formularea anterioar˘ a.Cu ajutorul funct ¸iilor, principiul cutiei se poate formula astfel:

Fie A si B doua mult imi nite cu |A| > |B | si funct ia f : A −→B .Atunci, exist˘a b

B cu proprietatea c˘ a

|f −

1(b)

| ≥2. Daca not am

|A| = n si |B | = r atunci |f −1(b)| ≥ nr .

Demonstr˘am ultima inegalitate. Dac˘ a aceasta nu ar adev˘ arat˘a, atunci

|f −1(b)| <nr

,∀b∈B.

Dar mult imea B are r elemente, deci

n =b∈B

|f −1(b)| < r ·nr

= n

ceea ce este o contradict¸ie.

8.2.1 Problema subsecvent ¸ei

Se da un sir nit a1 , a 2 ,...,a n de numereıntregi. Exist˘ a o subsecvent a a i , a i+1 ,...,a jcu proprietatea c˘ a a i + a i+1 + ... + a j este un multiplu de n.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 126/518

114 CAPITOLUL 8. ALGORITMI COMBINATORIALI

Sa consider am urm atoarele sume:

s1 = a1 ,s2 = a1 + a2 ,...sn = a1 + a2 + ... + an .

Daca exist a un k astfel sk este multiplu de n atunci i = 1 si j = k.Daca nici o suma part ial a sk nu este multiplu de n, atunci resturile ımp˘ art irii

acestor sume part ¸iale la n nu pot dec at ın mult¸imea 1, 2,...,n −1. Pentru c˘aavem n sume part iale si numai n −1 resturi, ınseamn˘ a ca exist a cel put in dou asume part iale ( sk 1 si sk 2 , unde k1 < k 2) cu acelasi rest. Atunci subsecvent ¸a c autat˘ase obtine lu and i = k1 + 1 si j = k2 .

8.2.2 Problema subsirurilor strict monotone

Se da sirul de numere reale distincte a1 , a2 ,...,a mn +1 . Atunci, sirul cont ¸ineun subsir cresc˘ator de m + 1 elemente:

a i 1 < a i 2 < ... < a i m +1 unde 1 ≤ i1 < i 2 < ... < i m +1 ≤mn + 1 ,

sau un subsir descresc˘ ator de n + 1 elemente

a j 1 < a j 2 < ... < a j n +1 unde 1 ≤ j 1 < j 2 < ... < j n +1 ≤mn + 1 ,

sau ambele tipuri de subsiruri.Fiecarui element al sirului ıi asociem perechea de numere naturale ( x i , yi )

unde x i este lungimea maxim˘a a subsirurilor cresc˘ atoare care ıncep cu a i iar yieste lungimea maxim˘a a subsirurilor descresc˘ atoare care ıncep ın a i .

Presupunem c˘a armat ia problemei nu este adev˘ arat a, adic a: pentru toatenumerele naturale x i si yi avem 1 ≤ x i ≤ m si 1 ≤ yi ≤ n. Atunci perechile denumere ( x i , yi ) pot avea mn elemente distincte.

Deoarece sirul are mn +1 termeni, exist˘ a un a i si un a j pentru care perechilede numere ( x i , yi ) si ( x j , yj ) sunt identice ( x i = x j , yi = yj ), dar acest lucru esteimposibil (cei doi termeni a i si a j ar trebui s˘a coincid a), ceea ce este o contradit ¸ie.

Deci exist a un subsir cresc˘ator cu m + 1 termeni sau un subsir descresc˘ atorcu n + 1 termeni.

8.3 Numere remarcabile

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 127/518

8.3. NUMERE REMARCABILE 115

8.3.1 Numerele lui Fibonacci

Numerele lui Fibonacci se pot deni recursiv prin:

F 0 = 0 , F 1 = 1 , F n = F n −1 + F n −2 pentru n ≥2. (8.3.1)

Primele numere Fibonacci sunt:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,...

Se poate ar ata c a

F n =1

2n √51 + √5

n

− 1 −√5n

.

Numerele lui Fibonacci satisfac multe identit˘ at i interesante, ca de exemplu:

1 11 0

n

= F n +1 F nF n F n −1

(8.3.2)

F n +1 F n −1 −F 2n = ( −1)n (8.3.3)F n + m = F m F n +1 + F m −1F n (8.3.4)

F nk = multiplu de F k (8.3.5)(8.3.6)

si

F 2 + F 4 + ... + F 2n = F 2n +1 −1 (8.3.7)F 1 + F 3 + ... + F 2n −1 = F 2n (8.3.8)

F 21 + F 22 + ... + F 2n = F n F n +1 (8.3.9)F 1F 2 + F 2F 3 + ... + F 2n −1F 2n = F 22n (8.3.10)F 1F 2 + F 2F 3 + ... + F 2n F 2n +1 = F 22n +1 −1 (8.3.11)

Teorema 2 Orice num˘ ar natural n se poate descompune ıntr-o sum˘ a de numereFibonacci. Dac˘ a nu se folosesc ın descompunere numerele F 0 si F 1 si nici dou˘ a numere Fibonacci consecutive, atunci aceast˘ a descompunere este unic˘ a abstract ie f˘ acand de ordinea termenilor.

Folosind aceast˘a descompunere, numerele naturale pot reprezentate asem˘ an atorreprezent˘arii ın baza 2. De exemplu

19 = 1 ·13 + 0 ·8 + 1 ·5 + 0 ·3 + 0 ·2 + 1 ·1 = (101001) F

In aceast a scriere nu pot exista dou˘ a cifre 1 alaturate.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 128/518

116 CAPITOLUL 8. ALGORITMI COMBINATORIALI

import java.io.*;class DescFibo

static int n=92;static long[] f=new long[n+1];

public static void main (String[]args) throws IOException

int iy, k, nrt=0;long x,y; // x=1234567890123456789L; cel mult!BufferedReader br=new BufferedReader(new InputStreamReader(System.in));System.out.print("x = ");x=Long.parseLong(br.readLine());f[0]=0;f[1]=1;f[2]=1;for(k=3;k<=n;k++) f[k]=f[k-1]+f[k-2];for(k=0;k<=n;k++) System.out.println(k+" : "+f[k]);System.out.println(" "+Long.MAX_VALUE+" = Long.MAX_VALUE");System.out.println(" x = "+x);while(x>0)

iy=maxFibo(x);y=f[iy];nrt++;System.out.println(nrt+" : "+x+" f["+iy+"] = "+y);

x=x-y;

static int maxFibo(long nr)

int k;for(k=1;k<=n;k++) if (f[k]>nr) break;return k-1;

8.3.2 Numerele lui Catalan

Numerele

C n =1

n + 1C n2n

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 129/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 130/518

118 CAPITOLUL 8. ALGORITMI COMBINATORIALI

a[j][i+j]=a[j][i+j]%10;a[j][i+j]=t;

t=0;for(j=0;j<m+n;j++)

z[j]=t;for(i=0;i<m;i++) z[j]=z[j]+a[i][j];t=z[j]/10;z[j]=z[j]%10;

if(z[m+n-1]!= 0) return z;else

int[]zz=new int[m+n-1];for(i=0;i<=m+n-2;i++) zz[i]=z[i];return zz;

static void afisv(int[]x)

int i;for(i=x.length-1;i>=0;i--) System.out.print(x[i]);System.out.print(" *** "+x.length);

System.out.println();

static int[] nrv(int nr)

int nrrez=nr;int nc=0;while(nr!=0) nc++; nr=nr/10; int[]x=new int [nc];nr=nrrez;nc=0;while(nr!=0) x[nc]=nr%10; nc++; nr=nr/10; return x;

static int[] Catalan(int n)

int[] rez;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 131/518

8.4. DESCOMPUNEREA IN FACTORI PRIMI 119

int i, j, d;int[] x=new int[n+1];int[] y=new int[n+1];for(i=2;i<=n;i++) x[i]=n+i;for(j=2;j<=n;j++) y[j]=j;for(j=2;j<=n;j++)

for(i=2;i<=n;i++)

d=cmmdc(y[j],x[i]);y[j]=y[j]/d;x[i]=x[i]/d;if(y[j]==1) break;

rez=nrv(1);for(i=2;i<=n;i++) rez=inm(rez,nrv(x[i]));return rez;

static int cmmdc (int a,int b)

int d,i,c,r;if (a>b) d=a;i=b; elsed=b;i=a;while (i!=0) c=d/i; r=d%i; d=i; i=r; return d;

8.4 Descompunerea ın factori primi

8.4.1 Funct ¸ia lui Euler

Funct ia φ(n) a lui Euler ne d a num arul numerelor naturale mai mici ca n siprime cu n.

Num arul n poate descompus ın factori primi sub forma:

n = pα 1

1pα 2

2...pα m

m

Not am cu Ai mult imea numerelor naturale mai mici ca n care sunt multipli de pi .Atunci avem:

|Ai | =n

pi, |Ai ∩Aj | =

n pi pj

, |Ai ∩Aj ∩Ak | =n

pi pj pk,...

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 132/518

120 CAPITOLUL 8. ALGORITMI COMBINATORIALI

Rezult a:

φ(n) = n −m

i =1

n pi

+1≤i<j ≤m

n pi pj −

1≤i<j<k ≤m

n pi pj pk

+ ... + ( −1)m n p1 p2 ...pm

care este tocmai dezvoltarea produsului

φ(n) = n 1 −1

p11 −

1 p2

... 1 −1

pm

class Euler

static long[] fact;public static void main (String[]args)

long n=36L; // Long.MAX_VALUE=9.223.372.036.854.775.807;long nrez=n;long[] pfact=factori(n);// afisv(fact);// afisv(pfact);int k,m=fact.length-1;for(k=1;k<=m;k++) n/=fact[k];for(k=1;k<=m;k++) n*=fact[k]-1;System.out.println("f("+nrez+") = "+n);

static long[] factori(long nr)

long d, nrrez=nr;int nfd=0; // nr. factori distinctiboolean gasit=false;while((nr!=1)&(nr%d==0)) nr=nr/d; gasit=true; if(gasit) nfd++;gasit=false;d=3;while(nr!=1)

while((nr!=1)&(nr%d==0)) nr=nr/d; gasit=true; if(gasit) nfd++;gasit=false;d=d+2;

nr=nrrez;fact=new long[nfd+1];long[] pf=new long[nfd+1];int pfc=0; // puterea factorului curentnfd=0; // nr. factori distincti

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 133/518

8.4. DESCOMPUNEREA IN FACTORI PRIMI 121

gasit=false;d=2;while((nr!=1)&(nr%d==0)) nr=nr/d; gasit=true; pfc++; if(gasit) fact[++nfd]=d;pf[nfd]=pfc;gasit=false;pfc=0;d=3;while(nr!=1)

while((nr!=1)&(nr%d==0)) nr=nr/d; gasit=true; pfc++; if(gasit) fact[++nfd]=d;pf[nfd]=pfc;gasit=false;pfc=0;d=d+2;

return pf;

//descfact

static void afisv(long[] a)

for(int i=1;i<a.length;i++) System.out.print(a[i]+" ");System.out.println();

8.4.2 Num˘ arul divizorilor

Fien = f e1

1 ·f e 22 ·... ·f e k

k

descompunerea lui n ın factori primi si ndiv (n) num arul divizorilor lui n . Atuncindiv (n) = (1 + e1) ·(1 + e2) ·... ·(1 + ek ).

8.4.3 Suma divizorilor

Fien = f e1

1 ·f e 22 ·... ·f e k

k

descompunerea lui n ın factori primi si sdiv (n) suma divizorilor lui n. Atunci

sdiv (n) =

d |nd =

f (1+ e1 )1 −1

f 1

−1 ·

f (1+ e 2 )2 −1

f 2

−1 ·... ·

f (1+ e k )k −1

f k

−1

.

Demonstrat ie:Fie n = ab cu a = b si cmmdc (a, b) = 1. Pentru orice divizor d al lui n,

d = a i bj , unde a i este divizor al lui a iar bj este divizor al lui b. Divizorii lui asunt: 1 , a1 , a 2 ,...,a . Divizorii lui b sunt: 1 , b1 , b2 ,...,b.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 134/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 135/518

8.6. PARTITIA MULTIMILOR 123

care poate transformat˘ a astfel:

P (n, k ) = P (n −1, k −1) + P (n −k, k)P (n −1, k −1) = P (n −2, k −2) + P (n −k, k −1)P (n −2, k −2) = P (n −3, k −3) + P (n −k, k −2)

...P (n −k + 3 , 3) = P (n −k + 2 , 2) + P (n −k, 3)P (n −k + 2 , 2) = P (n −k + 1 , 1) + P (n −k, 2)

Prin reducere si t ¸in and cont c a P (n −k + 1 , 1) = 1 = P (n −k, 1) obtinemrelat ia dat˘a la ınceput.

8.5.2 Partit ¸ia lui n ın cel mult k termeni

Fie A(n, k ) num arul modalit˘at ilor de a descompune num˘ arul natural n casuma de cel mult k termeni nenuli, considerˆ and dou a descompuneri ca ind dis-tincte dac˘a difer a prin cel put in un termen (deci, f˘ ar a a tine cont de ordineatermenilor).

AtunciA(n, k ) = A(n, k −1) + A(n −k, k)

Evident A(i, j ) = A(i, i ) pentru orice j > i iar A(n, n ) reprezint˘a num arulpartit¸iilor lui n.

(1) Num arul partit¸iilor ın cel mult k factori este egal cu num˘arul partit¸iilorın exact k factori plus num˘arul partit iilor ın cel mult k −1 termeni.

(2) Dat a ind o partit¸ie a lui n ın exact k termeni nenuli, putem sc˘ adea 1din ecare termeni, obt ¸in and o partit¸ie a lui n −k ın cel mult k termeni nenuli.Astfel, exist a o corespondent a bijectiv a ıntre partit ¸iile lui n ın exact k termeni sipartit¸iile lui n −k ın cel mult k factori.

8.5.3 Partit ¸ii multiplicative

Fie A(n, k ) num arul modalit˘at ilor de a descompune num˘ arul natural n casuma de cel mult k termeni nenuli, considerˆ and dou a descompuneri ca ind dis-tincte dac˘a difer a prin cel put in un termen (deci, f˘ ar a a tine cont de ordinea

termenilor).

8.6 Partit ¸ia mult ¸imilor

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 136/518

124 CAPITOLUL 8. ALGORITMI COMBINATORIALI

Fie S (n, k ) num arul modalit˘at ilor de a partit ¸iona o mult ime A cu n elementeın k submult imi nevide, considerˆand dou a partit¸ii ca ind distincte dac˘ a difer aprin cel put in o submult¸ime (deci, f ar a a tine cont de ordinea submult ¸imilor).

AtunciS (n, k ) = S (n −1, k −1) + k ·S (n −1, k)

undeS (i, 1) = S (i, i ) = 1 pentru ( ∀)i ≥1

siA = A1∪A2∪...∪Ak ; Ai ∩Aj = ∅pentru i = j.

Demonstrat ie:Fie

A =

a1 , a 2 ,...,a n

o multime cu n elemente si

A1 , A2 ,...,A k

o partit ie oarecare.Elementul an poate

(1) ıntr-o submult ¸ime cu un singur element (chiar el!), sau

(2) ıntr-o submult ¸ime cu cel put in 2 elemente (printre care se g˘ aseste si el!).

Num arul partit¸iilor de tipul (1) este S (n −1, k −1) (far a elementul an raman

n −1 elemente si k −1 submult imi ın partit ¸ie).Num arul partit¸iilor de tipul (2) este k·S (n−1, k) (elimin and elementul an dinsubmult imea ın care se a˘ a, acea submult¸ime r amane nevid a!). Se pare c a nu esteprea clar (sau evident!) de ce apare totusi factorul k ın expresia k ·S (n −1, k)! Saprivim put in altfel lucrurile: consider˘ am toate partit ¸iile mult imii a1 , a 2 ,...,a n −1care au k submult imi; num arul acestora este S (n −1, k); introducerea elementuluian ın aceste partit ¸ii se poate face ın oricare din cele k submult imi; deci k·S (n−1, k)reprezint˘a num arul partit¸iilor din cazul (2).

8.7 Probleme rezolvate

1. Sa se determine num˘arul arborilor binari cu n varfuri.Rezolvare : Fie b(n) num arul arborilor binari cu n varfuri. Prin convent ¸ie

b0 = 1. Prin desene b1 = 1, b2 = 2, b3 = 5, si: dac˘a xam r ad acina arborelui,ne mai r aman n −1 varfuri care pot ap˘ area ın subarborele stˆ ang sau drept; dac˘ aın subarborele stˆ ang sunt k varfuri, ın subarborele drept trebuie s˘ a e n −1 −k

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 137/518

8.7. PROBLEME REZOLVATE 125

varfuri; cu acesti subarbori se pot forma ın total bk bn −1−k arbori; adunˆand acestevalori pentru k = 0 , 1,...,n

−1 vom obtine valoarea lui b

n. Deci, pentru n

≥1

bn = b0bn −1 + b1bn −2 + ... + bn −1b0 =n −1

k =0

bk bn −1−k

Se obtinebn =

1n + 1

C n2n

2. Care este num˘arul permut˘arilor a n obiecte cu p puncte xe?Rezolvare : Deoarece cele p puncte xe pot alese ın C pn moduri, si cele n − p

puncte r˘amase nu mai sunt puncte xe pentru permutare, rezult a ca num arulpermut˘arilor cu p puncte xe este egal cu

C pn D (n − p)

deoarece pentru ecare alegere a celor p puncte xe exist a D(n − p) permut˘ari aleobiectelor r amase, f ar a puncte xe.

3. Fie X = 1, 2,...,n . Daca E (n) reprezint˘a num arul permut˘arilor pare 1

ale mult imii X far a puncte xe, atunci

E (n) =12

D(n) + ( −1)n −1(n −1) .

Rezolvare: Fie Ai mult imea permut˘ arilor pare p astfel ıncˆat p(i) = i. Deoarecenum arul permut˘arilor pare este 1

2 n!, rezult a ca

E (n) = 12n!− |A1∪...∪An | =

=12

n!−C 1n (n −1)! + C 2n (n −2)! + ... + ( −1)n C nn .

Tinˆand cont c a

|Ai 1 ∩Ai 2 ∩... ∩Ai k | = ( n −k)!

rezult a formula cerut˘a.

1 Dac a i < j , si ın permutare i apare dup˘ a j , spunem c˘a avem o inversiune . O permutare estepar˘ a dac a are un num˘ ar par de inversiuni

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 138/518

126 CAPITOLUL 8. ALGORITMI COMBINATORIALI

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 139/518

Capitolul 9

Algoritmi de cautare

9.1 Problema cautarii

Problema c˘aut arii este: se d a un vector a cu n elemente si o valoare x deacelasi tip cu elementele din a. Sa se determine p astfel ıncˆat x = a[ p] sau −1 dacanu exist a un element cu valoarea v ın a.

O tabel a cu campuri care nu sunt de acelasi tip se poate organiza cu a jutorulvectorilor dac˘a num arul de coloane este sucient de mic. De exemplu, o tabel˘ a cutrei informat¸ii: num ar curent, nume, telefon poate organizat˘ a cu ajutorul a doivectori (nume si telefon) iar num˘ arul curent este indicele din vector.

9.2 Cautarea secvent ¸iala

static int cauta (String x) for (int i = 0; i < N; ++i)

if (x.equals(nume[i])) return telefon[i];return 1;

se poate scrie si sub forma:

static int cauta (String x) int i = 0;while (i < N && !x.equals(nume[i])) ++i;if (i < N) return telefon[i];else return 1;

127

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 140/518

128 CAPITOLUL 9. ALGORITMI DE C ˘ AUTARE

O alt a posibilitate este de a pune o santinel˘ a ın cap˘atul tabelei.

static int cauta (String x) int i = 0;nume[N] = x; telefon[N] = 1;while (! x.equals(nume[i])) ++i;return tel[i];

Scrierea procedurii de c˘autare ıntr-un tabel de nume este ın acest caz maiecient a, pentru c˘a nu se face decat un singur test ın plus aici (ın loc de dou˘ a teste).Cautarea secvent ¸ial a se mai numeste si c˘autare linear˘a, pentru c˘a se execut a N/ 2operat ii ın medie, si N operat ii ın cazul cel mai defavorabil. Intr-un tablou cu10.000 elemente, c autarea execut˘ a 5.000 operat ii ın medie, ceea ce ınseamn˘ a unconsum de timp de aproximativ 0.005 ms (milisecunde).

Iat a un program complet care utilizeaz˘ a cautarea linear˘ a ıntr-o tabel˘ a.

class Tabela

final static int N = 6;static String nume[] = new String[N+1];static int telefon[] = new int[N+1];

static void initializare() nume[0] = "Paul"; telefon[0] = 2811;nume[1] = "Robert"; telefon[1] = 4501;nume[2] = "Laura"; telefon[2] = 2701;

nume[3] = "Ana"; telefon[3] = 2702;nume[4] = "Tudor"; telefon[4] = 2805;nume[5] = "Marius"; telefon[5] = 2806;

static int cauta(String x) for (int i = 0; i < N; ++i)

if (x.equals(nume[i]))return tel[i];

return 1;

public static void main (String args[]) initializare();if (args.length == 1)

System.out.println(cauta(args[0]));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 141/518

9.3. C ˘ AUTARE BINAR ˘ A 129

Cel mai simplu algoritm care rezolv˘ a aceast a problem a este c˘ autarea liniar˘ a ,care testeaz˘a elementele vectorului unul dupa altul, ıncepˆ and cu primul.

p=-1;for(i=0;i<n;i++)

if(x==a[i]) p=i; break;

Sa analiz am complexitatea acestui algoritm pe cazul cel mai defavorabil, acelaın care v nu se gaseste ın a. In acest caz se va face o parcurgere complet˘ a a lui a.Consider and ca operat¸ie elementar˘a testul v == a[i], numarul de astfel de operat¸iielementare efectuate va egal cu numarul de elemente al lui a, adic a n. Decicomplexitatea algoritmului pentru cazul cel mai defavorabil este O(n).

9.3 Cautare binara

O alt a tehnic a de cautare ın tabele este c˘ autarea binar˘ a. Presupunem c˘ atabela de nume este sortat˘ a ın ordine alfabetic˘ a (cum este cartea de telefoane).In loc de a cauta secvent¸ial, se compar˘a cheia de c autare cu numele care se af˘ ala mijlocul tabelei de nume. Dac˘ a acesta este acelasi, se returneaz˘ a num arul detelefon din mijloc, altfel se reıncepe c˘ autarea ın prima jum˘ atate (sau ın a doua)daca numele c autat este mai mic (respectiv, mai mare) decˆ at numele din mijlocultabelei.

static int cautareBinara(String x) int i, s, d, cmp;s = 0 ; d = N1;do

i = ( s + d) / 2 ;cmp = x.compareTo(nume[i]);if (cmp == 0)

return telefon[i];if (cmp < 0)

d = i - 1;else

s = i + 1; while (s <= d);return -1;

Num arul C N de comparat¸ii efectuate pentru o tabel˘ a de dimensiune N esteC N = 1 + C

⌊N/ 2⌋, unde C 0 = 1. Deci C N ≈ log2 N .

De acum ınaninte, log 2 N va scris mai simplu log N .Daca tabela are 10.000 elemente, atunci C N ≈ 14. Acesta reprezint a un

beneciu considerabil ın raport cu 5 .000 de operat ii necesare la c autarea linear˘ a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 142/518

130 CAPITOLUL 9. ALGORITMI DE C ˘ AUTARE

Desigur c autarea secvent ¸ial a este foarte usor de programat, si ea se poatefolosi pentru tabele de dimensiuni mici. Pentru tabele de dimensiuni mari, c˘ autareabinar a este mult mai interesant˘ a.

Se poate obt ine un timp sub-logaritmic dac˘ a se cunoaste distribut ¸ia obiectelor.De exemplu, ın cartea de telefon, sau ın dict ¸ionar, se stie apriori c˘ a un nume careıncepe cu litera V se aa catre sf arsit. Presupunˆ and distribut ¸ia uniform˘a, putemface o ”regul a de trei simpl a” pentru g˘asirea indicelui elementului de referint ¸apentru comparare, ın loc s˘ a alegem mijlocul, si s a urm am restul algoritmului decautare binar˘ a. Aceast a metod a se numeste c˘ autare prin interpolare . Timpul decautare este O(log log N ), ceea ce ınseamn˘a cam 4 operat ii pentru o tabel˘ a de10.000 elemente si 5 operat¸ii pentru 10 9 elemente ın tabel˘ a. Este spectaculos!

O implementare iterativ˘ a a caut arii binare ıntr-un vector ordonat (cresc˘ atorsau descresc ator) este:

int st, dr, m;boolean gasit;st=0;dr=n-1;gasit=false;while((st < dr) && !gasit)

m=(st+dr)/2;if(am]==x)

gasit=true;else if(a[m] > x)

dr=m-1;else st=m+1;

if(gasit) p=m; else p=-1;

Algoritmul poate descris, foarte elegant, recursiv.

9.4 Inserare ın tabela

La cautarea secvent ¸ial a sau binar˘a nu am fost preocupat ¸i de inserarea ıntabel a a unui nou element. Aceasta este destul de rar˘ a ın cazul c art ii de telefondar ın alte aplicat ¸ii, de exemplu lista utilizatorilor unui sistem informatic, estefrecvent utilizat˘ a.

Vom vedea cum se realizeaz˘ a inserarea unui element ıntr-o tabel˘ a, ın cazulcaut arii secvent iale si binare.

Pentru cazul secvent ¸ial este sucient s˘a ad augam la cap atul tabelei noulelement, dac˘a are loc. Dac a nu are loc, se apeleaz˘a o procedur a error care aseaz˘aun mesaj de eroare.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 143/518

9.5. DISPERSIA 131

void inserare(String x, int val) ++n;if (n >= N)

error ("Depasire tabela");numem[n] = x;telefon[n] = val;

Inserarea se face deci ın timp constant, de ordinul O(1).In cazul c aut arii binare, trebuie ment ¸inut tabelul ordonat. Pentru inserarea

unui element nou ın tabel˘ a, trebuie g˘asit a pozit ia sa printr-o c˘autare binar˘ a (sausecvent ial a), apoi se deplaseaz˘a toate elementele din spatele ei spre dreapta cu opozitie pentru a putea insera noul elementın locul corect. Aceasta necesit˘ a log n+ noperet ii. Inserarea ıntr-o tabel˘ a ordonat˘a cu n elemente este deci de ordinul O(n).

9.5 Dispersia

O alt a metod a de cautare ın tabele este dispersia . Se utilizeaz a o functie hde grupare a cheilor (adesea siruri de caractere) ıntr-un interval de numere ıntregi.Pentru o cheie x, h(x) este locul unde se af a x ın tabel˘a. Totul este ın ordine dac˘ ah este o aplicat ie injectiv˘a. De asemenea, este bine ca funct ¸ia aleas a sa permit˘aevaluarea cu un num˘ ar mic de operat¸ii. O astfel de funct ie este

h(x) = x1B m −1 + x2B m −2 + ... + xm −1B + xm mod N.

De obicei se ia B = 128 sau B = 256 si se presupune c˘a dimensiunea tabeleiN este un num˘ar prim. De ce? Pentru c˘ a ınmult¸irea puterilor lui 2 se poate facefoarte usor prin operat ¸ii de deplasare pe bit¸i, numerele ind reprezentateın binar.In general, la masinile (calculatoarele) moderne, aceste operat ¸ii sunt net mai rapidedecat ınmult ¸irea numerelor oarecare. Cˆ at despre alegerea lui N , aceasta se facepentru a evita orice interferent ¸a ıntre ıntre ınmult ¸irile prin B si ımp˘art irile prinN . Intr-adev˘ar, dac a de exemplu B = N = 256, atunci h(x) = x(m) este funct ia hcare nu depinde decˆat de ultimul caracter al lui x. Scopul este de a avea o funct ie h,de dispersie, simplu de calculat si avˆ and o bun a distribut¸ie pe intervalul [0 , N −1].Calculul funct iei h se face prin funct ia h(x,m) , unde m este lungimea sirului x,

static int h(String x)int r = 0;for (int i = 0; i < x.length(); ++i)

r = ((r * B) + x.charAt(i)) % N;return r;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 144/518

132 CAPITOLUL 9. ALGORITMI DE C ˘ AUTARE

Deci funct ia h da pentru toate cheile x o intrare posibil˘a ın tabel˘a. Se poateapoi verica dac˘a x = nume [h(x)]. Daca da, c autarea este terminat˘ a. Dac a nu,ınseamn˘a ca tabela cont¸ine o alt a cheie astfel ıncˆat h(x ′) = h(x). Se spune atuncica exist a o coliziune , si tabela trebuie s˘ a gestioneze coliziunile. O metod˘a simpl aeste de a lista coliziunile ıntr-un tabel col paralel cu tabelul nume. Tabela decoliziuni d a o alt a intrare i ın tabela de nume unde se poate g˘ asi cheia c autat˘a.Daca nu se gaseste valoarea x ın aceast˘a nou a intrare i, se continu a cu intrarea i′dat a de i′ = col[i]. Se continu a astfel c at timp col[i] = −1.

static int cauta(String x) for (int i = h(x); i != 1; i = col[i])

if (x.equals(nume[i]))return telefon[i];

return 1;

Astfel, procedura de c˘autare consum˘a un timp mai mare sau egal ca lungimea

medie a claselor de echivalent¸ a denite pe tabel˘a de valorile h(x), adic a de lungimeamedie a listei de coliziuni. Dac˘a funct ia de dispersie este perfect uniform˘ a, nu aparcoliziuni si determin˘ a toate elementele printr-o singur˘ a comparat¸ie. Acest caz estefoarte put in probabil. Dac˘ a num arul mediu de elemente avˆ and aceeasi valoare dedispersie este k = N/M , unde M este num arul claselor de echivalent¸a denitede h, cautarea ia un timp de N/M . Dispersia nu face decˆat s a reduc a printr-unfactor constant timpul c˘ aut arii secvent iale. Interesul fat ¸ a de dispersie este pentruca adesea este foarte ecace, si usor de programat.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 145/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 146/518

134 CAPITOLUL 10. ALGORITMI ELEMENTARI DE SORTARE

O alt a tehnic a (discut and serios de data aceasta), frecvent utilizat˘ a la un jocde cart i, const a ın a vedea dac˘a exist a o transpozit ie de efectuat. Dac˘a exist a, seface interschimbarea c˘ art ilor de joc si se caut˘a o alt a transpozit¸ie. Procedeul serepet a pan a cand nu mai exist˘a transpozit¸ii. Aceast˘a metod a funct ioneaz˘a foartebine pentru o bun˘a distribut¸ie a cart ilor.

Este usor de intuit c˘ a num arul obiectelor de sortat este important. Nu estecazul sa se caute o metod˘a sosticat˘a pentru a sorta 10 elemente. Cu alte cuvinte,nu se trage cu tunul ıntr-o musc˘ a !

Exemplele tratate ıntr-un curs sunt ıntotdeauna de dimensiuni limitate, dinconsiderente pedagogice nu este posibil de a prezenta o sortare a mii de elemente.

10.2 Sortare prin select ¸ie

In cele ce urmeaz a, presupunem c˘a trebuie s a sort am un num˘ar de ıntregi carese gasesc ıntr-un tablou (vector) a. Algoritmul de sortare cel mai simplu este prin select ie . El const a ın g asirea pozit iei ın tablou a elementului cu valoarea cea maimica, adic a ıntregul m pentru care a i ≥ am pentru orice i. Odat a gasit a aceast apozitie m, se schimba ıntre ele elementele a1 si am .

Apoi se reıncepe aceast˘ a operat ie pentru sirul ( a2 , a3 ,...,a N ), tot la fel,caut andu-se elementul cel mai mic din acest sir si interschimbˆ andu-l cu a2 . Siasa mai departe pˆ an a la un moment dat cˆ and sirul va cont¸ine un singur element.

Cautarea celui mai mic element ıntr-un tablou este un prim exercit ¸iu deprogramare. Determinarea pozit ¸iei acestui element este foarte simpl˘ a, ea se poateefectua cu ajutorul instruct ¸iunilor urm˘atoare:

m = 0;for (int j = 1; j < N; ++j)

if (a[j] < a[m]) m = i;

Schimbarea ıntre ele a celor dou˘ a elemente necesit˘a o variabil a temporar˘a tsi se efectueaz a prin:

t = a[m]; a[m] = a[1]; a[1] = t;

Acest set de operat¸ii trebuie reluat prin ınlocuirea lui 1 cu 2, apoi cu 3 siasa mai departe pˆ ana la N . Aceasta se realizeaz˘a prin introducerea unei variabilei care ia toate valorile ıntre 1 si N .

Toate acestea sunt ar˘ atate ın programul care urmeaz˘ a.De aceast a dat a vom prezenta programul complet.Procedurile de achizit¸ionare a datelor si de returnare a rezultatelor sunt

deasemenea prezentate.Pentru alt ¸i algoritmi, ne vom limita la descrierea efectiv˘ a a sort arii.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 147/518

10.2. SORTARE PRIN SELECTIE 135

class SortSelectie

final static int N = 10;static int[] a = new int[N];

static void initializare()

int i;for (i = 0; i < N; ++i)

a[i] = (int) (Math.random() * 128);

static void afisare()

int i;for (i = 0; i < N; ++i)

System.out.print (a[i] + " ");System.out.println();

static void sortSelectie()

int min, t;int i, j;for ( i = 0; i < N 1; ++i)

min = i;for (j = i+1; j < N; ++j)if (a[j] < a[min])

min = j;t = a[min];a[min] = a[i];a[i] = t;

public static void main (String args[])

initializare();afisare();sortSelectie();afisare();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 148/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 149/518

10.2. SORTARE PRIN SELECTIE 137

Se poate calcula de asemenea foarte usor num˘ arul de operat¸ii si se obt ine unnum ar de ordinul O(N 2) comparat¸ii si, eventual interschimb˘ ari (dac a, de exemplu,tabloul este init¸ial ın ordine descresc˘ atoare).

static void sortBule() int t;for (int i = N1; i >= 0; i)

for (int j = 1; j <= i; ++j)if (a[j1] > a[j])

t = a[j1]; a[j1] = a[j]; a[j] = t;

0 1 2 3 4 5 6 77 12 4 30 3 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 77 4 12 30 3 4 23 14

↑ ↑ j i0 1 2 3 4 5 6 77 4 12 30 3 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 77 4 12 3 30 4 23 14

↑ ↑ j i0 1 2 3 4 5 6 77 4 12 3 30 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 77 4 12 3 4 30 23 14

↑ ↑ j i

0 1 2 3 4 5 6 77 4 12 3 4 30 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 77 4 12 3 4 23 30 14

↑ ↑ j i0 1 2 3 4 5 6 77 4 12 3 4 23 30 14

↑↑ ji⇒

0 1 2 3 4 5 6 77 4 12 3 4 23 14 30

↑↑ jiDup a prima parcurgere 30 a ajuns pe locul s au (ultimul loc ın vector).

0 1 2 3 4 5 6 77 4 12 3 4 23 14 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 7 12 3 4 23 14 30

↑ ↑ j i0 1 2 3 4 5 6 74 7 12 3 4 23 14 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 7 3 12 4 23 14 30

↑ ↑ j i

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 150/518

138 CAPITOLUL 10. ALGORITMI ELEMENTARI DE SORTARE

0 1 2 3 4 5 6 74 7 3 12 4 23 14 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 7 3 4 12 23 14 30

↑ ↑ j i0 1 2 3 4 5 6 74 7 3 4 12 23 14 30

↑↑ ji⇒

0 1 2 3 4 5 6 74 7 3 4 12 14 23 30

↑↑ jiDup a a doua parcurgere 23 a ajuns pe locul s au (penultimul loc ın vector).

0 1 2 3 4 5 6 74 7 3 4 12 14 23 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 3 7 4 12 14 23 30

↑ ↑ j i

0 1 2 3 4 5 6 74 3 7 4 12 14 23 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 3 4 7 12 14 23 30

↑ ↑ j iDup a a treia parcurgere 14 a ajuns pe locul s au (de fapt era deja pe locul

sau de la ınceputul acestei parcurgeri; s-au mai aranjat totusi cˆateva elemente!).0 1 2 3 4 5 6 74 3 4 7 12 14 23 30

↑ ↑ j i⇒

0 1 2 3 4 5 6 73 4 4 7 12 14 23 30

↑ ↑ j iDup a a patra parcurgere 12 a ajuns pe locul s au (de fapt era deja pe locul s˘au

de la ınceputul acestei parcurgeri; oricum, la aceast˘ a parcurgere s-au mai aranjat

cateva elemente!).La urm atoarea parcurgere nu se efectueaz˘ a nici o interschimbare de elemente.Vectorul este deja sortat, asa c˘ a urm atoarele parcurgeri se fac, de asemenea, f˘ ar asa se execute nici o interschimbare de elemente. O idee bun˘ a este introducerea uneivariabile care s˘a contorizeze num˘arul de interschimb˘ ari din cadrul unei parcurgeri.Daca nu s-a efectuat nici o interschimbare atunci vectorul este deja sortat asa c˘ ase poate ıntrerupe execut ¸ia urm˘atoarelor parcurgeri. Programul modicat este:

static void sortBule() int t, k;for (int i = N1; i >= 0; i)

k=0;for (int j = 1; j <= i; ++j)

if (a[j1] > a[j]) t = a[j1]; a[j1] = a[j]; a[j] = t; k++;if(k==0) break;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 151/518

10.3. SORTARE PRIN INSERTIE 139

10.3 Sortare prin insert ¸ie

O metod a complet diferit˘a este sortarea prin insert ¸ie . Aceasta este metodautilizat˘a pentru sortarea unui pachet de c˘ art i de joc. Se ia prima carte, apoi adoua si se aranjeaz˘a ın ordine cresc˘atoare. Se ia a treia carte si se plaseaz˘ a pepozitia corespunz˘atoare fat a de primele dou a cart i, si asa mai departe. Pentrucazul general, s a presupunem c˘a primele i −1 cart i sun deja sortate cresc˘ ator. Seia a i-a carte si se plaseaz˘a pe pozit ia corespunz˘atoare relativ la primele i −1 cart ideja sortate. Se continu˘ a pan a la i = N .

10.3.1 Insert ¸ie direct˘ a

Daca determinarea pozit ¸iei corespunz˘atoare, ın subsirul format de primelei −1 elemente, se face secvent ial, atunci sortarea se numeste sortare prin insert ¸iedirect˘ a . Procedura care realizeaz˘ a aceastsortare este:

static void sortInsertie() int j, v;for (int i = 1; i < N; ++i)

v = a[i]; j = i;while (j > 0 && a[j-1] > v)

a[j] = a[j-1];j;

a[j] = v;

Pentru plasarea elementului a i din vectorul nesortat (elementele de pe pozit ¸iiledin st anga ind deja sortate) se parcurge vectorul spre stˆ anga plec and de la pozit iai −1. Elementele vizitate se deplaseaz˘ a cu o pozitie spre dreapta pentru a permiteplasarea elementului a i (a carui valoare a fost salvat˘ a n variabila temporar˘ a v) pepozitia corespunz˘atoare. Procedura cont ¸ine o mic a eroare, dac˘a a i este cel mai micelement din tablou, c˘ aci va iesi din tablou spre stˆ anga. Se poate remedia aceast˘ asituat ie plas and un element a0 de valoare −max int . Se spune ca a fost plasat˘ao santinel˘ a la st anga tabloului a. Aceasta nu este ıntotdeauna posibil, si atuncitrebuie ad˘augat un test asupra indicelui j ın bucla while . Un exemplu numericeste cel care urmeaz˘a:

Inserarea lui 12 nu necesit a deplas ari de elemente.0 1 2 3 4 5 6 77 12 4 30 3 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 74 7 12 30 3 4 23 14

↑ ↑ j i

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 152/518

140 CAPITOLUL 10. ALGORITMI ELEMENTARI DE SORTARE

Inserarea lui 30 nu necesit a deplas ari de elemente.

0 1 2 3 4 5 6 74 7 12 30 3 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 73 4 7 12 30 4 23 14

↑ ↑ j i0 1 2 3 4 5 6 73 4 7 12 30 4 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 73 4 4 7 12 30 23 14

↑ ↑ j i0 1 2 3 4 5 6 73 4 4 7 12 30 23 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 73 4 4 7 12 23 30 14

↑ ↑ j i0 1 2 3 4 5 6 73 4 4 7 12 23 30 14

↑ ↑ j i⇒

0 1 2 3 4 5 6 73 4 4 7 12 14 23 30

↑ ↑ j iNum arul de comparat¸ii pentru inserarea unui elementın secvent ¸a deja sortat˘ a

este egal cu num arul de inversiuni plus 1.Fie ci num arul de comparat¸ii. Atunci

ci = 1 + card a j |a j > a i , j < i Pentru o permutare π corespunz atoare unui sir de sort˘ ari, unde num˘arul de

inversiuni este inv (π), num arul total de comparat ¸ii pentru sortarea prin insert ¸ieeste

C π =N

i=2

ci = N −1 + inv (π).

Deci, num arul mediu de comparat ¸ii este

C N =1

N !π∈S N

C π = N −1 +N (N −1)

4=

N (N + 3)4 −1

unde S n reprezint˘a grupul permut˘ arilor de n elemente.Desi ordinul de crestere este tot N 2 , aceast a metod a de sortare este mai

ecient a decat sortarea prin select ¸ie. Cea mai bun˘a metod a de sortare necesit˘an log2 n comparat ii.

In plus, ea are o proprietate foarte bun˘ a: num arul de operat¸ii depinde puternicde ordinea init ial a din tablou. In cazul ın care tabloul este aproape ordonat, si drepturmare exist˘a put ine inversiuni si sunt necesare put ¸ine operat¸ii, spre deosebire deprimele dou a metode de sortare.

Sortarea prin inserare este deci o metod˘ a de sortare bun˘a dac a tabloul desortat are sansa de a aproape ordonat .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 153/518

10.3. SORTARE PRIN INSERTIE 141

10.3.2 Insert ie binara

Metoda anterioar˘ a se poate ımbunat˘ at i dac a t inem cont de faptul c˘ a secvent aın care se face inserarea este deja ordonat˘ a, iar ın loc s˘a se faca insert ia direct˘a ınaceast a secvent a, cautarea pozit¸iei pe care se face inserarea se face prin c˘ autarebinar a. Un program complet este:

import java.io.*;class SortInsBinApl

static int[] a=3,8,5,4,9,1,6,4;

static void afiseaza()

int j;for(j=0; j<a.length; j++)

System.out.print(a[j] + " ");System.out.println();

static int pozitiaCautBin(int p, int u, int x)

int i=u+1;while (p <= u)

i=(p+u)/2;

if (x>a[i])p=i+1;else if (x<a[i])

u=i-1;else return i;

return p;

static void deplasare(int k, int i)

if (i != k)

int x=a[k];for(int j=k; j>=i+1; j--) a[j]=a[j-1];a[i]=x;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 154/518

142 CAPITOLUL 10. ALGORITMI ELEMENTARI DE SORTARE

static void sorteaza()

int N=a.length,i;for(int k=1;k<=N-1;k++)

i=pozitiaCautBin(0,k-1,a[k]);deplasare(k,i);

public static void main(String[] args)

afiseaza();sorteaza();afiseaza();

10.4 Sortare prin interschimbare

Aceast a metod a foloseste interschimbarea ca si caracteristic˘ a principal˘a ametodei de sortare. In cadrul acestei metode se compar˘ a si se interschimb˘a perechiadiacente de chei pan˘ a cand toate elementele sunt sortate.

static void interschimbare(int a[])

int x, i, n=a.length;boolean schimb = true;while (!schimb)

schimb=false;for(i=0; i<n-1; i++)

if (a[i]>a[i+1])

x = a[i];a[i] = a[i+1];a[i+1] = x;schimb=true;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 155/518

10.5. SORTARE PRIN MICSORAREA INCREMENTULUI - SHELL 143

10.5 Sortare prin micsorarea incrementului - shell

Prezent˘am metoda pe urm˘ atorul sir:

44, 55, 12, 42, 94, 18, 6, 67.

Se grupeaz a elementele aate la 4 pozit¸ii distant¸a, si se sorteaz˘a separat.Acest proces este numit numit 4 sort . Rezult a sirul:

44, 18, 06, 42, 94, 55, 12, 67

Apoi se sorteaz a elementele aate la 2 pozit¸ii distant˘a. Rezult a:

6, 18, 12, 42, 44, 55, 94, 97

Apoi se sorteaz a sirul rezultat ıntr-o singur˘ a trecere: 1 - sort

6, 12, 18, 42, 44, 55, 94, 97

Se observa urm atoarele:

• un proces de sortare i −sort combin a 2 grupuri sortate ın procesul 2 i −sortanterior

• ın exemplul anterior s-a folosit secventa de increment ¸i 4, 2, 1 dar oricesecvent a, cu condit ia ca cea mai n a sortare s a e 1 −sort . In cazul celmai defavorabil, ın ultimul pas se face totul, dar cu multe comparat ii siinterschimb˘ari.

• daca cei t incrementi sunt h1 , h2 , .. h t , h t = 1 si h i +1 < h i , ecare h i -sortse poate implementa ca si o sortate prin insertie direct˘ a.

void shell(int a[], int n)

static int h[] = 9, 5, 3, 1;int m, x, i, j, k, n=a.length;for (m=0; m<4; m++)

k = h[m];/* sortare elemente aflate la distanta k in tablul a[] */for (i=k; i<n; i++)

x = a[i];

for (j = i-k; (j>=0) && (a[j]>x); j-=k) a[j+k] = a[j];a[j+k] = x;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 156/518

144 CAPITOLUL 10. ALGORITMI ELEMENTARI DE SORTARE

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 157/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 158/518

146 CAPITOLUL 11. LISTE

Lista (int x, Lista a) continut = x;urmator = a;

Instruct¸iunea new Lista(x,a) construieste o nou˘ a celula cu campurile x sia. Func tia Lista(x,a) este un constructor al clasei Lista (un constructor este ofunct ie nestatic˘a care se distinge prin tipul rezultatului s˘ au care este cel al claseicurente, si prin absent ¸a numelui de identicare). Obiectul null apart ine tuturorclaselor si reprezint˘ a ın cazul listelor marcajul de sfˆ arsit de list˘ a. De asemeneanew Lista(2, new Lista(7, new Lista(11,null))) reprezint˘a lista 2 , 7, 11.

static boolean esteVida (Lista a) return a == null;

Procedura adauga insereaz a un element ın capul listei. Aceast˘ a modalitate

de a introduce elemente ın capul listei este util˘ a pentru ca num˘arul de operat¸iinecesare ad augarii de elemente s a e independent de m˘arimea listei; este sucient˘ amodicarea valorii capului listei, ceea ce se face simplu prin:

static Lista adaug (int x, Lista a) return new Liste (x, a); // capul vechi se va regasi dupa x

e1e2e3e4

cap

e1e2e3e4

cap

Figura 11.1: Ad˘augarea unui element ın list˘ a

Funct ia cauta , care veric a dac a elementul x esteın lista a, efectueaz a o parcurgerea listei. Variabila a este modicat˘a iterativ prin a=a.urmator pentru a parcurgeelementele listei pˆan a se gaseste x sau p an a se gaseste sf arsitul listei ( a = null ).

static boolean cauta (int x, Lista a) while (a != null)

if (a.continut == x)return true;

a = a.urmator;return false;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 159/518

11.1. LISTE LINIARE 147

Funct ia cauta poate scris a ın mod recursiv:

static boolean cauta (int x, Lista a) if (a == null)

return false;else if (a.continut == x)

return true;else

return cauta(x, a.urmator);

sau sub forma:

static boolean cauta (int x, Lista a) if (a == null)

return false;else return (a.continut == x) || cauta(x, a.urmator);

sau sub forma:

static boolean cauta (int x, Lista a) return a != null && (a.continut == x || cauta(x, a.urmator));

Aceast a sciere recursiv a este sistematic˘a pentru funct¸iile care opereaz˘a asupralistelor. Tipul list˘ a verica ecuat ia urm˘atoare:

Lista = Lista vida ⊕Element ×Lista

unde ⊕este sau exclusiv iar × este produsul cartezian. Toate procedurile saufunct iile care opereaz˘a asupra listelor se pot scrie recursiv ın aceast˘ a manier a. Deexemplu, lungimea listei se poate determina prin:

static int lungime(Lista a) if (a == null) return 0;else return 1 + longime(a.urmator);

care este mai elegant˘a decat scrierea iterativ˘ a:

static int lungime(Lista a) int lg = 0;while (a != null)

++lg;a = a.urmator;

return lg;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 160/518

148 CAPITOLUL 11. LISTE

Alegerea ıntre maniera recursiv˘ a sau iterativ˘a este o problem a subiectiv a ıngeneral. Pe de alt˘a parte se spune c˘a scrierea iterativ˘ a este mai ecient˘a pentru c˘afoloseste mai put¸in a memorie. Grat¸ie noilor tehnici de compilare, acest lucru estemai put in adev arat; ocuparea de memorie suplimentar˘ a, pentru calculatoarele deast azi, este o problem a foarte put in critic˘a.

Eliminarea unei celule care cont ¸ine x se face modicand valoarea cˆampuluiurmator continut ın predecesorul lui x: succesorul predecesorului lui x devinesuccesorul lui x. Un tratament particular trebuie f˘ acut dac˘a elementul care trebuieeliminat este primul element din list˘ a. Procedura recursiv˘ a de eliminare este foartecompact a ın denit¸ia sa:

static Lista elimina (int x, Lista a) if (a != null)

if (a.continut == x)

a = a.urmator;else

a.urmator = elimina (x, a.urmator);return a;

e1e2e3e4

cap

e1e2e3e4

cap

Figura 11.2: Eliminarea unui element din list˘ a

O procedur a iterativ˘a solicit a un plus de atent¸ie.

static Lista elimina (int x, Lista a) if (a != null)

if (a.continut == x)a = a.urmator;

else Lista b = a ;while (b.urmator != null && b.urmator.continut != x)

b = b.urmator;if (b.urmator != null)

b.urmator = b.urmator.urmator;

return a;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 161/518

11.1. LISTE LINIARE 149

In cadrul funct¸iilor anterioare, care modic˘ a lista a, nu se dispune de dou˘aliste distincte, una care cont ¸ine x si alta identic˘ a cu precedenta dar care nu maicontine x. Pentru a face acest lucru, trebuie recopiat˘ a o parte a listei a ıntr-onoua list a, cum face programul urm˘ ator, unde exist a o utilizare put¸in important˘ ade memorie suplimentar˘ a. Oricum, spat¸iul de memorie pierdut este recuperat deculegatorul de spat¸iu de memorie GC (Garbage Colection) din Java, dac˘ a nu maieste folosit a lista a. Cu tehnicile actuale ale noilor versiuni ale GC, recuperarease efectueaz a foarte rapid. Aceasta este o diferent ¸ a important˘ a fat a de limbajelede programare precum Pascal sau C, unde trebuie s˘ a m preocupat¸i de spat iul dememorie pierdut, dac˘ a trebuie s a- l reutiliz am.

static Lista elimina (int x, Lista a) if (a != null)

return null;

else if (a.continut == x)return a.urmator;

elsereturn new Lista (a.continut, elimina (x, a.urmator));

Exist a o tehnic a, utilizat˘a adesea, care permite evitarea unor teste pentrueliminarea unui element dintr-o list˘ a si, ın general, pentru simplicarea program˘ ariioperat iilor asupra listelor. Aceasta const˘ a ın utilizarea unui fanion / santinel˘ a care permite tratarea omogen˘ a a listelor indiferent dac˘ a sunt vide sau nu. Inreprezentarea anterioar˘ a lista vid a nu a avut aceeasi structur˘ a ca listele nevide. Seutilizeaz a o celula plasat˘a la ınceputul listei, care nu are informat ¸ie semnicativ˘a

ın c ampul continut ; adresa adev˘aratei prime celule se a˘a ın c ampul urmator alacestei celule. Astfel obt¸inem o list a p˘ azit˘ a , avantajul ind c˘a lista vid a continenumai garda si prin urmare un num˘ ar de programe, care f˘aceau un caz special dinlista vid a sau din primul element din list˘ a, devin mai simple. Aceast˘ a notiune esteun pic echivalent˘a cu not iunea de santinel˘ a pentru tablouri. Se utilizeaz˘ a aceast atehnic a ın proceduri asupra sirurilor prea lungi.

De asemenea, se pot deni liste circulare cu gard˘ a / paznic ın care ın primacelula ın c ampul urmator este ultima celul˘a din list a.

Pentru implementarea listelor se pot folosi perechi de tablouri : primul tablou,numit continut , contine elementele de informat ¸ii, iar al doilea, numit urmator ,contine adresa elementului urm˘ ator din tabloul continut .

Procedura adauga efectueaz a numai 3 operat¸ii elementare. Este deci foarteecient a. Procedurile cauta si elimina sunt mai lungi pentru c˘ a trebuie s a parcurg˘aıntreaga list˘ a. Se poate estima c˘a num arul mediu de operat¸ii este jum atate dinlungimea listei. C˘autarea binar˘ a efectueaz a un num ar logaritmic iar c˘autarea cutabele hash (de dispersie) este si mai rapid˘ a.

Exemplu 1 . Consider am construirea unei liste de numere prime mai micidecat un num˘ar natural n dat. Pentru construirea acestei liste vom ıncepe, ın

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 162/518

150 CAPITOLUL 11. LISTE

prima faz a, prin ad augarea numerelor de la 2 la n ıncepˆand cu n si terminˆand cu2. Astfel numerele vor ın list˘ a ın ordine cresc˘atoare. Vom utiliza metoda clasic˘ a aciurului lui Eratostene: consider˘ am succesiv elementele listei ın ordine cresc˘ atoaresi suprim˘am tot i multiplii lor. Aceasta se realizeaz˘ a prin procedura urm˘ atoare:

static Lista Eratostene (int n) Lista a=null;int k;for(int i=n; i>=2; --i)

a=adauga(i,a);k=a.continut;for(Lista b=a; k*k<=n; b=b.urmator)

k=b.continut;for(int j=k; j<=n/k; ++j)

a=elimina(j*k,a);return a;

Exemplu 2 . Pentru ecare intrare i din intervalul [0 ..n −1] se construiesteo list a simplu ınl˘ant uit˘a format a din toate cheile care au h(x) = i. Elementelelistei sunt intr˘ari care permit accesul la tabloul de nume si numere de telefon.Procedurile de c˘autare si inserare a unui element x ıntr-un tablou devin proceduride cautare si ad˘ augare ıntr-o list˘ a. Tot astfel, dac˘ a funct ia h este r au aleas a,num arul de coliziuni devine important, multe liste devin de dimensiuni enorme sifar amit area risc˘a sa devin a la fel de costisitoare ca si c˘autarea ıntr-o list˘ a simpluınl ant uit a obisnuit˘a. Dac a h este bine aleas a, cautarea este rapid˘ a.

Lista al[] = new Lista[N1];

static void insereaza (String x, int val) int i = h(x);al[i] = adauga (x, al[i]);

static int cauta (String x) for (int a = al[h(x)]; a != null; a = a.urmator)

if (x.equals(nume[a.continut]))return telefon[a.continut];

return -1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 163/518

11.2. COZI 151

11.2 Cozi

Cozile sunt liste liniare particulare utilizate ın programare pentru gestionareaobiectelor care sunt ın asteptarea unei prelucr˘ ari ulerioare, de exemplu proceselede asteptare a resurselor unui sistem, nodurile unui graf, etc. Elementele suntad augate sistematic la coad˘ a si sunt eliminate din capul listei. In engleza se spunestrategie FIFO (First In First Out), ın opozit ¸ie cu strategia LIFO (Last In FirsOut) utilizat˘ a la stive.

Mai formalizat, consider˘ am o mult ime de elemente E , mult imea cozilor cuelemente din E este notat˘a Coada (E ), coada vid a (care nu cont ine nici un element)este C 0 , iar operat iile asupra cozilor sunt: esteV ida , adauga , valoare , elimina :

• esteV ida este o aplicat ie denit˘a pe Coada (E ) cu valori ın true, false ,

esteV ida (C ) aste egal a cu true daca si numai dac˘a coada C este vid a.

• adauga este o aplicat ie denit˘a pe E ×Coada (E ) cu valori ın Coada (E ),adauga (x, C ) este coada obt inut˘a plecand de la coada C si inser and elementulx la sfarsitul ei.

• valoare este o aplicat ie denit˘a pe Coada (E )−C 0 cu valori ın E care asociaz aunei cozi C , nevid a, elementul aat ın cap.

• elimina este o aplicat ie denit˘a pe Coada (E )−C 0 cu valoriın Coada (E ) careasociaz a unei cozi nevide C o coada obtinut˘a plecand de la C si elimin andprimul element.

Operat iile asupra cozilor satisfac urm˘ atoarele relat¸ii:

• Pentru C = C 0

– elimina (adauga (x, C )) = adauga (x, elimina (C ))– valoare (adauga (x, C )) = valoare (C )

• Pentru toate cozile C

– esteV ida (adauga (x, C )) = false

• Pentru coada C 0

– elimina (adauga (x, C 0)) = C 0– valoare (adauga (x, C 0)) = x– esteV ida (C 0) = true

O prim a idee de realizare sub form˘a de programe a operat ¸iilor asupra coziloreste de a ımprumuta tehnica folosit˘ a ın locurile unde client ¸ii stau la coad˘a pentrua servit i , de exemplu la gar a pentru a lua bilete, sau la cas˘ a ıntr-un magazin.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 164/518

152 CAPITOLUL 11. LISTE

Fiecare client care se prezint˘ a obtine un num˘ar si client ii sunt apoi chemat ¸i de catrefunct ionarul de la ghiseu ın ordinea cresc˘ atoare a numerelor de ordine primite lasosire. Pentru gestionarea acestui sistem, gestionarul trebuie s˘ a cunoasc a dou anumere: num˘arul obt inut de c˘atre ultimul client sosit si num˘ arul obt inut de c˘atreultimul client servit. Not˘ am aceste dou˘a numere inceput si sfarsit si gestion amsistemul ın modul urm˘ ator:

• coada de asteptare este vid˘ a dac a si numai dac˘a inceput = sfarsit ,

• atunci c and soseste un nou client, se incrementeaz˘ a sfarsit si se da acestnum ar clientului respectiv,

• atunci c and funct ionarul este liber el poate servi un alt client, dac˘ a coadanu este vid a, incrementeaz˘a inceput si cheam a posesorul acestui num˘ ar.

In cele ce urmeaz a sunt prezentate toate operat ¸iile ın Java utilizˆ and tehnicileurm atoare: se reatribuie num˘ arul 0 unui nou client atunci cˆ and se dep aseste unanumit prag pentru valoarea sfarsit . Se spune ca este un tablou (sau tampon)circular, sau coad˘a circular a.

class Coada final static int MaxC = 100;int inceput;int sfarsit;boolean plina, vida;int continut[];

Coada () inceput = 0; sfarsit = 0;plina= false; vida = true;info = new int[MaxC];

static Coada vida()return new Coada();

static void facVida (Coada c) c.inceput = 0; c.sfarsit = 0;c.plina = false; c.vida = true;

static boolean esteVida(Coada c) return c.vida;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 165/518

11.2. COZI 153

static boolean estePlina(Coada c) return c.plina;

static int valoare(Coada c) if (c.vida)

erreur ("Coada Vida.");return c.info[f.inceput];

private static int succesor(int i) return (i+1) % MaxC;

static void adaug(int x, Coada c) if (c.plina)

erreur ("Coada Plina.");c.info[c.sfarsit] = x;c.sfarsit = succesor(c.sfarsit);c.vida = false;c.plina = c.sfarsit == c.inceput;

static void elimina (Coada c) if (c.vida)

erreur ("Coada Vida.");c.inceput = succesor(c.inceput);c.vida = c.sfarsit == c.inceput;c.plina = false;

e1 e2 en

inceput sfarsit

...

Figura 11.3: Coad˘a de asteptare implementat˘ a ca list a

O alt a modalitate de gestionare a cozilor const˘ a ın utilizarea listelor ınl˘ ant uite cu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 166/518

154 CAPITOLUL 11. LISTE

gard˘ a ın care se cunosc adresele primului si ultimului element. Aceasta d˘ a operat iileurm atoare:

class Coada Lista inceput;Lista sfarsit;

Coada (Lista a, Lista b) inceput = a;sfarsit = b;

static Coada vida() Lista garda = new Lista();

return new Coada (garda, garda);

static void facVida (Coada c) Lista garda = new Lista();c.inceput = c.sfarsit = garda;

static boolean esteVida (Coada c) return c.inceput == c.sfarsit;

static int valoare (Coada c) Lista b = c.inceput.next;return b.info;

static void adauga (int x, Coada c) Lista a = new Lista (x, null);c.sfarsit.next = a;f.sfarsit = a;

static void elimina (Coada c) if (esteVida(c))

erreur ("Coada Vida.");c.inceput = c.inceput.next;

Cozile se pot implementa e cu ajutorul tablourilor e cu ajutorul listelor sim-

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 167/518

11.3. STIVE 155

plu ınl˘ant uite. Scrierea programelor const˘ a ın primul rˆand ın alegerea structurilorde date pentru reprezentarea cozilor. Ansamblul funct ¸iilor care opereaz˘a asupracozilor se pot plasa ıntr-un modul care manipuleaz˘a tablouri sau liste. Utilizareacozilor se face cu ajutorul funct¸iilor vida , adauga , valoare , elimina . Aceasta estedeci interfat a cozilor care are important ¸a ın programe complexe.

11.3 Stive

Notiunea de stiv˘a intervine ın mod curent ın programare, rolul s˘ au principalind la implementarea apelurilor de proceduri. O stiv˘ a se poate imagina ca o cutieın care sunt plasate obiecte si din care se scot ın ordinea invers˘ a fata de cum aufost introduse: obiectele sunt puse unul peste altul ın cutie si se poate avea acces

numai la obiectul situat ın vˆ arful stivei. In mod formalizat, se consider˘ a o multimeE , mult imea stivelor cu elemente din E este notat˘a Stiva (E ), stiva vid a (care nucontine nici un element) este S 0 , operat iile efectuate asupra stivelor sunt vida ,adauga , valoare , elimina , ca si la re. De aceast˘a dat a, relat iile satisf acute sunturm atoarele:

• elimina (adauga (x, S )) = S

• esteV ida (adauga (x, S )) = false

• valoare (adauga (x, S )) = x

• esteV ida (S 0) = true

Cu ajutorul acestor relat ¸ii se pot exprima toate operat ¸iile relative la stive.Realizarea operat ¸iilor asupra stivelor se poate face utilizˆ and un tablou care

contine elementele si un indice care indic˘ a pozit ia v arfului stivei.

class Stiva final static int maxP = 100;int inaltime;Element continut[];

Stiva() inaltime = 0;continut = new Element[maxP];

static Fir vid () return new Stiva();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 168/518

156 CAPITOLUL 11. LISTE

static void facVida (Stiva s) s.inaltime = 0;

static boolean esteVida (Stiva s) return s.inaltime == 0;

static boolean estePlina (Stiva s) return s.inaltime == maxP;

static void adauga (Element x, Stiva s) throws ExceptionStiva if (estePlina (s))

throw new ExceptionStiva("Stiva plina");s.continut[s.inaltime] = x;++ s.inaltime;

static Element valoare (Stiva s) throws ExceptionStiva if (esteVida (s))

throw new ExceptionStiva("Stiva vida");return s.continut[s.inaltime-1];

static void supprimer (Stiva s) throws ExceptionStiva

if (esteVida (s))throw new ExceptionStiva ("Stiva vida");s.inaltime;

unde

class ExceptionStiva extends Exception String text;

public ExceptionStiva (String x) text = x;

Stivele se pot implementa atˆ at cu ajutorul tablourilor (vectorilor) cˆ at si cuajutorul listelor simplu ınl˘ ant uite.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 169/518

11.4. EVALUAREA EXPRESIILOR ARITMETICE PREFIXATE 157

11.4 Evaluarea expresiilor aritmetice prexate

Vom ilustra utilizarea stivelor printr-un program de evaluare a expresiiloraritmetice scrise sub o form˘a particular a. In programare o expresie aritmetic˘ apoate cont ine numere, variabile si operat ¸ii aritmetice (ne vom limita numai la +si *). Vom considera ca intr˘ ari numai numere naturale.

Expresiile prexate cont ¸in simbolurile: numere naturale, +, *, ( si ). Dac˘ a e1si e2 sunt expresii prexate atunci (+ e1e2) si (∗e1e2) sunt expresii prexate.

Pentru reprezentarea unei expresii prexate ın Java, vom utiliza un tablou alecarui elemente sunt entit˘ at ile expresiei. Elementele tabloului sunt obiecte cu treicampuri: primul reprezint˘ a natura entit˘ atii (simbol sau num˘ar), al doilea reprezint˘ avaloarea entit˘ at ii dac a aceasta este num˘ ar, iar al treilea este este un simbol dac˘ aentitatea este simbol.

class Element boolean esteOperator;int valoare;char simbol;

Vom utiliza funct¸iile denite pentru stiv˘ a si procedurile denite ın cele ceurmeaz a.

static int calcul (char a, int x, int y) switch (a)

case ’+’: return x + y;case ’*’: return x * y;return 1;

Procedura de evaluare const˘ a ın stivuirea rezultatelor intermediare, stivacontin and operatori si numere, dar niciodat˘ a nu va cont ine consecutiv numere.Se examineaz a succesiv entit˘at ile expresiei dac˘a entitatea este un operator sau unnum ar si dac˘a varful stivei este un operator, atunci se plaseaz˘ a ın stiv˘a. Dac aeste un num˘ar si v arful stivei este de asemenea un num˘ ar, act ioneaz˘a operatorulcare precede v arful stivei asupra celor dou˘ a numere si se repet˘a operat ia asuprarezultatului g˘asit.

De exemplu, pentru expresia

(+ (* (+ 35 36) (+ 5 6)) (* (+ 7 8) (*9 9 )))

evaluarea decurge astfel:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 170/518

158 CAPITOLUL 11. LISTE

95 7 * *

35 + + + + 15 15+ + 71 71 71 * * * * *

* * * * * * 781 781 781 781 781 781+ + + + + + + + + + + + +

static void insereaza (Element x, Stiva s) throws ExceptionStiva Element y, op;while (!(Stiva.esteVida(s) || x.esteOperator

|| Stiva.valoare(s).esteOperator)) y = Stiva.valoare(s);Stiva.elimina(s);op = Stiva.valoare(s);

Stiva.elimina(s);x.valoare = calcul(op.valsimb, x.valoare, y.valoare);Stiva.adauga(x,s);

static int calcul (Element u[]) throws ExceptionStiva Stiva s = new Stiva();for (int i = 0; i < u.length ; ++i)

insereaza(u[i], s);return Stiva.valoare(s).valoare;

In acest caz, este util˘a prezentarea unui program principal care utilizeaz˘ aaceste funct ii.

public static void main (String args[]) Element exp[] = new Element [args.length];for (int i = 0; i < args.length; ++i)

String s = args[i];if (s.equals("+") || s.equals("*"))

exp[i] = new Element (true, 0, s.charAt(0));else

exp[i] = new Element (false, Integer.parseInt(s), ’ ’);try System.out.println(calcul(exp)); catch (ExceptionStiva x)

System.err.println("Stiva " + x.nom);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 171/518

11.5. OPERATII ASUPRA LISTELOR 159

11.5 Operat ¸ii asupra listelor

In aceast a sectiune sunt prezentat ¸i cativa algoritmi de manipulare a listelor.Acestia sunt utilizat ¸i ın limbajele de programare care au listele ca structuri debaza. Funct ia Tail este o primitiv˘a clasica; ea suprim a primul element al listei.

e1 e2 e3 e4

a Tail(a)

e1 e2 e3 e4

Figura 11.4: Suprimarea primului element din list˘ a

class Lista Object info;Lista next;Lista(Object x, Lista a)

info = x;next = a;

static Lista cons (Object x, Lista a) return new Lista (x, a);

static Object head (Lista a) if (a == null)

erreur ("Head d’une liste vide.");return a.info;

static Lista tail (Lista a) if (a == null)

erreur ("Tail d’une liste vide.");return a.next;

Procedurile asupra listelor construiesc o list˘ a plecand de la alte dou˘a liste,pun o list a la cap atul celeilalte liste. In prima procedur˘ a append , cele doua listenu sunt modicate; ın a doua procedur˘ a, concat , prima list a este transformat˘ apentru a ret¸ine rezultatul. Totusi, se poate remarca faptul c˘ a, dac a append copiazaprimul s au argument, partajeaz˘ a nalul listei rezultat cu al doilea argument.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 172/518

160 CAPITOLUL 11. LISTE

a b

a1 a2 a3 b1 b2 b3 b4

append(a,b

a1 a2 a3

Figura 11.5: Concatenarea a dou˘ a liste prin append

static Lista append (Lista a, Lista b)

if (a == null)return b;

elsereturn adauga(a.info, append (a.next, b)) ;

a b

a1 a2 a3 b1 b2 b3 b4

concat(a,b

Figura 11.6: Concatenarea a dou˘ a liste prin concat

static Lista concat(Lista a, Lista b)

if (a == null)return b;

else

Lista c = a;while (c.next != null)

c = c.next;c.next = b;return a;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 173/518

11.5. OPERATII ASUPRA LISTELOR 161

Aceast a ultim a procedur a se poate scrie recursiv:

static Lista concat (Lista a, Lista b) if (a == null)

return b;else

a.next = concat (a.next, c);return a;

Procedura de calcul de oglindire a unei liste a const a ın construirea uneiliste ın care elementele listei a sunt ın ordine invers˘ a. Realizarea acestei procedurieste un exercit iu clasic de programare asupra listelor. D˘ am aici dou a solut i, unaiterativ˘a, cealalt a recursiv a, complexitatea este O(n2) deci patratic˘a, dar clasic a.Noua metod˘a nReverse modic a argumentul s˘au, ın timp ce Reverse nu-l modic aci construieste o alt˘ a list a pentru rezultat.

static Lista nReverse (Lista a) Lista b = null;while (a != null)

Lista c = a.next;a.next = b; b = a; a = c;

return b;

a

b

e1 e2 e3 e4 e5

c

nill

Figura 11.7: Transformarea listei prin inversarea leg˘ aturilor

static Lista Reverse (Lista a) if (a == null)

return a;else

return append(Reverse (a.next), adauga(a.info, null));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 174/518

162 CAPITOLUL 11. LISTE

Se poate scrie o versiune iterativ˘ a a versiunii recursive, grat ¸ie unei funct ii auxiliarecare acumuleaz˘a rezultatul ıntr-unul din argumentele sale:

static Lista nReverse (Lista a) return nReverse1(null, a);

static Lista nReverse1 (Lista b, Lista a) if (a == null)

return b;else

return nReverse1(adauga(a.info, b), a.next);

Un alt exercit iu formator const˘ a ın a administra liste ın care elementele suntaranjate ın ordine cresc˘ atoare. Procedura de ad˘ augare devine ceva mai complex˘ apentru c˘a trebuie g asit a pozit ia celulei care trebuie ad˘ augat a dup a parcurgereaunei p art i a listei.

Nu trat˘am acest exercit¸iu dec at ın cazul listelor circulare cu gard˘ a. Pentru oastfel de list a, valoarea c ampului info din prima celul˘a nu are nici o semnicat ie(este celula de gard˘ a ). Campul next din ultima celul˘a cont ine adresa primei celule.

a

a1 a2 a3 a4 a5 a6

garda

Figura 11.8: List˘a circular a cu gard a

static Lista insereaza (int v, Lista a) Lista b = a;while (b.next != a && v > head(b.next))

b = b.next;b.next = adauga(v, b.next);a.info = head(a) + 1;return a;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 175/518

Capitolul 12

Algoritmi divide et impera

12.1 Tehnica divide et impera

Divide et impera 1 este o tehnic a de elaborare a algoritmilor care const˘ a ın:

• Descompunerea repetat˘ a a problemei (subproblemei) ce trebuie rezolvat˘ a ınsubprobleme mai mici.

• Rezolvarea ın acelasi mod (recursiv) a tuturor subproblemelor.

• Compunerea subsolut ¸iilor pentru a obt ¸ine solut ia problemei (subproblemei)initiale.

Descompunerea problemei (subproblemelor) se face pˆ an a n momentul ın carese obtin subprobleme de dimensiuni atˆ at de mici ıncˆat au solut ie cunoscut˘a saupot rezolvate prin tehnici elementare.

Metoda poate descris˘a astfel:procedure divideEtImpera( P,n,S )

if (n ≤n0)then rezolv˘ a subproblema P prin tehnici elementareelse

ımparte P ın P 1 ,...,P k de dimensiuni n1 ,...,n kdivideEtImpera( P 1 , n 1 , S 1)...

divideEtImpera( P a , n k , S k )combin˘ a S 1 ,...,S k pentru a obt¸ine S Exemplele tipice de aplicare a acestei metode sunt algoritmii de parcurgere

a arborilor binari si algoritmul de c˘ autare binar˘ a.1 divide-and-conquer, ın englez˘ a

163

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 176/518

164 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

12.2 Ordinul de complexitate

Vom presupune c˘a dimensiunea n i a subproblemei i satisface relat¸ia n i ≤ nb ,

unde b > 1. Astfel, pasul de divizare reduce o subproblem˘ a la altele de dimensiunimai mici, ceea ce asigur a terminarea subprogramului recursiv.

Presupunem c˘a divizarea problemei ın subprobleme si compunerea solutiilorsubproblemelor necesit˘ a un timp de ordinul O(n k ). Atunci, complexitatea timpT (n) a algoritmului divideEtImpera este dat˘ a de relat ia de recurent¸ a:

T (n) =O(1) , dac a n ≤n0

a ·T ( nb ) + O(n k ) , dac a n > n 0

(12.2.1)

Teorema 3 Dac˘ a n > n 0 atunci:

T (n) =O(n log b a ) , dac˘ a a > b k

O(nk logb n) , dac˘ a a = bk

O(nk ) , dac˘ a a < b k(12.2.2)

Demonstrat ie: Putem presupune, f˘ ar a a restr ange generalitatea, c˘ a n = bm ·n0 . Deasemenea, presupunem c˘ a T (n) = c ·nk

0 daca n ≤ n0 si T (n) = a ·T ( nb ) + c ·nk

daca n > n 0 . Pentru n > n 0 avem:

T (n) = aT nb

+ cnk

= aT bm −1n0 + cnk

= a aT bm −2n0 + cnb

k+ cnk

= a2T bm −2n0 + c anb

k+ nk

= ...

= am T (n0) + c am −1 nbm −1

k+ ... + a

nb

k+ n k

= am cnk0 + c am −1bk n k

0 + ... + a bm −1 knk

0 + ( bm )k n k0

= cnk0 am 1 +

bk

a+ ... +

bk

a

m

= camm

i=0

bk

a

i

unde am notat cnk0 prin c. Distingem cazurile:

1. a > b k . Seria mi=0

bk

a

ieste convergent˘a si deci sirul sumelor part ¸iale este

convergent. De aici rezult˘ a ca T (n) = O(am ) = O(a log b n ) = O(n log b a )

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 177/518

12.3. EXEMPLE 165

2. a = bk . Rezult a ca am = bkm = cnk si de aici T (n) = O(nk m) = O(nk logb n).

3. a < b k . Avem T (n) = O(am ( bka )m ) = O(bkm ) = O(n k ).

12.3 Exemple

Dintre problemele clasice care se pot rezolva prin metoda divide et imperament ion am:

• cautare binar˘ a

• sortare rapid˘ a (quickSort)

• problema turnurilor din Hanoi

• sortare prin interclasare - Merge sort

• dreptunghi de arie maxim˘ a ın placa cu g˘auri, etc

12.3.1 Sortare prin partitionare - quicksort

Se bazeaz a pe metoda interschimb˘ arii, ıns˘a din nou, interschimbarea se facepe distant¸e mai mari. Astfel, avˆand tabloul a[], se aplica urm atorul algoritm:

1. se alege la ıntˆamplare un element x al tabloului

2. se scaneaza tabloul a[] la stanga lui x pan a cand se gaseste un element a i > x3. se scaneaza tabloul la dreapta lui x pan a cand se gaseste un element a j < x

4. se interschimb˘a a i cu a j

5. se repeta pasii 2, 3, 4 p an a cand scan arile se vor ıntˆ alni pe undeva la mijlocultabloului. In acel moment, tabloul a[] va partitionat ın 2 astfel, la stˆ angalui x se vor gasi elemente mai mici ca si x, la dreapta, elemente mai mari casi x. Dup a aceasta, se aplic˘a acelasi proces subsirurilor de la stˆ anga si de ladreapta lui x, pan a cand aceste subsiruri sunt sucient de mici (se reduc laun singur element).

class QuickSort

static int x[]=3,5,2,6,4,1,8,2,4,3,5,3;

public static void main(String[]args)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 178/518

166 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

quickSort(0,x.length-1,x);for(int i=0;i<x.length;i++) System.out.print(x[i]+" ");

//main

static void quickSort(int st,int dr,int a[])

int i=st, j=dr, x, temp;x=a[(st+dr)/2];do

while (a[i]<x) i++;while (a[j]>x) --j;if(i<=j)

temp=a[i]; a[i]=a[j]; a[j]=temp;j--;i++;

while(i<=j);if(st<j) quickSort(st,j,a);if(i<dr) quickSort(i,dr,a);

// quickSort(...)//class

Aceasta metoda are complexitatea n log n, ın practic˘ a (ın medie)!

12.3.2 Sortare prin interclasare - MergeSort

Ideea este de a utiliza interclasarea ın etapa de asamblare a solut ¸iilor.In urma rezolv arii recursive a subproblemelor rezult˘ a vectori ordonat i si prin

interclasarea lor obt ¸inem vectorul init ¸ial sortat. Vectorii de lungime 1 sunt evidentconsiderat i sortat¸i.

Pasul de divizare se face ın timpul O(1). Faza de asamblare se face ın timpulO(m1 + m2) unde n1 si n2 sunt lungimile celor doi vectori care se interclaseaz˘ a.

Din Teorema 3 pentru a = 2, b = 2 si k = 1 rezult˘a ca ordinul de complexitateal algoritmului MergeSort este O(n log2 n) unde n este dimensiunea vectoruluiinit ial supus sort˘arii.

class MergeSort

static int x[]=3,5,2,6,4,1,8,2,4,3,5,3;

public static void main(String[]args)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 179/518

12.3. EXEMPLE 167

mergeSort(0,x.length-1,x);for(int i=0;i<x.length;i++) System.out.print(x[i]+" ");

//main

public static int[] mergeSort(int st,int dr,int a[])

int m,aux;if((dr-st)<=1)

if(a[st]>a[dr]) aux=a[st];a[st]=a[dr];a[dr]=aux;else

m=(st+dr)/2; mergeSort(st,m,a); mergeSort(m+1,dr,a);interclasare(st,m,dr,a);

return a;

// mergeSort(...)

public static int[] interclasare(int st,int m,int dr,int a[])

// interclasare pozitii st,...,m cu m+1,...,drint i,j,k;

int b[]=new int[dr-st+1];i=st;j=m+1;k=0;while((i<=m)&&(j<=dr))

if(a[i]<=a[j]) b[k]=a[i]; i++; else b[k]=a[j]; j++; k++;

if(i<=m) for(j=i;j<=m; j++) b[k]=a[j]; k++; else for(i=j;i<=dr;i++) b[k]=a[i]; k++;

k=0;for(i=st;i<=dr;i++) a[i]=b[k]; k++; return a;

//interclasare(...)//class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 180/518

168 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

12.3.3 Placa cu g˘ auri

Se consider a o placa dreptunghiular˘ a ın care exist˘a n gauri punctiforme decoordonate cunoscute. S˘ a se determine pe aceast˘ a plac a un dreptunghi de ariemaxim a, cu laturile paralele cu laturile pl˘ acii, care s a nu cont in a gauri ın interiorci numai eventual pe laturi.

Vom considera placa ıntr-un sistem cartezian. Consider˘ am o subproblem˘a deforma urm atoare: dreptunghiul determinat de diagonala ( x1, y1) (din st anga-jos)si ( x2, y2) din dreapta-sus este analizat pentru a vedea dac˘ aın interior cont ¸ine vreogaur a; dac a nu cont ine, este o solut ie posibil a (se va alege cea de arie maxim˘a); dac aexist a o gaur a ın interiorul s˘ au, atunci se consider˘a patru subprobleme generatede cele 4 dreptunghiuri obt ¸inute prin descompunerea pe orizontal˘ a si pe vertical˘ade cele doua drepte paralele cu axele care trec prin punctul care reprezint˘ a gaura.

1

23

4

Figura 12.1: Dreptunghi de arie maxim˘ a ın placa cu g˘auri

import java.io.*;class drArieMaxima

static int x1,y1,x2,y2,n,x1s,y1s,x2s,y2s,amax;static int[] x;static int[] y;

public static void main (String[] args) throws IOException

int i;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("dreptunghi.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("dreptunghi.out")));

st.nextToken(); x1=(int) st.nval;st.nextToken(); y1=(int) st.nval;st.nextToken(); x2=(int) st.nval;st.nextToken(); y2=(int) st.nval;st.nextToken(); n=(int) st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 181/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 182/518

170 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

• la un moment dat se va muta un singur disc (cel care se a˘ a deasupracelorlalte discuri pe o tij˘a);

•un disc poate asezat doar peste un disc de diametru mai mare decˆ atal sa sau pe o tij a goala.

Imp art im problema astfel:

• se mut a primele n −1 discuri de pe tija surs˘ a A pe tija intermediar˘ a B

• se mut a ultimul disc de pe tija surs˘ a A pe tija destinat ie C

• se mut a cele n −1 discuri de pe tija intermediar˘ a B pe tija destinat ie C

A B C A B C

A B CA B C

a) b)

c)d)

pasul 1

pasul 2

pasul 3

import java.io.*;class Hanoi

static int nrMutare=0;public static void main(String[] args) throws IOException

int nrDiscuri;

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Introduceti numarul discurilor: ");nrDiscuri=Integer.parseInt(br.readLine());

solutiaHanoi(nrDiscuri, ’A’, ’B’, ’C’);// main()

static void solutiaHanoi(int nrDiscuri, char tijaSursa,char tijaIntermediara, char tijaDestinatie)

if(nrDiscuri==1)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 183/518

12.3. EXEMPLE 171

System.out.println(++nrMutare + " Disc 1 " +tijaSursa + " ==> "+ tijaDestinatie);

else

solutiaHanoi(nrDiscuri-1,tijaSursa,tijaDestinatie,tijaIntermediara);

System.out.println(++nrMutare + " Disk " + nrDiscuri +" " + tijaSursa + " --> "+ tijaDestinatie);

solutiaHanoi(nrDiscuri-1,tijaIntermediara,tijaSursa,tijaDestinatie);

// solutiaHanoi()// class

Introduceti numarul discurilor: 41 Disc 1 A ==> B2 Disk 2 A --> C3 Disc 1 B ==> C4 Disk 3 A --> B5 Disc 1 C ==> A6 Disk 2 C --> B7 Disc 1 A ==> B8 Disk 4 A --> C9 Disc 1 B ==> C

10 Disk 2 B --> A11 Disc 1 C ==> A12 Disk 3 B --> C

13 Disc 1 A ==> B14 Disk 2 A --> C15 Disc 1 B ==> C

import java.io.*;class HanoiDisc

static int nrMutare=0;static final int MAX_NR_DISCURI=9;static int[] a=new int[MAX_NR_DISCURI],

b=new int[MAX_NR_DISCURI],c=new int[MAX_NR_DISCURI];

static int na,nb,nc; // na = nr. discuri pe tija A; etc. ...static int discMutat;

public static void main(String[] args) throws IOException

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 184/518

172 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

int nrDiscuri=0;while((nrDiscuri<1)||(nrDiscuri>MAX_NR_DISCURI))

System.out.print("Numar discuri"+"[1<=...<="+MAX_NR_DISCURI+"]: ");nrDiscuri = Integer.parseInt(br.readLine());

na=nrDiscuri;nb=0;nc=0;for(int k=0;k<na;k++) a[k]=na-k;afisareDiscuri(); System.out.println();solutiaHanoi(nrDiscuri, ’A’, ’B’, ’C’);

// main()

static void solutiaHanoi(int nrDiscuri, char tijaSursa,char tijaIntermediara, char tijaDestinatie)

if (nrDiscuri==1)

mutaDiscul(tijaSursa, tijaDestinatie);System.out.print(++nrMutare + " Disc " + "1" + " " +

tijaSursa + " ==> "+ tijaDestinatie + " ");afisareDiscuri(); System.out.println();

else

solutiaHanoi(nrDiscuri-1,tijaSursa,tijaDestinatie,tijaIntermediara); mutaDiscul(tijaSursa, tijaDestinatie);System.out.print(++nrMutare + " Disc " + nrDiscuri +

" " + tijaSursa + " --> "+ tijaDestinatie + " ");afisareDiscuri();System.out.println();solutiaHanoi(nrDiscuri-1, tijaIntermediara, tijaSursa, tijaDestinatie);

// solutiaHanoi()

static void mutaDiscul(char tijaSursa, char tijaDestinatie)

switch (tijaSursa)

case ’A’: discMutat=a[(na--)-1]; break;case ’B’: discMutat=b[(nb--)-1]; break;case ’C’: discMutat=c[(nc--)-1];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 185/518

12.3. EXEMPLE 173

switch (tijaDestinatie)

case ’A’: a[(++na)-1]=discMutat; break;case ’B’: b[(++nb)-1]=discMutat; break;case ’C’: c[(++nc)-1]=discMutat;

// mutaDiscul()

static void afisareDiscuri()

System.out.print(" A(");for(int i=0;i<na;i++) System.out.print(a[i]);System.out.print(") ");System.out.print(" B(");for(int i=0;i<nb;i++) System.out.print(b[i]);System.out.print(") ");System.out.print(" C(");for(int i=0;i<nc;i++) System.out.print(c[i]);System.out.print(") ");

// afisareDiscuri()// class

Numar discuri[1<=...<=9]: 4A(4321) B() C()

1 Disc 1 A ==> B A(432) B(1) C()

2 Disc 2 A --> C A(43) B(1) C(2)3 Disc 1 B ==> C A(43) B() C(21)4 Disc 3 A --> B A(4) B(3) C(21)5 Disc 1 C ==> A A(41) B(3) C(2)6 Disc 2 C --> B A(41) B(32) C()7 Disc 1 A ==> B A(4) B(321) C()8 Disc 4 A --> C A() B(321) C(4)9 Disc 1 B ==> C A() B(32) C(41)

10 Disc 2 B --> A A(2) B(3) C(41)11 Disc 1 C ==> A A(21) B(3) C(4)12 Disc 3 B --> C A(21) B() C(43)13 Disc 1 A ==> B A(2) B(1) C(43)14 Disc 2 A --> C A() B(1) C(432)15 Disc 1 B ==> C A() B() C(4321)

12.3.5 Injumat˘ atire repetata

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 186/518

174 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

Se consider a un sir de numere naturale x1 , x2 ,...,x n si o succesiune de deciziid

1, d

2,... unde d

i∈

S, D

au urm atoarea semnicat ¸ie: la pasul i, sirul r amas ın

acel moment se ımparte ın dou˘ a subsiruri cu num˘ ar egal elemente (dac˘a num arul deelemente este impar, elementul situat la mijloc se elimin˘ a) si se elimin a jum atateadin partea stˆ anga a sirului dac˘a di = S (dac a di = D se elimina jum atatea dinpartea drept˘ a).

Deciziile se aplica ın ordine, una dup˘ a alta, p an a cand r amane un singurelement. Se cere acest element.

class Injumatatire1

static int n=10;static char[] d=’X’,’S’,’D’,’S’,’S’; // nu folosesc d_0 ... !

public static void main(String[]args)

int st=1,dr=n,m,i=1;boolean impar;

while(st<dr)

System.out.println(st+" ... "+dr+" elimin "+d[i]); m=(st+dr)/2;if((dr-st+1)%2==1) impar=true; else impar=false;

if(d[i]==’S’) // elimin jumatatea stanga

st=m+1;else // elimin jumatatea dreapta

dr=m;if(impar) dr--;

i++;System.out.println(st+" ... "+dr+" a ramas! \n");

//main

//class

1 ... 10 elimin S6 ... 10 a ramas!

6 ... 10 elimin D

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 187/518

12.3. EXEMPLE 175

6 ... 7 a ramas!

6 ... 7 elimin S7 ... 7 a ramas!

Toate elementele care pot r˘ amane:

class Injumatatire2

static int n=10;static char[] d=new char[10];

public static void main(String[]args)

divide(1,n,1);//main

static void divide(int st0,int dr0, int i)

int st,dr,m;boolean impar;

if(st0==dr0)

for(m=1;m<=i;m++) System.out.print(d[m]);System.out.println(" --> "+st0);

return;

m=(st0+dr0)/2;if((dr0-st0+1)%2==1) impar=true; else impar=false;

// elimin jumatatea stangast=m+1;d[i]=’S’;if(st<=dr0) divide(st,dr0,i+1);

// elimin jumatatea dreaptadr=m;if(impar) dr--;d[i]=’D’;if(st0<=dr) divide(st0,dr,i+1);

// divide(...)//class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 188/518

176 CAPITOLUL 12. ALGORITMI DIVIDE ET IMPERA

SSS --> 10SSD --> 9SDS --> 7SDD --> 6DSS --> 5DSD --> 4DDS --> 2DDD --> 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 189/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 190/518

178 CAPITOLUL 13. ALGORITMI BFS-LEE

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;st.nextToken(); nods=(int)st.nval;st.nextToken(); nodd=(int)st.nval;

a=new int[n+1][n+1];color=new int[n+1];p=new int[n+1];d=new int[n+1];q=new int[m+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=1;a[j][i]=1;

bfs(nods,nodd);

System.out.println("Distanta("+nods+","+nodd+") = "+d[nodd]);System.out.print("drum : "); drum(nodd); System.out.println();out.close();

//main

static void videzcoada()ic=0;sc=0; // coada : scot <-- icoada...scoada <-- introduc

static boolean coadaEsteVida()

return (sc==ic);

static void incoada(int v)

q[sc++]=v;color[v]=GRAY;

static int dincoada()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 191/518

13.1. PREZENTARE GENERAL ˘ A 179

int v=q[ic++];color[v]=BLACK;return v;

static void bfs(int start, int fin)

int u, v;for(u=1; u<=n; u++)

color[u]=WHITE;d[u]=oo;

color[start]=GRAY;d[start]=0;

videzcoada();incoada(start);while(!coadaEsteVida())

u=dincoada();

// Cauta nodurile albe v adiacente cu nodul u si pun v in coadafor(v=1; v<=n; v++)

if(a[u][v]==1) // v in Ad[u]if(color[v]==WHITE) // neparcurs deja

color[v]=GRAY;d[v]=d[u]+1;p[v]=u;if(color[fin]!=WHITE) break; // optimizare; ies din forincoada(v);

//for

color[u]=BLACK;if(color[fin]!=WHITE) break; // am ajuns la nod_destinatie

//while//bfs

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 192/518

180 CAPITOLUL 13. ALGORITMI BFS-LEE

static void drum(int u) // nod_sursa ---> nod_destinatie

if(p[u]!=0) drum(p[u]);System.out.print(u+" ");

//class

/*9 12 2 8 Distanta(2,8) = 42 5 drum : 2 3 4 7 81 22 33 13 44 55 66 47 88 99 77 4*/

13.2 Probleme rezolvate

13.2.1 Romeo si Julieta - OJI2004 clasa a X-a

In ultima ecranizare a celebrei piese shakespeariene Romeo si Julieta tr˘ aiescıntr-un oras modern, comunic˘ a prin e-mail si chiar ınvat ¸a sa programeze. Intr-o secvent a tulbur˘atoare sunt prezentate fr˘ amat arile interioare ale celor doi eroiıncercˆand f ar a succes sa scrie un program care s˘a determine un punct optim deıntˆalnire.

Ei au analizat harta orasului si au reprezentat-o sub forma unei matrice cun linii si m coloane, ın matrice ind marcate cu spat ¸iu zonele prin care se poatetrece (str˘azi lipsite de pericole) si cu X zonele prin care nu se poate trece. Deasemenea, ın matrice au marcat cu R locul ın care se a˘a locuint a lui Romeo, iarcu J locul ın care se a˘a locuint a Julietei.

Ei se pot deplasa numai prin zonele care sunt marcate cu spat ¸iu, din pozit iacurent a ın oricare dintre cele 8 pozit ¸ii ınvecinate (pe orizontal˘ a, vertical˘a sau di-agonale).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 193/518

13.2. PROBLEME REZOLVATE 181

Cum lui Romeo nu ıi place s˘ a astepte si nici s˘ a se lase asteptat n-ar tocmaibine, ei au hot ar at c a trebuie s a aleag a un punct de ıntˆ alnire ın care atˆ at Romeo,cat si Julieta s˘ a poat a ajunge ın acelasi timp, plecˆ and de acas a. Fiindc a la ıntˆalniriamandoi vin ıntr-un suet, ei estimeaz˘ a timpul necesar pentru a ajunge la ıntˆ alnireprin num˘arul de elemente din matrice care constituie drumul cel mai scurt de acas˘ apan a la punctul de ıntˆ alnire. Si cum probabil exist˘ a mai multe puncte de ıntˆ alnireposibile, ei vor sa ıl aleag˘a pe cel ın care timpul necesar pentru a a junge la punctulde ınt alnire este minim.

Cerint ¸aScriet i un program care s˘a determine o pozit¸ie pe hart˘a la care Romeo si

Julieta pot s˘a ajung a ın acelasi timp. Dac˘ a exist a mai multe solut¸ii, programultrebuie s a determine o solut¸ie pentru care timpul este minim.

Datele de intrareFisierul de intrare rj.in contine:

−pe prima linie numerele naturale NM , care reprezint˘a num arul de linii sirespectiv de coloane ale matricei, separate prin spat ¸iu;

−pe ecare dintre urm˘ atoarele N linii se aa M caractere (care pot doarR, J , X sau spat iu) reprezentˆ and matricea.

Datele de iesireFisierul de iesire rj.out va cont ine o singur a linie pe care sunt scrise trei

numere naturale separate prin cˆ ate un spat¸iu tmin x y , avand semnicat¸ia:

−x y reprezint˘a punctul deıntˆ alnire ( x - numarul liniei, y - numarul coloanei);

−tmin este timpul minim ın care Romeo (respectiv Julieta) ajunge la punctulde ınt alnire.

Restrict ii si precizari

• 1 < N, M < 101

• Liniile si coloanele matricei sunt numerotate ıncepˆ and cu 1.

• Pentru datele de test exist˘ a ıntotdeauna solut ¸ie.

Exemplerj.in

5 8XXR XXX

X X XJ X X X

XXXXX XXXX

rj.out

4 4 4

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 194/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 195/518

13.2. PROBLEME REZOLVATE 183

Rezolvare detaliat˘ a

Codul sursa *

import java.io.*;class RJ

static final int zid=10000;static int m,n;static int[][] xr,xj;static int[] qi=new int[5000]; // coada sau coada circulara mai bine !static int[] qj=new int[5000]; // coada

static int ic, sc; // ic=inceput coada

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i,j,ir=0,jr=0,ij=0,jj=0, imin, jmin, tmin;String s;

BufferedReader br=new BufferedReader(new FileReader("rj.in"));StreamTokenizer st=new StreamTokenizer(br);PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("rj.out")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;

xr=new int[m+2][n+2]; // matrice bordata cu zid !xj=new int[m+2][n+2]; // matrice bordata cu zid !

br.readLine(); // citeste CRLF !!!for(i=1;i<=m;i++)

s=br.readLine();for(j=1;j<=n;j++)

if(s.charAt(j-1)==’X’) xr[i][j]=xj[i][j]=zid; // zid!else if(s.charAt(j-1)==’R’) ir=i; jr=j; xr[i][j]=1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 196/518

184 CAPITOLUL 13. ALGORITMI BFS-LEE

else if(s.charAt(j-1)==’J’) ij=i; jj=j; xj[i][j]=1;

for(i=0;i<=m+1;i++) xr[i][0]=xr[i][n+1]=xj[i][0]=xj[i][n+1]=zid; // E si Vfor(j=0;j<=n+1;j++) xr[0][j]=xr[m+1][j]=xj[0][j]=xj[m+1][j]=zid; // N si S

ic=sc=0; // coada vida;qi[sc]=ir; qj[sc]=jr; sc++; // (ir,jr) --> coadawhile(ic!=sc)

i=qi[ic]; j=qj[ic]; ic++; // scot din coadafill(xr,i,j);

ic=sc=0; // coada vida;qi[sc]=ij; qj[sc]=jj; sc++; // (ij,jj) --> coadawhile(ic!=sc)

i=qi[ic]; j=qj[ic]; ic++; // scot din coadafill(xj,i,j);

tmin=10000;imin=jmin=0;for(i=1;i<=m;i++)

for(j=1;j<=n;j++)

if(xr[i][j]==xj[i][j])if(xj[i][j]!=0) // pot exista pozitii ramase izolate !if(xr[i][j]<tmin) tmin=xr[i][j]; imin=i; jmin=j;

out.println(tmin+" "+imin+" "+jmin);out.close();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()

static void fill(int[][] x,int i, int j)

int t=x[i][j]; // timpif(x[i-1][j]==0) x[i-1][j]=t+1; qi[sc]=i-1; qj[sc]=j; sc++; // Nif(x[i-1][j+1]==0) x[i-1][j+1]=t+1; qi[sc]=i-1; qj[sc]=j+1; sc++; // NEif(x[i-1][j-1]==0) x[i-1][j-1]=t+1; qi[sc]=i-1; qj[sc]=j-1; sc++; // NV

if(x[i+1][j]==0) x[i+1][j]=t+1; qi[sc]=i+1; qj[sc]=j; sc++; // S

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 197/518

13.2. PROBLEME REZOLVATE 185

if(x[i+1][j+1]==0) x[i+1][j+1]=t+1; qi[sc]=i+1; qj[sc]=j+1; sc++; // SEif(x[i+1][j-1]==0) x[i+1][j-1]=t+1; qi[sc]=i+1; qj[sc]=j-1; sc++; // SV

if(x[i][j+1]==0) x[i][j+1]=t+1; qi[sc]=i; qj[sc]=j+1; sc++; // Eif(x[i][j-1]==0) x[i][j-1]=t+1; qi[sc]=i; qj[sc]=j-1; sc++; // V

// fil(...)// class

13.2.2 Sudest - OJI2006 clasa a X-a

Fermierul Ion det¸ine un teren de form˘a patrat˘a, ımp˘artit ın N ×N patratede latur˘a unitate, pe care cultiv˘ a carto. Pentru recoltarea cartolor fermierulfoloseste un robot special proiectat ın acest scop. Robotul porneste din p˘ atratuldin st anga sus, de coordonate (1 , 1) si trebuie s˘a ajung a ın p˘atratul din dreapta jos, de coordonate ( N, N ).

Traseul robotului este programat prin memorarea unor comenzi pe o cartel˘ amagnetic a. Fiecare comand˘a specica direct ia de deplasare (sud sau est) si num˘ arulde patrate pe care le parcurge ın direct ¸ia respectiv˘a. Robotul strˆange recolta doardin p atratele ın care se opreste ıntre dou˘ a comenzi.

Din p acate, cartela pe care se a˘ a programul s-a deteriorat si unitatea decitire a robotului nu mai poate distinge direct ¸ia de deplasare, ci numai num˘ arulde pasi pe care trebuie s˘ a-i faca robotul la ecare comand˘ a. Fermierul Ion trebuiesa introduc˘a manual, pentru ecare comand˘ a, direct ia de deplasare.

Cerint ¸aScriet i un program care s˘ a determine cantitatea maxim˘ a de carto pe care

o poate culege robotul, ın ipoteza ın care Ion specic˘ a manual, pentru ecarecomand a, direct ia urmat˘a de robot. Se va determina si traseul pe care se obt ¸inerecolta maxim˘a.

Datele de intrareFisierul de intrare sudest.in are urm atoarea structur˘ a:

• Pe linia 1 se aa num arul natural N , reprezentˆand dimensiunea parcelei deteren.

• Pe urm atoarele N linii se aa cate N numere naturale, separate prin spat ¸ii,reprezentˆand cantitatea de carto din ecare p˘ atrat unitate.

•Pe linia N +2 se a a un num ar natural K reprezentˆand num arul de comenziaate pe cartela magnetic˘ a.

• Pe linia N + 3 se a a K numerele naturale C 1 , ...,C K , separate prin spat ¸ii,reprezentˆand num arul de pasi pe care trebuie s˘ a-i efectueze robotul la ecarecomand a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 198/518

186 CAPITOLUL 13. ALGORITMI BFS-LEE

Datele de iesire

Fisierul de iesire sudest.out va cont ine pe prima linie cantitatea maxim˘ ade carto recoltat˘ a de robot. Pe urm˘atoarele K + 1 linii vor scrise, ın ordine,coordonatele p˘atratelor unitate ce constituie traseul pentru care se obt ¸ine canti-tate maxim˘a de carto, c ate un p atrat unitate pe o linie. Coordonatele scrise peaceeasi linie vor separate printr-un spat ¸iu. Primul p˘atrat de pe traseu va aveacoordonatele 11, iar ultimul va avea coordonatele NN . Daca sunt mai multe traseepe care se obt ine o cantitate maxim˘ a de carto recoltat˘ a se va asa unul dintreacestea.

Restrict ii si precizari

• 5 ≤N ≤100

• 2 ≤K ≤2∗N −2

• 1 ≤C 1 ,...,C K ≤10

• Cantitatea de carto dintr-un p˘ atrat de teren este num˘ ar natural ıntre 0 si100.

• Pentru ecare set de date de intrare se garanteaz˘ a ca exist a cel put in untraseu.

• Se consider a ca robotul strˆange recolta si din p˘atratul de plecare (1 , 1) si dincel de sosire (N, N ).

• Pentru determinarea corect˘ a a cantit˘at ii maxime recoltate se acord˘ a 50%din punctajul alocat testului respectiv; pentru cantitate maxim˘ a recoltat˘a sitraseu corect se acord˘ a 100%.

Exemplusudest.in sudest.out Explicat ¸ii6 29 Un alt traseu posibil este:1 2 1 0 4 1 1 1 1 11 3 3 5 1 1 3 1 1 32 2 1 2 1 10 5 1 1 54 5 3 9 2 6 6 1 2 5

1 1 3 2 0 1 6 5 6 510 2 4 6 5 10 6 6 6 65 dar costul s au este 1 + 1 + 4 + 1 + 5 + 10 = 222 2 1 4 1

Timp maxim de execut ¸ie/test: 1 secund a

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 199/518

13.2. PROBLEME REZOLVATE 187

Indicat ¸ii de rezolvare *

solut ¸ia comisiei Reprezentarea informat ¸iilor

• N - numarul de linii

• K - numarul de comenzi

• A[Nmax ][Nmax ]; - memoreaza cantitatea de produs

• C [Nmax ][Nmax ]; - C [i][ j ] = cantitatea maxim˘ a de carto culeas˘a pe untraseu ce porneste din (1 , 1) si se termin˘a ın ( i, j ), respect and condit iileproblemei

• P [Nmax ][Nmax ]; - P [i][ j ] = pasul la care am a juns ın pozit ¸ia i, j culegando cantitate maxim˘ a de carto

• Move[2∗Nmax ]; - memoreaza cele K comenzi

Parcurg sirul celor k mut ari. La ecare mutare marchez pozit ¸iile ın care potajunge la mutarea respectiv˘ a.

Mai exact, parcurg toate pozit ¸iile ın care am putut a junge la pasul precedent(cele marcate ın matricea P corespunz ator cu num˘arul pasului precedent) si pentruecare pozit ie veric dac a la pasul curent pot s˘ a execut mutarea la sud.

In caz armativ, veric dac˘ a ın acest caz obt¸in o cantitate de carto maimare dec at cea obt inut˘a pan a la momentul curent (dac˘ a da, ret in noua cantitate,si marchez ın matricea P pozit ia ın care am ajuns cu indicele mut˘ arii curente).

In mod similar procedez pentru o mutare spre est.

Codul sursa *

Variant˘a dup a solut ia ocial a:

import java.io.*;class Sudest1

static StreamTokenizer st;static PrintWriter out;static final int Nmax=101;static int N, K;static int[][] A=new int[Nmax][Nmax]; // A[i][j]=cantitatea de cartofistatic int[][] C=new int[Nmax][Nmax]; // C[i][j]=cantitatea maxima ...static int[][] P=new int[Nmax][Nmax]; // passtatic int[] Move=new int[2*Nmax]; // comenzile

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 200/518

188 CAPITOLUL 13. ALGORITMI BFS-LEE

public static void main(String[] args) throws IOException

st=new StreamTokenizer( new BufferedReader(new FileReader("sudest.in")));out=new PrintWriter(new BufferedWriter(new FileWriter("sudest.out")));read_data();init();solve();

// main(...)

static void read_data() throws IOException

int i,j,cmd;st.nextToken(); N=(int)st.nval;for(i=1;i<=N;i++)

for(j=1;j<=N;j++) st.nextToken(); A[i][j]=(int)st.nval;st.nextToken(); K=(int)st.nval;for(cmd=1;cmd<=K;cmd++) st.nextToken(); Move[cmd]=(int)st.nval;

// read_data()

static void init()

int i,j;for(i=1;i<=N;i++) for(j=1;j<=N;j++) C[i][j]=-1; P[i][j]=255;

// init()

static boolean posibil(int x,int y) return 1<=x && 1<=y && x<=N && y<=N;

static void solve()

int i,j, cmd;P[1][1]=0;C[1][1]=A[1][1];for(cmd=1; cmd<=K; cmd++)

for(i=1; i<=N; i++)for(j=1; j<=N; j++)

if(P[i][j]==cmd-1)

if(posibil(i+Move[cmd],j)) // SUDif(C[i][j]+A[i+Move[cmd]][j]>C[i+Move[cmd]][j])

P[i+Move[cmd]][j]=cmd;C[i+Move[cmd]][j]=C[i][j]+A[i+Move[cmd]][j];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 201/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 202/518

190 CAPITOLUL 13. ALGORITMI BFS-LEE

static int[][] a=new int[nmax][nmax]; // a[i][j]=cantitatea de cartofistatic int[][] c=new int[nmax][nmax]; // c[i][j]=cantitatea maxima ...static int[][] p=new int[nmax][nmax]; // pozitia anterioara optimastatic int[] move=new int[2*nmax]; // comenzilestatic int ic,sc,scv,qmax=100;static int[] q=new int[qmax]; // coada

public static void main(String[] args) throws IOException

st=new StreamTokenizer(new BufferedReader(new FileReader("sudest.in")));out=new PrintWriter(new BufferedWriter(new FileWriter("sudest.out")));read_data();init();solve();

// main(...)

static void read_data() throws IOException

int i,j,cmd;st.nextToken(); n=(int)st.nval;for(i=1;i<=n;i++)

for(j=1;j<=n;j++) st.nextToken(); a[i][j]=(int)st.nval;st.nextToken(); k=(int)st.nval;for(cmd=1;cmd<=k;cmd++) st.nextToken(); move[cmd]=(int)st.nval;

// read_data()

static void init()int i,j;for(i=1;i<=n;i++) for(j=1;j<=n;j++) c[i][j]=-1; p[i][j]=255;

// init()

static void solve()

int i,j,ii,jj,cmd;p[1][1]=0; c[1][1]=a[1][1];ic=0; sc=1; q[ic]=1; // pozitia [1][1] --> qscv=1; // ultimul din coada la distanta 1 de [1][1]for(cmd=1; cmd<=k; cmd++)

while(ic!=scv)

i=(q[ic]-1)/n+1; j=(q[ic]-1)%n+1; ic=(ic+1)%qmax; // scot din coada// propag catre Sud

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 203/518

13.2. PROBLEME REZOLVATE 191

ii=i+move[cmd];jj=j;if((ii>=1)&&(ii<=n))

if(c[i][j]+a[ii][jj]>c[ii][jj])

c[ii][jj]=c[i][j]+a[ii][jj];p[ii][jj]=(i-1)*n+j;q[sc]=(ii-1)*n+jj; sc=(sc+1)%qmax; // pun in coada

// propag catre Estjj=j+move[cmd];ii=i;if((jj>=1)&&(jj<=n))

if(c[i][j]+a[ii][jj]>c[ii][jj])

c[ii][jj]=c[i][j]+a[ii][jj];p[ii][jj]=(i-1)*n+j;q[sc]=(ii-1)*n+jj; sc=(sc+1)%qmax; // pun in coada

// whilescv=sc;

// for

out.println(c[n][n]); drum(n,n); out.close();// solve()

static void drum(int i, int j)

if(i*j==0) return;drum((p[i][j]-1)/n+1,(p[i][j]-1)%n+1);out.println(i+" "+j);

// drum(...)// class

13.2.3 Muzeu - ONI2003 clasa a X-a

Suntet i un participant la Olimpiada Nat ¸ional a de Informatic˘a. In pro-gramul olimpiadei intr˘ a si cateva activit˘ at ii de divertisment. Una dintre ele estevizitarea unui muzeu. Acesta are o structur˘ a de matrice dreptunghiular˘ a cu M linii si N coloane; din orice camer˘a se poate a junge ın camerele vecine pe direct ¸iilenord, est, sud si vest (dac˘ a aceste camere exist˘a). Pentru pozit ¸ia ( i, j ) deplasareaspre nord presupune trecerea ın pozit ¸ia ( i −1, j ), spre est ın ( i, j + 1), spre sud ın

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 204/518

192 CAPITOLUL 13. ALGORITMI BFS-LEE

(i + 1 , j ) si spre vest ın ( i, j −1).

Acest muzeu are cˆateva reguli speciale. Fiecare camer˘ a este marcat˘a cu unnum ar ıntre 0 si 10 inclusiv. Mai multe camere pot marcate cu acelasi num˘ ar.Camerele marcate cu num˘ arul 0 pot vizitate gratuit. Intr-o camer˘a marcat˘acu num arul i (i > 0) se poate intra gratuit, dar nu se poate iesi din ea decˆ atdac a ar atat i supraveghetorului un bilet cu num˘ arul i. Din fericire, orice camer˘acu num arul i (i > 0) ofera spre v anzare un bilet cu num˘ arul i; o dat a cump aratacest bilet, el este valabilın toate camerele marcate cu num˘ arul respectiv. Biletelepot avea pret¸uri diferite, dar un bilet cu num˘ arul i va avea acelasi pret ın toatecamerele ın care este oferit spre vˆ anzare.

Dumneavoastr˘a intrat¸i ın muzeu prin colt ¸ul de Nord-Vest (pozit ¸ia (1 , 1) amatricei) si dorit ¸i sa ajunget i la iesirea situat˘ a ın colt ul de Sud-Est (pozit ¸ia ( M, N )a matricei). O dat˘ a ajuns acolo primit¸i un bilet gratuit care v˘ a permite s a vizitat i

tot muzeul.Pozit iile (1 , 1) si (M, N ) sunt marcate cu num˘ arul 0.

Cerint ¸a

Cunosc andu-se structura muzeului, determinat ¸i o strategie de parcurgere acamerelor, astfel ıncˆ at s a ajunget i ın camera ( M, N ) platind c at mai put¸in. Dac aexist a mai multe variante, aleget ¸i una ın care este parcurs un num˘ ar minim decamere (pentru a cˆ a?tiga timp si pentru a avea mai mult timp pentru vizitareaintegral a a muzeului).

Date de intrare

Prima linie a sierului de intrare muzeu.in contine dou a numere ıntregi M si N , separate printr-un spat ¸iu, num˘arul de linii, respectiv de coloane, al matriceicare reprezint˘a muzeul. Urm˘atoarele M linii cont in structura muzeului; ecarecontine N numere ıntregi ıntre 0 si 10 inclusiv, separate prin spat ¸ii. Linia M + 2contine 10 numere ıntregi ıntre 0 si 10000 inclusiv, reprezentˆ and costurile biletelor1, 2, 3,... 10 ın aceast˘a ordine.

Date de iesire

In sierul muzeu.out veti asa:

pe prima linie suma minim˘ a necesar a pentru a ajunge din (1 , 1) ın ( M, N );

pe a doua linie num˘arul minim de mut˘ari L efectuate dintr-o camer˘ a ıntr-ocamer a vecina, pentru a ajunge din (1 , 1) ın ( M, N );

pe a treia linie L caractere din multimea N , E , S , V reprezentˆand deplas˘arispre Nord, Est, Sud sau Vest.

Restrict ii si precizari

2 ≤N ≤50

Exemplu:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 205/518

13.2. PROBLEME REZOLVATE 193

muzeu.in muzeu.out5 6 120 0 0 0 0 2 90 1 1 1 4 3 EEEEESSSS0 1 0 0 0 00 1 5 1 0 00 0 0 1 0 01000 5 7 100 12 1000 1000 1000 1000 1000

Timp maxim de executare: 1 secund a/test.

Indicat ¸ii de rezolvare *

Mihai Stroe, GInfo nr. 13/6 - octombrie 2003 Se observ a ca num arul variantelor de cump˘ arare a biletelor (cump˘ ar / nu

cump ar biletul 1, biletul 2, ..., biletul 10) este 2 10 = 1024.Se genereaz a ecare din aceste variante. Pentru o astfel de variant˘ a, se cal-

culeaz a costul si se transform˘ a matricea init¸ial a ıntr-o matrice cu 0 si 1, ın care 0reprezint˘a o camer a pentru care se pl˘ateste biletul (sau nu e nevoie de bilet) si 1reprezint˘a o camer a pentru care nu se cump˘ ara bilet (deci ın care nu se intr˘ a).

Pentru o astfel de matrice, problema determin˘ arii celui mai scurt drum de la(1, 1) la (M, N ) se rezolva cu algoritmul lui Lee .

Se rezolva aceast a problem a pentru toate cele 1024 variante. Eventual, dac˘ ala un moment dat exist˘ a o solutie cu un cost mai bun decˆat al variantei curente,aceasta nu mai este abordat˘ a.

Evident, problema determin˘ arii celui mai scurt drum se poate rezolva si pematricea init¸ial a, tin and cont la ecare pas de biletele cump˘ arate; cum algoritmul lui Lee este folosit de obicei pentru o matrice cu 0 si 1, am folosit init ¸ial convent iarespectiv˘a pentru a usura ınelegerea.

Se alege solutia de cost minim si, ın caz de egalitate, cea cu num˘ ar minim decamere.

Analiza complexit˘ at iiOperat ia de citire a datelor are ordinul de complexitate O(M ·N ).Fie C num arul de numere de marcaj diferite din matrice. Pentru ecare dintre

cele 2C variante, g˘asirea drumului minim cu algoritmul lui Lee are complexitateaO(M ·N ).

Operat ia de scriere a solut¸iei are ordinul de complexitate O(M ·N ) pentrucazul cel mai defavorabil.

Ordinul de complexitate al algoritmului de rezolvare a acestei probleme esteO(M ·N ·2C ).

Algoritmul funct¸ioneaz˘a datorit˘a restrict iei impuse pentru C (cel mult 10numere de marcaj). Considerˆ and 2C o constant˘a, ordinul de complexitate devineO(M ·N ).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 206/518

194 CAPITOLUL 13. ALGORITMI BFS-LEE

Codul sursa

import java.io.*;class Muzeu

static final int qdim=200; // dimensiune coada circularastatic final int sus=1, dreapta=2, jos=3, stanga=4;

static int m,n; // dimensiuni muzeustatic int ncmin; // nr camere minimstatic int cc,cmin=50*50*10000/2; // cost curent/minimstatic boolean amAjuns;

static int[][] x=new int[51][51]; // muzeustatic int[][] c=new int[51][51]; // costul (1,1) --> (i,j)static int[][] d=new int[51][51]; // directii pentru "intoarcere"static int[][] dsol=new int[51][51];

static int[] cb=new int[11]; // costuri biletestatic boolean[] amBilet=new boolean[11];

static int[] qi=new int[qdim]; // coada pentru i din pozitia (i,j)static int[] qj=new int[qdim]; // coada pentru j din pozitia (i,j)static int ic, sc; // ic=inceput coada

public static void main(String[] args) throws IOExceptionint i,j;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("10-muzeu.in")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;

for(i=1;i<=m;i++)for(j=1;j<=n;j++) st.nextToken(); x[i][j]=(int)st.nval;

for(i=1;i<=10;i++) st.nextToken(); cb[i]=(int)st.nval;

amBilet[0]=true; // 0 ==> gratuitfor(i=0;i<=1023;i++)

bilete(i);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 207/518

13.2. PROBLEME REZOLVATE 195

cc=0; for(j=1;j<=10;j++) if(amBilet[j]) cc+=cb[j];if(cc>cmin) continue;

amAjuns=false; matriceCosturi();

if(!amAjuns) continue;if(cc>cmin) continue;if(cc<cmin) cmin=cc; ncmin=c[m][n]; copieDirectii(); else // costuri egale

if(c[m][n]<ncmin) ncmin=c[m][n]; copieDirectii();

d=dsol; // schimbare "adresa" ... ("pointer"!) ...afisSolutia();

// main()

static void bilete(int i)

int j;for(j=1;j<=10;j++)

if(i%2==1) amBilet[j]=true; else amBilet[j]=false;i/=2;

// bilete(...)

static void matriceCosturi()

int i,j;for(i=1;i<=m;i++)for(j=1;j<=n;j++) c[i][j]=0; // curat "numai" traseul !ic=sc=0; // coada vidaqi[sc]=1; qj[sc]=1; sc=(sc+1)%qdim; // (1,1) --> coada circulara !c[1][1]=1; // cost 1 pentru pozitia (1,1) (pentru marcaj!)while(ic!=sc) // coada nevida

i=qi[ic]; j=qj[ic]; ic=(ic+1)%qdim;vecini(i,j);if(amAjuns) break;

//matriceCosturi()

static void copieDirectii()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 208/518

196 CAPITOLUL 13. ALGORITMI BFS-LEE

int i,j;for(i=1;i<=m;i++) for(j=1;j<=n;j++) dsol[i][j]=d[i][j];

// copieDirectii()

static void vecini(int i, int j)

int t=c[i][j]; // "timp" = nr camere parcurse

if((i-1>=1)&&(c[i-1][j]==0)&&amBilet[x[i-1][j]]) // N

c[i-1][j]=t+1; qi[sc]=i-1; qj[sc]=j; sc=(sc+1)%qdim;d[i-1][j]=jos;if((i-1==m)&&(j==n)) amAjuns=true; return;

if((j+1<=n)&&(c[i][j+1]==0)&&amBilet[x[i][j+1]]) // E

c[i][j+1]=t+1; qi[sc]=i; qj[sc]=j+1; sc=(sc+1)%qdim;d[i][j+1]=stanga;if((i==m)&&(j+1==n)) amAjuns=true; return;

if((i+1<=m)&&(c[i+1][j]==0)&&amBilet[x[i+1][j]])// S

c[i+1][j]=t+1; qi[sc]=i+1; qj[sc]=j; sc=(sc+1)%qdim;

d[i+1][j]=sus;if((i+1==m)&&(j==n)) amAjuns=true; return;

if((j-1>=1)&&(c[i][j-1]==0)&&amBilet[x[i][j-1]]) // V

c[i][j-1]=t+1; qi[sc]=i; qj[sc]=j-1; sc=(sc+1)%qdim;d[i][j-1]=dreapta;if((i==m)&&(j-1==n)) amAjuns=true; return;

// vecini(...)

static void afisSolutia() throws IOException

int i,j;PrintWriter out = new PrintWriter(

new BufferedWriter(new FileWriter("muzeu.out")));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 209/518

13.2. PROBLEME REZOLVATE 197

out.println(cmin);out.println(ncmin-1);

i=m; j=n; // (m,n) --> (1,1)while((i!=1)||(j!=1)) // folosesc "c" care nu mai e necesara !if(d[i][j]==sus) c[i-1][j]=jos; i--; else if(d[i][j]==jos) c[i+1][j]=sus; i++;else if(d[i][j]==dreapta) c[i][j+1]=stanga; j++; else if(d[i][j]==stanga) c[i][j-1]=dreapta; j--; else System.out.println("Eroare la traseu ... (m,n)-->(1,1)!");

i=1; j=1; // (1,1) --> (m,n)while((i!=m)||(j!=n))

if(c[i][j]==sus) out.print("N"); i--;else if(c[i][j]==jos) out.print("S"); i++;else if(c[i][j]==dreapta) out.print("E"); j++;else if(c[i][j]==stanga) out.print("V"); j--;else System.out.println("Eroare la traseu ... (1,1)--(m,n)!");

out.close();

//afisSolutia()// class

13.2.4 Paianjen ONI2005 clasa a X-a

Un p aianjen a t esut o plas˘a, ın care nodurile sunt dispuse sub forma unuicaroiaj cu m linii (numerotate de la 0 la m −1) si n coloane (numerotate de la 0 lan −1) ca ın gur˘a. Init ial, oricare dou˘a noduri vecine (pe orizontal˘ a sau vertical˘a)erau unite prin segmente de plas˘ a de lungime 1. In timp unele port¸iuni ale plasei s-au deteriorat, devenind nesigure. Pe plas˘ a, la un moment dat, se g˘ asesc paianjenulsi o musc a, ın noduri de coordonate cunoscute.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 210/518

198 CAPITOLUL 13. ALGORITMI BFS-LEE

0

1

2

3

4

5

6

7

8

0 1 2 3 4 5 6

pozitie paianzen

pozitie musca

Cerint ¸a

Sa se determine lungimea celui mai scurt traseu pe care trebuie s˘ a-l parcurg˘apaianjenul, folosind doar port ¸iunile sigure ale plasei, pentru a ajunge la musc˘ a. Deasemenea, se cere un astfel de traseu.

Datele de intrareFisierul de intrare paianjen.in contine:

− pe prima linie dou a numere naturale m n , separate printr-un spat ¸iu,reprezentˆand num arul de linii si respectiv num˘ arul de coloane ale plasei;

− pe a doua linie dou a numere naturale lp cp, separate printr-un spat ¸u,reprezentnd linia si respectiv coloana nodului ın care se a˘ a init ial p aianjenul;

− pe linia a treia dou˘a numere naturale lm cm separate printr-un spat ¸iu,reprezentˆand linia si respectiv coloana pe care se a˘ a init ial musca;

−pe linia a patra, un num˘ ar natural k, reprezentˆand num arul de port iuni

de plas a deteriorate;

−pe ecare dintre urm˘ atoarele k linii, cate patru valori naturale l1 c1 l2 c2,separate prin cˆate un spat¸iu, reprezentˆ and coordonatele capetelor celor k port iunide plas a deteriorate (linia si apoi coloana pentru ecare cap˘ at).

Datele de iesireFisierul de iesire paianjen.out va cont ine pe prima linie un num˘ ar natural

min reprezentˆand lungimea drumului minim parcurs de p˘ aianjen, exprimat ınnum ar de segmente de lungime 1. Pe urm˘ atoarele min +1 linii sunt scrise nodurileprin care trece p˘aianjenul, cˆate un nod pe o linie. Pentru ecare nod sunt scriselinia si coloana pe care se a˘a, separate printr-un spat ¸iu.

Restrict ii si precizari

• 1 ≤m, n ≤140• 1 ≤k ≤2∗(m∗n −m −n + 1)

• Lungimea drumului minim este cel mult 15000

• Pentru datele de test exist˘ a ıntotdeauna solut ¸ie. Dac a problema are maimulte solut ii, se va asa una singur˘ a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 211/518

13.2. PROBLEME REZOLVATE 199

• Port iunile nesigure sunt specicate ın sierul de intrare ıntr-o ordine oare-care. Oricare dou˘a port iuni nesigure orizontale se pot intersecta cel mult ıntr-uncapat. De asemenea, oricare dou˘ a port iuni nesigure verticale se pot intersecta celmult ıntr-un cap˘ at.

• Se acord a 30% din punctaj pentru determinarea lungimii drumului minimsi 100% pentru rezolvarea ambelor cerint ¸e.

Exemplupaianjen.in paianjen.out Explicat ie9 7 8 Problema corespunde gurii de mai sus.2 3 2 3 Traseul optim este desenat cu linie groas˘ a,7 4 2 2 iar portiunile nesigure sunt desenate punctat.8 3 22 4 2 5 4 2

2 3 3 3 5 23 0 3 1 6 23 3 3 5 6 34 4 5 4 7 36 4 6 5 7 46 5 7 57 2 7 3

Timp maxim de execut ¸ie/test: 1 secund a pentru Windows si 0 .1 secundepentru Linux.

Indicat ¸ii de rezolvare *

prof. Carmen Popescu, C. N. ”Gh. Laz˘ ar” Sibiu Plasa de p aianjen se memoreaz˘a ıntr-o matrice A cu M linii si N coloane,

ecare element reprezentˆ and un nod al plasei. A[i, j ] va codica pe patru bit¸idirect iile ın care se poate face deplasarea din punctul ( i, j ): bitul 0 este 1 dac apaianjenul se poate deplasa ın sus, bitul 1 este 1 dac˘ a se poate deplasa la dreapta,bitul 2 - ın jos, bitul 3 - la stˆanga.

Rezolvarea se bazeaz˘a pe parcurgerea matriciei si ret ¸inerea nodurilor parcurseıntr-o structur˘ a de date de tip coad˘ a (parcurgere BF - algoritm Lee).

Drumul minim al p˘aianjenului se ret¸ine ıntr-o alt˘ a matrice B , unde B [i, j ] este0 daca nodul ( i, j ) nu este atins, respectiv o valoare pozitiv˘ a reprezentˆand pasulla care a a juns paianjenul ın drumul lui spre musc˘ a. Deci elementul B [lm,cm ] vacontine lungimea drumului minim.

Reconstituirea drumului minim se face pornind de la pozit ¸ia mustei, utilizˆ and,de asemenea un algoritm de tip BF, cu oprirea c˘ aut arii ın jurul nodului curent ınmomentul detect˘ arii unui nod de pas mai mic cu o unitate decˆ at cel al noduluicurent.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 212/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 213/518

13.2. PROBLEME REZOLVATE 201

System.out.println("TIME = "+(t2-t1)+" millisec ");// main()

static void citescDate() throws IOException

int nrSegmenteDeteriorate, k,i,j,l1,c1,l2,c2;int i1,i2,j1,j2;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("paianjen.in")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;st.nextToken(); lp=(int)st.nval;st.nextToken(); cp=(int)st.nval;st.nextToken(); lm=(int)st.nval;st.nextToken(); cm=(int)st.nval;st.nextToken(); nrSegmenteDeteriorate=(int)st.nval;

for(i=0;i<m;i++) for(j=0;j<n;j++) p[i][j]=0xF; // 1111=toate firele !for(k=1;k<=nrSegmenteDeteriorate;k++)

st.nextToken();l1=(int)st.nval;st.nextToken();c1=(int)st.nval;st.nextToken();l2=(int)st.nval;st.nextToken();c2=(int)st.nval;

i1=min(l1,l2); i2=max(l1,l2);j1=min(c1,c2); j2=max(c1,c2);

if(j1==j2) // ruptura verticala

p[i1][j1]^=jos; // sau ... p[i1][j1]-=jos; ... !!!for(i=i1+1;i<=i2-1;i++)

p[i][j1]^=jos; // 0 pe directia josp[i][j1]^=sus; // 0 pe directia sus

p[i2][j1]^=sus;

elseif(i1==i2) // ruptura orizontala

p[i1][j1]^=dreapta; // 0 pe directia dreaptafor(j=j1+1;j<=j2-1;j++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 214/518

202 CAPITOLUL 13. ALGORITMI BFS-LEE

p[i1][j]^=dreapta;p[i1][j]^=stanga;

p[i1][j2]^=stanga; // 0 pe directia stanga

else System.out.println("Date de intrare ... eronate !");

// for k//citescDate()

static void matriceCosturi()

int i,j;ic=sc=0; // coada vidaqi[sc]=lp; qj[sc]=cp; sc=(sc+1)%qdim; // (lp,cp) --> coada !c[lp][cp]=1; // cost 1 pentru pozitie paianjen (pentru marcaj!)while(ic!=sc) // coada nevida

i=qi[ic]; j=qj[ic]; ic=(ic+1)%qdim;fill(i,j);if(c[lm][cm]!=0) break; // a ajuns deja la musca !

// while//matriceCosturi()

static void fill(int i, int j)

int t=c[i][j]; // timp !

if((i-1>=0)&&(c[i-1][j]==0)&&ok(i,j,sus)) // N

c[i-1][j]=t+1;qi[sc]=i-1;qj[sc]=j;sc=(sc+1)%qdim;d[i-1][j]=jos;

if((j+1<=n-1)&&(c[i][j+1]==0)&&ok(i,j,dreapta)) // E

c[i][j+1]=t+1;qi[sc]=i;qj[sc]=j+1;sc=(sc+1)%qdim;d[i][j+1]=stanga;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 215/518

13.2. PROBLEME REZOLVATE 203

if((i+1<=m-1)&&(c[i+1][j]==0)&&ok(i,j,jos)) // S

c[i+1][j]=t+1;qi[sc]=i+1;qj[sc]=j;sc=(sc+1)%qdim;d[i+1][j]=sus;

if((j-1>=0)&&(c[i][j-1]==0)&&ok(i,j,stanga)) // V

c[i][j-1]=t+1;qi[sc]=i;qj[sc]=j-1;sc=(sc+1)%qdim;d[i][j-1]=dreapta;

// fill(...)

static boolean ok(int i, int j, int dir)

if((p[i][j]&dir)!=0) return true; else return false;// ok(...)

static int min(int a, int b)if(a<b) return a; else return b;

static int max(int a, int b)

if(a>b) return a; else return b;

static void afisSolutia() throws IOException

int i,j;PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("paianjen.out")));out.println(c[lm][cm]-1);

i=lm;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 216/518

204 CAPITOLUL 13. ALGORITMI BFS-LEE

j=cm;while((i!=lp)||(j!=cp)) // folosesc matricea c care nu mai e necesara !

if(d[i][j]==sus) c[i-1][j]=jos; i--; else if(d[i][j]==jos) c[i+1][j]=sus; i++;else if(d[i][j]==dreapta) c[i][j+1]=stanga; j++; else if(d[i][j]==stanga) c[i][j-1]=dreapta; j--; else System.out.println("Eroare la traseu ... !");

i=lp;j=cp;while((i!=lm)||(j!=cm))

out.println(i+" "+j);if(c[i][j]==sus) i--;else if(c[i][j]==jos) i++;else if(c[i][j]==dreapta) j++;else if(c[i][j]==stanga) j--;else System.out.println("Eroare la traseu ... !");

out.println(i+" "+j); // pozitia pentru musca !out.close();

//afisSolutia()// class

13.2.5 Algoritmul Edmonds-Karp

import java.io.*;class FluxMaxim

static final int WHITE=0, GRAY=1, BLACK=2;static final int MAX_NODES=10;static final int oo=0x7fffffff;static int n, m; // nr noduri, nr arcestatic int[][] c=new int[MAX_NODES+1][MAX_NODES+1]; // capacitatistatic int[][] f=new int [MAX_NODES+1][MAX_NODES+1]; // fluxstatic int[] color=new int[MAX_NODES+1]; // pentru bfsstatic int[] p=new int[MAX_NODES+1]; // predecesor (ptr. drum crestere)static int ic, sc; // inceput coada, sfarsit coadastatic int[] q=new int[MAX_NODES+2]; // coada

public static void main(String[] args) throws IOException

int s,t,i,j,k,fluxm; // fluxm=flux_maximStreamTokenizer st=new StreamTokenizer(

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 217/518

13.2. PROBLEME REZOLVATE 205

new BufferedReader(new FileReader("fluxMaxim.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("fluxMaxim.out")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;st.nextToken(); s=(int)st.nval;st.nextToken(); t=(int)st.nval;

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); c[i][j]=(int)st.nval;

fluxm=fluxMax(s,t);

System.out.println("\nfluxMax("+s+","+t+") = "+fluxm+" :");for(i=1;i<=n;i++)

for(j=1;j<=n;j++) System.out.print(maxim(f[i][j],0)+"\t");System.out.println();

out.print(fluxm); out.close();

// main()

static int fluxMax(int s, int t)int i, j, u, min, maxf = 0;for(i=1; i<=n; i++) for(j=1; j<=n; j++) f[i][j]=0;

// Cat timp exista drum de crestere a fluxului (in graful rezidual),// mareste fluxul pe drumul gasitwhile(bfs(s,t))

// Determina cantitatea cu care se mareste fluxul min=oo;for(u=t; p[u]!=-1; u=p[u]) min=minim(min,c[p[u]][u]-f[p[u]][u]);

// Mareste fluxul pe drumul gasitfor(u=t; p[u]!=-1; u=p[u])

f[p[u]][u]+=min;f[u][p[u]]-=min; // sau f[u][p[u]]=-f[p[u]][u];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 218/518

206 CAPITOLUL 13. ALGORITMI BFS-LEE

maxf += min;System.out.print("drum : ");drum(t);System.out.println(" min="+min+" maxf="+maxf+"\n");

// while(...)

// Nu mai exista drum de crestere a fluxului ==> Gata !!!System.out.println("Nu mai exista drum de crestere a fluxului !!!");return maxf;

// fluxMax(...)

static boolean bfs(int s, int t) // s=sursa t=destinatie

// System.out.println("bfs "+s+" "+t+" flux curent :");// afism(f);int u, v;boolean gasitt=false;

for(u=1; u<=n; u++) color[u]=WHITE; p[u]=-1; ic=sc=0; // coada vidaincoada(s);p[s]=-1;

while(ic!=sc)

u=dincoada();

// Cauta nodurile albe v adiacente cu nodul u si pune v in coada// cand capacitatea reziduala a arcului (u,v) este pozitivafor(v=1; v<=n; v++)

if(color[v]==WHITE && ((c[u][v]-f[u][v])>0))

incoada(v);p[v]=u;if(v==t) gasitt=true; break;

if(gasitt) break;//while

return gasitt;// bfs(...)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 219/518

13.2. PROBLEME REZOLVATE 207

static void drum(int u)

if(p[u]!=-1) drum(p[u]);System.out.print(u+" ");

// drum(...)

static void afism(int[][] a)

int i,j;for(i=1;i<=n;i++)

for(j=1;j<=n;j++) System.out.print(a[i][j]+"\t");System.out.println();

// System.out.println();

// afism(...)

static int minim(int x, int y) return (x<y) ? x : y;

static int maxim(int x, int y) return (x>y) ? x : y;

static void incoada(int u)

q[sc++]=u;color[u]=GRAY;

static int dincoada()

int u=q[ic++];color[u]=BLACK;return u;

// class

/*6 10 1 6 drum : 1 2 4 6 min=12 maxf=121 2 16 drum : 1 3 5 6 min= 4 maxf=161 3 13 drum : 1 3 5 4 6 min= 7 maxf=232 3 4 Nu mai exista drum de crestere a fluxului !!!2 4 12 fluxMax(1,6) = 23 :3 2 10 0 12 11 0 0 03 5 14 0 0 0 12 0 0

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 220/518

208 CAPITOLUL 13. ALGORITMI BFS-LEE

4 3 9 0 0 0 0 11 04 6 20 0 0 0 0 0 195 4 7 0 0 0 7 0 45 6 4 0 0 0 0 0 0*/

13.2.6 Cuplaj maxim/* Culori - Descrierea problemei:Doi elfi au pus pe o masa n patratele si m cerculete. Unul a ales patratelelesi celalalt cerculetele si au desenat pe ele mai multe benzi colorate. Apoi auinceput sa se joace cu patratelele si cerculetele. Au decis ca un cerculetpoate fi amplasat pe un patratel daca exista cel putin o culoare care aparepe ambele. Ei doresc sa formeze perechi din care fac parte un cerculet si unpatratel astfel incat sa se obtina cat mai multe perechi.

Date de intrare: Fisierul de intrare de intrare contine pe prima linienumarul n al patratelelor. Pe fiecare dintre urmatoarele n linii suntdescrise benzile corespunzatoare unui patratel. Primul numar de pe o astfelde linie este numarul b al benzilor, iar urmatoarele b numere reprezintacodurile celor b culori. Urmatoarea linie contine numarul m al cerculetelor.Pe fiecare dintre urmatoarele m linii sunt descrise benzile corespunzatoareunui cerculet. Primul numar de pe o astfel de linie este numarul b albenzilor, iar urmatoarele b numere reprezinta codurile celor b culori.Numerele de pe o linie vor fi separate prin cte un spatiu. Patratelele sicerculetele vor fi descrise in ordinea data de numarul lor de ordine.

Date de iesire: Fisierul de iesire trebuie sa contina pe prima linie numarulk al perechilor formate. Fiecare dintre urmatoarele k va contine cate douanumere, separate printr-un spatiu, reprezentand numerele de ordine ale unuipatratel, respectiv cerc, care formeaza o pereche.

Restrictii si precizari: numarul patratelelor este cuprins intre 1 si 100;numarul cerculetelor este cuprins intre 1 si 100; patratelele sunt identificateprin numere cuprinse intre 1 si n; cerculetele sunt identificate prin numerecuprinse intre 1 si m; numarul benzilor colorate de pe cerculete si patrateleeste cuprins intre 1 si 10; un patratel sau un cerc nu poate face parte din mai mult decat o pereche; daca exista mai multe solutii trebuie determinatadoar una dintre acestea.ExempluINPUT.TXT OUTPUT.TXT3 21 1 1 1 1 . 1 \1 2 3 2 / . \

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 221/518

13.2. PROBLEME REZOLVATE 209

1 3 s=0 - 2 . 2 --- n+m+1=t4 \ . / /2 1 2 3 . 3 / /1 3 . /2 3 4 . 4 /1 4 Timp de executie: 0,5 secunde/test */

import java.io.*; // u=0 ==> v=1,2,...,nclass CuplajMaximCulori // u=1,..,n ==> v=n+1,..,n+m // u=n+1,..,n+m ==> v=1,2,.,n sau n+m+1(=t)

static final int WHITE=0, GRAY=1, BLACK=2;static final int oo=0x7fffffff;static int n, m, ic, sc;static int[][] c, f; // capacitati, fluxstatic boolean[][] cp, cc; // cp = culoare patratel, cc = culoare cercstatic int[] color, p, q; // predecesor, coada

public static void main(String[] args) throws IOException

citire();capacitati();scrie(fluxMax(0,n+m+1));

// main()

static void citire() throws IOException

int i,j,k,nc;StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("CuplajMaximCulori.in")));

st.nextToken(); n=(int)st.nval; cp=new boolean[n+1][11];for(i=1;i<=n;i++)

st.nextToken(); nc=(int)st.nval;for(k=1;k<=nc;k++)

st.nextToken(); j=(int)st.nval;cp[i][j]=true;

st.nextToken(); m=(int)st.nval; cc=new boolean[m+1][11];for(i=1;i<=m;i++)

st.nextToken(); nc=(int)st.nval;for(k=1;k<=nc;k++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 222/518

210 CAPITOLUL 13. ALGORITMI BFS-LEE

st.nextToken(); j=(int)st.nval;cc[i][j]=true;

// citire()

static void capacitati()

int i,ic,j,jc;c=new int[n+m+2][n+m+2];for(i=1;i<=n;i++)

c[0][i]=1;for(ic=1;ic<=10;ic++)

if(cp[i][ic])for(j=1;j<=m;j++)

if(cc[j][ic]) c[i][j+n]=1;for(j=1;j<=m;j++) c[j+n][n+m+1]=1;

// capacitati()

static int fluxMax(int s, int t)

int i,j,u,min,maxf=0;

f=new int[n+m+2][n+m+2];p=new int[n+m+2];q=new int[n+m+2];color=new int[n+m+2];

for(i=0;i<=n+m+1;i++)for(j=0;j<=n+m+1;j++) f[i][j]=0;

while(bfs(s,t))

min=oo;for(u=t;p[u]!=-1;u=p[u]) min=minim(min,c[p[u]][u]-f[p[u]][u]);for(u=t;p[u]!=-1;u=p[u])

f[p[u]][u]+=min;f[u][p[u]]-=min; // sau f[u][p[u]]=-f[p[u]][u];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 223/518

13.2. PROBLEME REZOLVATE 211

maxf+=min;// while(...)

return maxf;// fluxMax(...)

static boolean bfs(int s, int t)

int u, v;boolean gasitt=false;for(u=0;u<=n+m+1;u++) color[u]=WHITE; p[u]=-1;ic=sc=0;q[sc++]=s; color[s]=GRAY; // s --> coadap[s]=-1;while(ic!=sc)

u=q[ic++]; color[u]=BLACK;if(u==0)

for(v=1;v<=n;v++)if((color[v]==WHITE)&&((c[u][v]-f[u][v])>0))

q[sc++]=v; color[v]=GRAY; // incoada(v);p[v]=u;

else if(u<=n)for(v=n+1;v<=n+m;v++)

if((color[v]==WHITE)&&((c[u][v]-f[u][v])>0))

q[sc++]=v; color[v]=GRAY; // incoada(v);p[v]=u;

else

for(v=n+m+1;v>=1;v--)if((color[v]==WHITE)&&((c[u][v]-f[u][v])>0))

q[sc++]=v; color[v]=GRAY; // incoada(v);p[v]=u;if(v==t) gasitt=true; break;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 224/518

212 CAPITOLUL 13. ALGORITMI BFS-LEE

if(gasitt) break; // din while !

// while()

return gasitt;// bfs()

static int minim(int x, int y) return (x<y) ? x : y;

static int maxim(int x, int y) return (x>y) ? x : y;

static void scrie(int fluxm) throws IOException

int i,j;PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("CuplajMaximCulori.out")));out.println(fluxm);for (i=1;i<=n;i++)

if(f[0][i]>0)for(j=1;j<=m;j++)

if(f[i][j+n]>0)

out.println(i+" "+j);break;

out.close();// scrie(...)// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 225/518

Capitolul 14

Metoda optimului local -

greedy14.1 Metoda greedy

Metoda Greedy are ın vedere rezolvarea unor probleme de optim ın careoptimul global se determin˘ a din estim ari succesive ale optimului local.

Metoda Greedy se aplic˘a urm atorului tip de problem˘ a: dintr-o mult¸ime deelemente C (candidat i la construirea solut ¸iei problemei), se cere s a se determineo submult ime S , (solut ia problemei) care ındeplineste anumite condit ii . Deoareceeste posibil s a existe mai multe solut¸ii se va alege solut ia care maximizeaz˘ a sauminimizeaz˘ a o anumit a funct ie obiectiv .

O problem a poate rezolvat˘a prin tehnica (metoda) Greedy dac˘ aındeplinesteproprietatea: dac˘ a S este o solut ¸ie, iar S ′ este inclus aın S , atunci si S ′ este o solut ¸ie .

Pornind de la aceast˘ a condit ie, init ial se presupune c˘a S este mult imea vid asi se adaug˘a succesiv elemente din C ın S , ajung and la un optim local . Succesiuneade optimuri locale nu asigur a, ın general, optimul global . Daca se demonstreaz˘a casuccesiunea de optimuri locale conduce la optimul global , atunci metoda Greedyeste aplicabil˘a cu succes.

Exist a urm atoarele variante ale metodei Greedy:

1. Se pleaca de la solut ia vid a pentru multimea S si se ia pe r and c ate un

element din mult¸imea C . Daca elementul ales ındeplineste condit ia de optim local , el este introdus ın mult ¸imea S .

2. Se ordoneaz a elementele mult¸imii C si se verica dac a un elementındeplinestecondit ia de apartenent ¸a la mult imea S .

213

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 226/518

214 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

14.2 Algoritmi greedy

Algoritmii greedy sunt ın general simpli si sunt folosit ¸i la rezolvarea unorprobleme de optimizare. In cele mai multe situat ¸ii de acest fel avem:

• o multime de candidat i (lucr ari de executat, vˆarfuri ale grafului, etc.)

• o functie care veric a dac a o anumit a mult ime de candidat¸i constituie osolut ¸ie posibil˘ a , nu neap arat optim˘ a , a problemei

• o functie care veric a dac a o mult ime de candidat¸i este fezabil˘ a , adic a dac aeste posibil s a complet am aceast˘a mult ime astfel ıncˆat s a obtinem o solut ¸ieposibil˘ a , nu neap arat optim˘ a , a problemei

•o funct ie de select ie care indic a la orice moment care este cel mai promit ¸atordintre candidat ii ınc˘a nefolositi

• o funct ie obiectiv care d a valoarea unei solut¸ii (timpul necesar execut˘ ariituturor lucr˘ arilor ıntr-o anumit˘ a ordine, lungimea drumului pe care l-amgasit, etc) si pe care urm˘ arim s a o optimiz am (minimiz am/maximiz˘ am)

Pentru a rezolva problema de optimizare , caut am o solut ¸ie posibil˘ a care s aoptimizeze valoarea funct iei obiectiv .

Un algoritm greedy construieste solut ¸ia pas cu pas.Init ial, mult imea candidat ¸ilor selectat¸i este vid a.La ecare pas, ıncerc˘ am sa ad augam la aceast˘a mult ime pe cel mai promit ator

candidat, conform funct iei de select ie . Daca, dup a o astfel de ad augare, mult¸imeade candidat¸i selectat i nu mai este fezabil˘ a , eliminam ultimul candidat ad˘ augat;acesta nu va mai niciodat˘ a considerat. Dac˘a, dup a ad augare, mult¸imea decandidat i selectat i este fezabil˘ a , ultimul candidat ad˘ augat va r˘amane de acumıncolo ın ea. De ecare dat˘ a cand l argim mult imea candidat ¸ilor selectat¸i, veric amdaca aceast a mult ime constituie o solut ¸ie posibil˘ a a problemei. Dac˘a algoritmulgreedy funct ioneaz a corect, prima solut¸ie gasit a va considerat˘a solut ¸ie optim˘ a aproblemei.

Solut ¸ia optim˘ a nu este ın mod necesar unic˘ a: se poate ca funct ia obiectiv saaib a aceeasi valoare optim˘ a pentru mai multe solut ¸ii posibile .

Descrierea formal˘a a unui algoritm greedy general este:

function greedy (C ) // C este mult imea candidat ¸ilorS ← ∅ // S este mult imea ın care construim solut ¸ia

while not solutie (S ) and C =

dox ←un element din C care maximizeaz˘a/minimizeaz˘a select (x)C ←C − xif fezabil (S ∪x) then S ←S ∪xif solutie (S ) then return S

else return ”nu exist a solutie”

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 227/518

14.3. EXEMPLE 215

14.3 Exemple

Dintre problemele clasice care se pot rezolva prin metoda greedy ment ion am:plata restului cu num˘ ar minim de monezi, problema rucsacului, sortare prin select ¸ie,determinarea celor mai scurte drumuri care pleac˘ a din acelasi punct (algoritmul luiDijkstra), determinarea arborelui de cost minim (algoritmii lui Prim si Kruskal),determinarea mult ¸imii dominante, problema color˘ arii intervalelor, codicarea Huff-man, etc.

14.3.1 Problema continua a rucsacului

Se consider a n obiecte. Obiectul i are greutatea gi si valoarea vi (1 ≤ i ≤n).

O persoan a are un rucsac. Fie G greutatea maxim˘ a suportat˘a de rucsac. Persoanaın cauz˘a doreste s˘a pun a ın rucsac obiecte astfel ıncˆ at valoarea celor din rucsac s˘ ae cat mai mare. Se permite fract ¸ionarea obiectelor (valoarea p˘ art ii din obiectulfract ionat ind direct proport ¸ional a cu greutatea ei!).

Not am cu x i ∈[0, 1] partea din obiectul i care a fost pus a ın rucsac. Practic,trebuie s a maximiz am funct ia

f (x) =n

i =1

x i ci .

Pentru rezolvare vom folosi metoda greedy. O modalitate de a ajunge lasolut ia optim˘a este de a considera obiectele ın ordinea descresc˘ atoare a valorilorutilit˘at ilor lor date de raportul v i

gi(i = 1 ,...,n ) si de a le ınc˘arca ıntregi ın rucsac

pan a cand acesta se umple. Din aceast˘ a cauz a presupunem ın continuare c˘ a

v1

g1 ≥v2

g2 ≥ ... ≥vn

gn.

Vectorul x = ( x1 , x2 ,...,x n ) se numeste solut ¸ie posibil˘ a dac a

x i ∈[0, 1],∀i = 1 , 2,...,nni=1 x i gi ≤G

iar o solut ie posibil a este solut ¸ie optim˘ a dac a maximizeaz a funct ia f .Vom nota G p greutatea permis˘ a de a se ınc arca ın rucsac la un moment dat.

Conform strategiei greedy, procedura de rezolvare a problemei este urm˘ atoarea:procedure rucsac ()

G p ←Gfor i = 1 , n

if G p > g ithen G p ←G p −gi

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 228/518

216 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

elsex

i ←G p

gifor j = i + 1 , nx j ←0

Vectorul x are forma x = (1 ,..., 1, x i , 0,..., 0) cu x i ∈(0, 1] si 1 ≤ i ≤n.

Propozit ¸ia 1 Procedura rucsac () furnizeaz˘ a o solut ¸ie optim˘ a.

Demonstrat¸ia se g aseste, de exemplu, ın [25] la pagina 226.

14.3.2 Problema plasarii textelor pe o banda

Sa presupunem c˘a trebuie s a plas am n texte T 1 , T 2 ,...,T n , de lungimi dateL1 , L2 ,...,L n , pe o singur a band a sucient de lung˘a. Atunci c and este necesar˘acitirea unui text sunt citite toate textele situate ınaintea lui pe band˘ a.

Modalitatea de plasare a celor n texte pe band˘a corespunde unei permut˘ ari pa mult imii 1, 2,...,n , textele ind asezate pe band˘ a ın ordinea T p(1) T p(2) ...T p(n ) .

Intr-o astfel de aranjare a textelor pe band˘ a, timpul mediu de citire a unuitext este:

f ( p) =1n

n

k=1

k

i=1

L p( i )

Se doreste determinarea unei permut˘ ari care s a asigure o valoare minim˘ a atimpului mediu de citire. Rezolvarea problemei este foarte simpl˘ a:

• se sorteaz˘ a crescator textele ın funct ¸ie de lungimea lor si

•se plaseaz˘ a pe banda ın ordinea dat˘ a de sortare.

Urm atoarea propozit ¸ie ([25] pagina 99) ne permite s˘a m siguri c a ın acestmod ajungem la o plasare optim˘ a.

Propozit ¸ia 2 Dac˘ a L1 ≤L2 ≤ ... ≤Ln atunci plasarea textelor corespunz˘ atoarepermutarii identice este optim˘ a.

Demonstrat ie: Fie p = ( p1 , p2 ,...,p n ) o plasare optim˘a. Dac a exist a i < j cuL p( i ) ≥ L p( j ) atunci consider˘am permutarea p′ obtinut˘a din p prin permutareaelementelor de pe pozit¸iile i si j . Atunci

f ( p′) −f ( p) = ( n − j + 1)( L p( i ) −L p( j ) ) + ( n −i + 1)( L p( j ) −L p( i ) )

deci

f ( p′) −f ( p) = ( L p( j ) −L p( i ) )( j −i) ≤0.Cum p este o plasare optim˘a si f ( p′) ≤f ( p) rezult a ca f ( p′) = f ( p) deci si p′

este o plasare optim˘a. Aplic and de un num˘ar nit de ori acest rat ¸ionament, trecemde la o permutare optim˘ a la alt a permutare optim˘ a pan a ajungem la permutareaidentic a. Rezult a ca permutarea identic˘ a corespunde unei plas˘ari optime.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 229/518

14.3. EXEMPLE 217

14.3.3 Problema plasarii textelor pe m benzi

Sa presupunem c˘a trebuie s a plas am n texte T 1 , T 2 ,...,T n , de lungimi dateL1 , L2 ,...,L n , pe m benzi sucient de lungi. Atunci cˆ and este necesar˘a citirea unuitext sunt citite toate textele situate ınaintea lui pe banda respectiv˘ a.

Se doreste determinarea unei plas˘ ari a celor n texte pe cele m benzi care s aasigure o valoare minim˘ a a timpului mediu de citire. Rezolvarea problemei estefoarte simpl a:

• se sorteaz˘ a crescator textele ın funct ¸ie de lungimea lor si

• plasarea textelor pe benzi se face ın ordinea dat˘ a de sortare,ıncepand cu primul text (cu cea mai mica lungime) care seplaseaz˘ a pe prima banda, iar mai departe

• ecare text se plaseaza pe banda urmatoare celei pe care afost plasat textul anterior.

Presupunˆand c a L1 ≤L2 ≤ ... ≤Ln , se poate observa c˘a textul T i va plasatpe banda i − i−1

m ·m ın continuarea celor aate deja pe aceast˘ a band a iar dup atextul T i , pe aceeasi band˘a cu el, vor plasate textele i + m, i + 2 m, ..., deci ınc˘a

n −im texte (demonstrat ¸iile se pot consulta, de exemplu, ın [25]).

14.3.4 Maximizarea unei sume de produse

Se dau mult imile de numere ıntregi A =

a1 , a2 ,...,a n

si B =

b1 , b2 ,...,bm

,

unde n ≤ m. Sa se determine o submult ¸ime B ′ = x1 , x2 ,...,x n a lui B astfelınc at valoarea expresiei E = a1 ·x1 + a2 ·x2 + an ·xn sa e maxim a.

Vom sorta cresc˘ator elementele celor dou˘ a mult imi. Putem presupune acumca a1 ≤a2 ≤ ... ≤an si b1 ≤b2 ≤ ... ≤bm .

Daca toate elementele din A sunt pozitive vom lua xn = bm , xn −1 = bm −1 ,si asa mai departe.

Daca toate elementele din A sunt negative vom lua x1 = b1 , x2 = b2 , si asamai departe.

Daca primele n1 elemente din A sunt strict negative si ultimele n2 elementedin A sunt pozitive sau nule ( n1 + n2 = n) atunci vom lua x1 = b1 , x2 = b2 , ...,xn 1 = bn 1 si xn = bm , xn −1 = bm −1 , ..., xn −n 2 +1 = bm −n 2 +1 .

14.3.5 Problema stat ¸iilor

Se consider a o multime de numere naturale A = a1 , a2 ,...,a n care reprezint˘acoordonatele a n stat ii pe axa real˘a. Vom presupune a1 < a 2 < ... < a n . Sa se

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 230/518

218 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

determine o submult ¸ime cu num˘ar maxim de stat¸ii cu proprietatea c˘ a distant¸adintre dou˘a stat ii al aturate este cel putin d (o distant¸a dat a).

Rezolvarea problemei este urm˘ atoarea:

• se alege stat ia 1,

• se parcurge sirul stat ¸iilor si se alege prima stat ie ınt alnit a care estela distant¸a cel put in d fat a de stat ia aleas a anterior; se repet˘ a acestpas p an a cand s-au vericat toate stat ¸iile.

Propozit ¸ia 3 Exist˘ a o solut ¸ie optim˘ a care cont ine stat ia 1.

Demonstrat ie: Fie B = a i 1 , a i 2 ,...,a i m o solutie a problemei care nu cont ¸inestat ia 1 (deci a i 1 > a 1). Evident |a i 2 −a i 1 | ≥d. Stat ia i1 se poate ınlocui cu stat ¸ia1 pentru c a

|a i 2

−a1

|=

|a i 2

−a i 1 + a i 1

−a1

|=

|a i 2

−a i 1

|+

|a i 1

−a1

|> d .

Dup a selectarea stat ¸ie 1 se pot selecta (pentru obt ¸inerea unei solut¸ii optime)numai stat¸ii situate la distant ¸e cel put in d fat a de stat ia 1. Pentru aceste stat ¸iirepet am strategia sugerat˘ a de propozit ia anterioar˘ a.

14.3.6 Problema cutiilor

Se doreste obt¸inerea unei congurat ¸ii de n numere plasate pe n +1 pozit ii (opozitie ind liber a) dintr-o congurat ¸ie init ial a dat a ın care exist˘a o pozitie liber asi cele n numere plasate ın alt˘ a ordine. O mutare se poate face dintr-o anumit˘ apozitie numai ın pozit ¸ia liber a.

Prezent˘am algoritmul de rezolvare pe baza urm˘ atorului exemplu:1 2 3 4 5 6 7

initial → 3 1 2 6 5 4nal → 1 2 3 4 5 6

rezolvat → ×Vom proceda astfel: cutia goal˘ a din congurat¸ia init ial a se aa pe pozit ia 3

dar pe aceast˘a pozitie, ın congurat ¸ia nal a, se aa num arul 3; c aut am num arul 3din congurat¸ia init ial a (ıl g asim pe pozit ia 1) si ıl mut˘ am pe pozit ia cutiei goale;acum, cutia goal˘a se aa pe pozit ia 1; vom repeta acest rat ¸ionament pˆana candpozitiile cutiilor goale, ın cele dou˘ a congurat ii, coincid.

1 2 3 4 5 6 7modicat → 1 3 2 6 5 4

nal

→1 2 3 4 5 6

rezolvat → × ×1 2 3 4 5 6 7modicat → 1 3 2 6 5 4

nal → 1 2 3 4 5 6rezolvat → × ×

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 231/518

14.3. EXEMPLE 219

1 2 3 4 5 6 7modicat

→1 2 3 6 5 4

nal → 1 2 3 4 5 6rezolvat → × × × ×Acum vom c auta o cutie nerezolvat˘ a si vom muta num˘ arul din acea cutie ın

cutia goal a.1 2 3 4 5 6 7

modicat → 1 2 3 6 5 4nal → 1 2 3 4 5 6

rezolvat → × × × ×Repet am rat ionamentul prezentat la ınceput si vom continua pˆ ana cand toate

numerele ajung pe pozit¸iile din congurat¸ia nal a.1 2 3 4 5 6 7

modicat

→1 2 3 6 4 5

nal → 1 2 3 4 5 6rezolvat → × × × × ×

1 2 3 4 5 6 7modicat → 1 2 3 4 5 6

nal → 1 2 3 4 5 6rezolvat → × × × × × ×

14.3.7 Problema subsirurilor

Sa se descompun a un sir de n numere ıntregi ın subsiruri strict cresc˘ atoareastfel ıncˆat numerele lor de ordine din sirul init ¸ial s a e ordonate cresc˘ator ın

subsirurile formate si num˘ arul subsirurilor s˘ a e minim.Metota de rezolvare este urm˘ atoarea: se parcurg elementele sirului init ¸ial unuldup a altul si pentru ecare element x i se caut a un subsir existent la care x i sepoate ad˘auga la sf arsit; dac˘a nu exist a un astfel de subsir se creeaz˘ a un subsir noucare va cont ine ca prim element pe x i ; daca exist a mai multe subsiruri la care sepoate ad˘auga x i , se va alege acela care are cel mai mare ultim element.

Observat ie: Ultimele elemente din ecare subsir (care sunt si elemente maximedin aceste subsiruri) formeaz˘ a un sir descresc˘ator. Acest fapt permite utilizareacautarii binare pentru determinarea subsirului potrivit pentru elementul x iatunci c and prelucr˘am acest element.

14.3.8 Problema intervalelor disjuncte

Se consider a n intervale ınchise pe axa real˘ a [a1 , b1], [a2 , b2],..., [an , bn ]. Secere selectarea unor intervale disjuncte astfel ıncˆ at num arul acestora s˘a e maxim.

Metoda de rezolvare este urm˘ atoarea: se sorteaz˘ a intervalele cresc˘ator dup˘acapatul din dreapta; se selecteaz˘ a primul interval; se parcurg intervalele, unul

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 232/518

220 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

dup a altul, p an a se gaseste un interval [ a i , bi ] disjunct cu ultimul interval ales sise adaug a acest interval la solut ¸ie, el devenind astfel ”ultimul interval ales”; acestprocedeu continu˘a pan a cand nu mai r˘aman intervale de analizat.

Propozit ¸ia 4 Exist˘ a o solut ¸ie optim˘ a care cont ine primul interval dup˘ a sortare.

14.3.9 Problema alegerii taxelor

Se dau dou a siruri cu c ate 2n numere ıntregi ecare, x = ( x1 , x2 ,...,x 2n ) siy = ( y1 , y2 ,...,y 2n ) reprezentˆand taxe. S˘a se determine sirul z = ( z1 , z2 ,...,z 2n ),unde zi ∈ x i , yi(1 ≤ i ≤2n), astfel ıncˆat suma tuturor elementelor din sirul zsa e minima si acest sir s˘a contin a exact n elemente din sirul x si n elemente dinsirul y.

Metoda de rezolvare este urm˘ atoarea: se construieste sirul t = x −y (ın caret i = x i −yi ) si se sorteaz˘a crescator; se aleg din sirul x elementele corespunz˘atoareprimelor n elemente din sirul t sortat iar celelalte n elemente se iau din sirul y.

14.3.10 Problema acoperirii intervalelor

Se consider a n intervale ınchise [ a1 , b1], [a2 , b2], ..., [an , bn ]. Sa se determine omult ime cu num˘ar minim de alemente C = c1 , c2 ,...,c m care sa ”acopere” toatecele n intervale date (spunem c˘ a ci ”acoper a” intervalul [ ak , bk ] daca ci ∈[ak , bk ]).

Metoda de rezolvare este urm˘ atoarea: se sorteaz˘ a intervalele cresc˘ator dup˘acapatul din dreapta. Presupunem c˘ a b1 ≤ b2 ≤ ... ≤ bn . Primul punct ales estec1 = b1 . Parcurgem intervalele pˆ an a cand g asim un interval [ a i , bi ] cu a i > c 1 sialegem c2 = bi . Parcurgem mai departe intervalele pˆ an a cand g asim un interval[a j , bj ] cu a j > c 2 si alegem c3 = bj . Repet am acest procedeu pˆana cand termin˘amde parcurs toate intervalele.

14.3.11 Algoritmul lui Prim

Determinarea arborelui minim de acoperire pentru un graf neorientat.

Alg prim de ordinul O(n3)

import java.io.*; // arbore minim de acoperire: algoritmul lui Primclass Prim // O(n 3)

static final int oo=0x7fffffff;static int n,m;static int[][] cost;static boolean[] esteInArbore;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 233/518

14.3. EXEMPLE 221

static int[] p; // predecesor in arbore

public static void main(String[]args) throws IOException

int nods=3; // nod startint i, j, k, costArbore=0,min,imin=0,jmin=0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("prim.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("prim.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

cost=new int[n+1][n+1];esteInArbore=new boolean [n+1];p=new int[n+1];

for(i=1;i<=n;i++) for(j=1;j<=n;j++) cost[i][j]=oo;for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost[i][j]=cost[j][i]=(int)st.nval;

esteInArbore[nods]=true;for(k=1;k<=n-1;k++) // sunt exact n-1 muchii in arbore !!! O(n)

min=oo;for(i=1;i<=n;i++) // O(n)

if(!esteInArbore[i]) continue;for(j=1;j<=n;j++) // O(n)

if(esteInArbore[j]) continue;if(min>cost[i][j]) min=cost[i][j]; imin=i; jmin=j;

//for j//for i

esteInArbore[jmin]=true;p[jmin]=imin;costArbore+=min;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 234/518

222 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

//for k

for(k=1;k<=n;k++) if(p[k]!=0) out.println(k+" "+p[k]);out.println("cost="+costArbore);out.close();

//main//class

/*6 7 1 31 2 3 2 31 3 1 4 32 3 2 5 43 4 1 6 44 5 1 cost=75 6 34 6 2*/

Alg Prim cu distant ¸e

import java.io.*; // arbore minim de acoperire: algoritmul lui Primclass PrimDist // O(n^2)

static final int oo=0x7fffffff;static int n,m;

static int[][] cost;static boolean[] esteInArbore;static int[] p; // predecesor in arborestatic int[] d; // distante de la nod catre arbore

public static void main(String[]args) throws IOException

int nodStart=3; // nod startint i, j, k, costArbore=0,min,jmin=0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("prim.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("prim.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 235/518

14.3. EXEMPLE 223

cost=new int[n+1][n+1];esteInArbore=new boolean [n+1];p=new int[n+1];d=new int[n+1];

for(i=1;i<=n;i++)for(j=1;j<=n;j++)

cost[i][j]=oo;for(i=1;i<=n;i++) d[i]=oo;

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost[i][j]=cost[j][i]=(int)st.nval;

d[nodStart]=0;

for(k=1;k<=n;k++) // O(n)

min=oo;for(j=1;j<=n;j++) // O(n)

if(esteInArbore[j]) continue;if(min>d[j]) min=d[j]; jmin=j;

//for j

esteInArbore[jmin]=true;d[jmin]=0;costArbore+=min;

for(j=1;j<=n;j++) // actualizez distantele nodurilor O(n)

if(esteInArbore[j]) continue; // j este deja in arboreif(cost[jmin][j]<oo) // am muchia (jmin,j)if(d[jmin]+cost[jmin][j]<d[j])

d[j]=d[jmin]+cost[jmin][j];p[j]=jmin;

//for k

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 236/518

224 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

for(k=1;k<=n;k++) if(p[k]!=0) out.println(k+" "+p[k]);out.println("cost="+costArbore);out.close();

//main//class

/*6 7 1 31 2 3 2 31 3 1 4 32 3 2 5 43 4 1 6 44 5 1 cost=75 6 34 6 2*/

Alg Prim cu heap

import java.io.*; // arbore minim de acoperire: algoritmul lui Primclass PrimHeap // folosesc distantele catre arbore // pastrate in MinHeap ==> O(n log n) ==> OK !!!

static final int oo=0x7fffffff;static int n,m;static int[][] w; // matricea costurilorstatic int[] d; // distante de la nod catre arbore

static int[] p; // predecesorul nodului in arborestatic int[] hd; // hd[i]=distanta din pozitia i din heapstatic int[] hnod; // hnod[i]= nodul din pozitia i din heapstatic int[] pozh; // pozh[i]=pozitia din heap a nodului i

public static void main(String[]args) throws IOException

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("prim.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("prim.out")));

int i,j,k,cost,costa=0,nods;

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;st.nextToken(); nods=(int)st.nval;

w=new int[n+1][n+1];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 237/518

14.3. EXEMPLE 225

for(i=1;i<=n;i++) for(j=1;j<=n;j++) w[i][j]=oo;

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[j][i]=w[i][j]=cost;

prim(nods);

for(i=1;i<=n;i++) // afisez muchiile din arboreif(i!=nods) out.println(p[i]+" "+i);costa+=w[p[i]][i];

out.println("costa="+costa);out.close();

//main

static void prim(int nods)

int u,v,q,aux;

d=new int [n+1];p=new int [n+1];hd=new int[n+1];hnod=new int[n+1];

pozh=new int[n+1];

for(u=1;u<=n;u++)

hnod[u]=pozh[u]=u;hd[u]=d[u]=oo;p[u]=0;

q=n; // q = noduri nefinalizate = dimensiune heapd[nods]=0;hd[pozh[nods]]=0;

urcInHeap(pozh[nods]);while(q>0) // la fiecare pas adaug un varf in arbore

u=extragMin(q);if(u==-1) System.out.println("graf neconex !!!"); break;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 238/518

226 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

q--;for(v=1;v<=q;v++) // noduri nefinalizate = in heap 1..q

if(w[u][hnod[v]]<oo) // cost finit ==> exista arc (u,v)relax(u,hnod[v]); // relax si refac heap

//prim(...)

static void relax(int u,int v)

if(w[u][v]<d[v])

d[v]=w[u][v];p[v]=u;hd[pozh[v]]=d[v];urcInHeap(pozh[v]);

//relax(...)

static int extragMin(int q) // in heap 1..q

// returnez valoarea minima (din varf!) si refac heap in jos// aducand ultimul in varf si coborand !

int aux,fiu1,fiu2,fiu,tata,nod;

aux=hd[1]; hd[1]=hd[q]; hd[q]=aux; // 1 <---> q

aux=hnod[1]; hnod[1]=hnod[q]; hnod[q]=aux;

pozh[hnod[q]]=q;pozh[hnod[1]]=1;

tata=1;fiu1=2*tata;fiu2=2*tata+1;

while(fiu1<=q-1) //refac heap de sus in jos pana la q-1

fiu=fiu1;if(fiu2<=q-1)

if(hd[fiu2]<hd[fiu1])fiu=fiu2;

if(hd[tata]<=hd[fiu])

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 239/518

14.3. EXEMPLE 227

break;

pozh[hnod[fiu]]=tata;pozh[hnod[tata]]=fiu;

aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;

aux=hnod[fiu]; hnod[fiu]=hnod[tata]; hnod[tata]=aux;

tata=fiu;fiu1=2*tata;fiu2=2*tata+1;

return hnod[q]; // hnod[1] a ajuns deja (!) in hnod[q]// extragMin(...)

static void urcInHeap(int nodh)

int aux,fiu,tata,nod;

nod=hnod[nodh];fiu=nodh;tata=fiu/2;while((tata>0)&&(hd[fiu]<hd[tata]))

pozh[hnod[tata]]=fiu;hnod[fiu]=hnod[tata];

aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;

fiu=tata;tata=fiu/2;

pozh[nod]=fiu;hnod[fiu]=nod;

//class

/*6 7 31 2 3 3 11 3 1 3 2

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 240/518

228 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

2 3 2 3 43 4 1 4 54 5 1 4 65 6 3 costa=74 6 2*/

14.3.12 Algoritmul lui Kruskalimport java.io.*; // Arbore minim de acoperire : Kruskalclass Kruskal

static int n,m,cost=0;static int[] x,y,z,et;

public static void main(String[] args) throws IOException

int k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("kruskal.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("kruskal.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

x=new int[m+1];y=new int[m+1];z=new int[m+1];et=new int[n+1];

for(k=1;k<=m;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;st.nextToken(); z[k]=(int)st.nval;

kruskal();

System.out.println("cost="+cost);out.println(cost);out.close();

//main

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 241/518

14.3. EXEMPLE 229

static void kruskal()

int nm=0,k,etg1,etg2;

for(k=1;k<=n;k++) et[k]=k;

qsort(1,m,z);

for(k=1;k<=m;k++)

if(et[x[k]]!=et[y[k]])

nm++;cost+=z[k];System.out.println(x[k]+" "+y[k]);etg1=et[x[k]];etg2=et[y[k]];for(int i=1;i<=n;i++)

if(et[i]==etg2) et[i]=etg1;if(nm==n-1)break;

//kruskal

static void qsort(int p, int u, int []x)

int k=poz(p,u,x);if(p<k-1) qsort(p,k-1,x);if(k+1<u) qsort(k+1,u,x);

static void invers(int i, int j, int x[])

int aux;aux=x[i]; x[i]=x[j]; x[j]=aux;

static int poz(int p, int u, int z[])

int k,i,j;i=p; j=u;while(i<j)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 242/518

230 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

while((z[i]<=z[j])&&(i<j)) i++;while((z[i]<=z[j])&&(i<j)) j--;

if(i<j) invers(i,j,z); invers(i,j,x); invers(i,j,y); return i; //i==j

//poz//class

14.3.13 Algoritmul lui Dijkstra

Alg Dijkstra cu distant ¸e, ın graf neorientat

import java.io.*; // drumuri minime de la nodSursaclass Dijkstra // O(n^2)

static final int oo=0x7fffffff;static int n,m;static int[][] cost;static boolean[] esteFinalizat;static int[] p; // predecesor in drumstatic int[] d; // distante de la nod catre nodSursa

public static void main(String[]args) throws IOException

int nodSursa=1; // nod startint i, j, k, min,jmin=0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("dijkstraNeorientat.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("dijkstraNeorientat.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

cost=new int[n+1][n+1];esteFinalizat=new boolean [n+1];p=new int[n+1];d=new int[n+1];

for(i=1;i<=n;i++) for(j=1;j<=n;j++) cost[i][j]=oo;for(i=1;i<=n;i++) d[i]=oo;

for(k=1;k<=m;k++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 243/518

14.3. EXEMPLE 231

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost[i][j]=cost[j][i]=(int)st.nval;

d[nodSursa]=0;

for(k=1;k<=n;k++) // O(n)

min=oo;for(j=1;j<=n;j++) // O(n)

if(esteFinalizat[j]) continue;if(min>d[j]) min=d[j]; jmin=j;

//for jesteFinalizat[jmin]=true;for(j=1;j<=n;j++) // actualizez distantele nodurilor // O(n)

if(esteFinalizat[j]) continue; // j este deja in arboreif(cost[jmin][j]<oo) // am muchia (jmin,j)

if(d[jmin]+cost[jmin][j]<d[j])

d[j]=d[jmin]+cost[jmin][j];p[j]=jmin;

//for kfor(k=1;k<=n;k++)

System.out.print(nodSursa+"-->"+k+" dist="+d[k]+" drum: ");drum(k);System.out.println();

out.close();

//mainstatic void drum(int k) // s --> ... --> k

if(p[k]!=0) drum(p[k]);System.out.print(k+" ");

//class/*6 7 1-->1 dist=0 drum: 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 244/518

232 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

1 2 4 1-->2 dist=3 drum: 1 3 21 3 1 1-->3 dist=1 drum: 1 32 3 2 1-->4 dist=2 drum: 1 3 43 4 1 1-->5 dist=3 drum: 1 3 4 55 4 1 1-->6 dist=4 drum: 1 3 4 65 6 34 6 2*/

Alg Dijkstra cu heap, ın graf neorientat

import java.io.*; // distante minime de la nodSursaclass DijkstraNeorientatHeap // pastrate in MinHeap ==> O(n log n) ==> OK !!!

static final int oo=0x7fffffff;static int n,m;static int[][]w; // matricea costurilorstatic int[]d; // distante de la nod catre arborestatic int[]p; // predecesorul nodului in arborestatic int[] hd; // hd[i]=distanta din pozitia i din heapstatic int[] hnod; // hnod[i]= nodul din pozitia i din heapstatic int[] pozh; // pozh[i]=pozitia din heap a nodului i

public static void main(String[]args) throws IOException

int i,j,k,cost,costa=0,nodSursa;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("dijkstraNeorientat.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("dijkstraNeorientat.out")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;w=new int[n+1][n+1];for(i=1;i<=n;i++) for(j=1;j<=n;j++) w[i][j]=oo;for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[j][i]=w[i][j]=cost;

nodSursa=1;dijkstra(nodSursa);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 245/518

14.3. EXEMPLE 233

for(k=1;k<=n;k++)

System.out.print(nodSursa+"-->"+k+" dist="+d[k]+" drum: ");drum(k);System.out.println();

out.close();

//main

static void dijkstra(int nods)

int u,v,q,aux;

d=new int [n+1];p=new int [n+1];hd=new int[n+1];hnod=new int[n+1];pozh=new int[n+1];

for(u=1;u<=n;u++)

hnod[u]=pozh[u]=u;hd[u]=d[u]=oo;p[u]=0;

q=n; // q = noduri nefinalizate = dimensiune heapd[nods]=0;hd[pozh[nods]]=0;

urcInHeap(pozh[nods]);

while(q>0) // la fiecare pas adaug un varf in arbore

u=extragMin(q);if(u==-1) System.out.println("graf neconex !!!"); break; q--;for(v=1;v<=q;v++) // noduri nefinalizate = in heap 1..q

if(w[u][hnod[v]]<oo) // cost finit ==> exista arc (u,v)relax(u,hnod[v]); // relax si refac heap

// dijkstra()

static void relax(int u,int v)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 246/518

234 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

if(d[u]+w[u][v]<d[v])

d[v]=d[u]+w[u][v];p[v]=u;hd[pozh[v]]=d[v];urcInHeap(pozh[v]);

// relax(...)

static int extragMin(int q) // in heap 1..q

// returnez valoarea minima (din varf!) si refac heap in josint aux,fiu1,fiu2,fiu,tata,nod;

aux=hd[1]; hd[1]=hd[q]; hd[q]=aux; // 1 <---> qaux=hnod[1]; hnod[1]=hnod[q]; hnod[q]=aux;pozh[hnod[q]]=q;pozh[hnod[1]]=1;

tata=1;fiu1=2*tata;fiu2=2*tata+1;

while(fiu1<=q-1) //refac heap de sus in jos pana la q-1

fiu=fiu1;if(fiu2<=q-1)if(hd[fiu2]<hd[fiu1]) fiu=fiu2;

if(hd[tata]<=hd[fiu]) break;

pozh[hnod[fiu]]=tata;pozh[hnod[tata]]=fiu;

aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;aux=hnod[fiu]; hnod[fiu]=hnod[tata]; hnod[tata]=aux;

tata=fiu;fiu1=2*tata;fiu2=2*tata+1;

return hnod[q]; // hnod[1] a ajuns deja (!) in hnod[q] // extragMin(...)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 247/518

14.3. EXEMPLE 235

static void urcInHeap(int nodh)

int aux,fiu,tata,nod;

nod=hnod[nodh];fiu=nodh;tata=fiu/2;

while((tata>0)&&(hd[fiu]<hd[tata]))

pozh[hnod[tata]]=fiu;hnod[fiu]=hnod[tata];aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;fiu=tata;tata=fiu/2;

pozh[nod]=fiu;hnod[fiu]=nod;

// urcInHeap(...)

static void drum(int k) // s --> ... --> k

if(p[k]!=0) drum(p[k]);System.out.print(k+" ");

//class

/*6 7 1-->1 dist=0 drum: 11 2 4 1-->2 dist=3 drum: 1 3 21 3 1 1-->3 dist=1 drum: 1 32 3 2 1-->4 dist=2 drum: 1 3 43 4 1 1-->5 dist=3 drum: 1 3 4 55 4 1 1-->6 dist=4 drum: 1 3 4 65 6 34 6 2*/

Alg Dijkstra cu distant ¸e, ın graf orientat

import java.io.*; // drumuri minime de la nodSursaclass Dijkstra // O(n^2)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 248/518

236 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

static final int oo=0x7fffffff;static int n,m;static int[][] cost;static boolean[] esteFinalizat;static int[] p; // predecesor in drumstatic int[] d; // distante de la nod catre nodSursa

public static void main(String[]args) throws IOException

int nodSursa=1; // nod startint i, j, k, min,jmin=0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("dijkstraOrientat.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("dijkstraOrientat.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

cost=new int[n+1][n+1];esteFinalizat=new boolean [n+1];p=new int[n+1];d=new int[n+1];

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)cost[i][j]=oo;for(i=1;i<=n;i++) d[i]=oo;

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost[i][j]=(int)st.nval;

d[nodSursa]=0;

for(k=1;k<=n;k++) // O(n)

min=oo;for(j=1;j<=n;j++) // O(n)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 249/518

14.3. EXEMPLE 237

if(esteFinalizat[j]) continue;if(min>d[j]) min=d[j]; jmin=j;

//for jesteFinalizat[jmin]=true;for(j=1;j<=n;j++) // actualizez distantele nodurilor // O(n)

if(esteFinalizat[j]) continue; // j este deja in arboreif(cost[jmin][j]<oo) // am muchia (jmin,j)

if(d[jmin]+cost[jmin][j]<d[j])

d[j]=d[jmin]+cost[jmin][j];p[j]=jmin;

//for kfor(k=1;k<=n;k++)

System.out.print(nodSursa+"-->"+k+" dist="+d[k]+" drum: ");if(d[k]<oo) drum(k); else System.out.print("Nu exista drum!");System.out.println();

out.close();

//main

static void drum(int k) // s --> ... --> k

if(p[k]!=0) drum(p[k]);System.out.print(k+" ");

//class/*6 7 1-->1 dist=0 drum: 11 2 4 1-->2 dist=4 drum: 1 21 3 1 1-->3 dist=1 drum: 1 32 3 2 1-->4 dist=2 drum: 1 3 43 4 1 1-->5 dist=2147483647 drum: Nu exista drum!5 4 1 1-->6 dist=4 drum: 1 3 4 65 6 34 6 2 */

Alg Dijkstra cu heap, ın graf orientat

import java.io.*; // distante minime de la nodSursaclass DijkstraOrientatHeap // pastrate in MinHeap ==> O(n log n) ==> OK !!!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 250/518

238 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

static final int oo=0x7fffffff;static int n,m;

static int[][]w; // matricea costurilorstatic int[]d; // distante de la nod catre arborestatic int[]p; // predecesorul nodului in arbore

static int[] hd; // hd[i]=distanta din pozitia i din heapstatic int[] hnod; // hnod[i]= nodul din pozitia i din heapstatic int[] pozh; // pozh[i]=pozitia din heap a nodului i

public static void main(String[]args) throws IOException

int i,j,k,cost,costa=0,nodSursa;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("dijkstraOrientat.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("dijkstraOrientat.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

w=new int[n+1][n+1];

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)w[i][j]=oo;

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[i][j]=cost;

nodSursa=1;dijkstra(nodSursa);

for(k=1;k<=n;k++)

if(d[k]<oo)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 251/518

14.3. EXEMPLE 239

System.out.print(nodSursa+"-->"+k+" dist="+d[k]+" drum: ");drum(k);

else System.out.print(nodSursa+"-->"+k+" Nu exista drum! ");System.out.println();

out.close();//main

static void dijkstra(int nods)

int u,v,q,aux;

d=new int [n+1];p=new int [n+1];hd=new int[n+1];hnod=new int[n+1];pozh=new int[n+1];

for(u=1;u<=n;u++) hnod[u]=pozh[u]=u; hd[u]=d[u]=oo; p[u]=0; q=n; // q = noduri nefinalizate = dimensiune heapd[nods]=0;hd[pozh[nods]]=0;

urcInHeap(pozh[nods]);

while(q>0) // la fiecare pas adaug un varf in arbore

u=extragMin(q);

if(u==-1) System.out.println("graf neconex !!!"); break;

q--;for(v=1;v<=q;v++) // noduri nefinalizate = in heap 1..q

if(w[u][hnod[v]]<oo) // cost finit ==> exista arc (u,v)relax(u,hnod[v]); // relax si refac heap

//dijkstra(...)

static void relax(int u,int v)

if(d[u]+w[u][v]<d[v])

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 252/518

240 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

d[v]=d[u]+w[u][v];p[v]=u;hd[pozh[v]]=d[v];urcInHeap(pozh[v]);

// relax(...)

static int extragMin(int q) // in heap 1..q

// returnez valoarea minima (din varf!) si refac heap in josint aux,fiu1,fiu2,fiu,tata,nod;

aux=hd[1]; hd[1]=hd[q]; hd[q]=aux; // 1 <---> qaux=hnod[1]; hnod[1]=hnod[q]; hnod[q]=aux;pozh[hnod[q]]=q;pozh[hnod[1]]=1;

tata=1;fiu1=2*tata;fiu2=2*tata+1;while(fiu1<=q-1) //refac heap de sus in jos pana la q-1

fiu=fiu1;if(fiu2<=q-1)

if(hd[fiu2]<hd[fiu1]) fiu=fiu2;

if(hd[tata]<=hd[fiu]) break;

pozh[hnod[fiu]]=tata;pozh[hnod[tata]]=fiu;aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;aux=hnod[fiu]; hnod[fiu]=hnod[tata]; hnod[tata]=aux;

tata=fiu;fiu1=2*tata;fiu2=2*tata+1;

return hnod[q]; // hnod[1] a ajuns deja (!) in hnod[q] // extragMin(...)

static void urcInHeap(int nodh)

int aux,fiu,tata,nod;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 253/518

14.3. EXEMPLE 241

nod=hnod[nodh];fiu=nodh;tata=fiu/2;while((tata>0)&&(hd[fiu]<hd[tata]))

pozh[hnod[tata]]=fiu;hnod[fiu]=hnod[tata];

aux=hd[fiu]; hd[fiu]=hd[tata]; hd[tata]=aux;

fiu=tata;tata=fiu/2;

pozh[nod]=fiu;hnod[fiu]=nod;

// urcInHeap(...)

static void drum(int k) // s --> ... --> k

if(p[k]!=0) drum(p[k]);System.out.print(k+" ");

//class

/*6 7 1-->1 dist=0 drum: 11 2 4 1-->2 dist=4 drum: 1 21 3 1 1-->3 dist=1 drum: 1 32 3 2 1-->4 dist=2 drum: 1 3 43 4 1 1-->5 Nu exista drum!5 4 1 1-->6 dist=4 drum: 1 3 4 65 6 34 6 2*/

14.3.14 Urgent ¸a - OJI2002 cls 11

Autorit˘at ile dintr-o zon˘a de munte intent ¸ioneaz˘a sa stabileasc˘a un plan deurgent a pentru a react ¸iona mai ecient la frecventele calamit˘ ati naturale din zon˘ a.In acest scop au identicat N puncte de interes strategic si le-au numerotat distinctde la 1 la N . Punctele de interes strategic sunt conectate prin M cai de acces av and

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 254/518

242 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

priorit ati ın funct¸ie de important ¸a. Intre oricare dou˘a puncte de interes strategicexist a cel mult o cale de acces ce poate parcurs˘ a ın ambele sensuri si cel put ¸inun drum (format din una sau mai multe c˘ ai de acces) ce le conecteaz a.

In cazul unei calamit˘at i unele c ai de acces pot temporar ıntrerupte si astfelıntre anumite puncte de interes nu mai exist˘ a legatur a. Ca urmare pot rezulta maimulte grupuri de puncte ın asa fel ıncˆ at ıntre oricare dou˘ a puncte din acelasi grupsa existe m acar un drum si ıntre oricare dou˘ a puncte din grupuri diferite s˘ a nuexiste drum.

Autorit˘atile estimeaz˘a gravitatea unei calamit˘ at i ca ind suma priorit˘ atilorcailor de acces distruse de aceasta si doresc s˘ a determine un scenariu de gravitatemaxim a, ın care punctele de interes strategic s˘ a e ımp˘art ite ıntr-un num˘ ar de K grupuri.

Date de intrareFisierul de intrare URGENTA.IN are urm˘ atorul format:N M K i1 j 1 p1 - ıntre punctele i1 si j 1 exist a o cale de acces de prioritate p1

i2 j 2 p2 - ıntre punctele i2 si j 2 exist a o cale de acces de prioritate p2

...iM j M pM - ıntre punctele iM si j M exist a o cale de acces de prioritate pM

Date de iesireFisierul de iesire URGENTA.OUT va avea urm˘ atorul format:

gravmax - gravitatea maxim˘ aC - numarul de c ai de acces ıntrerupte de calamitatek1 h1 - ıntre punctele k1 si h1 a fost ıntrerupt˘ a calea de accesk2 h2 - ıntre punctele k2 si h2 a fost ıntrerupt˘ a calea de acces...kC hC - ıntre punctele kC si hC a fost ıntrerupt˘ a calea de acces

Restrict ii si precizari0 < N < 256N −2 < M < 323850 < K < N + 1

Priorit˘atile cailor de acces sunt ıntregi strict pozitivi mai mici decˆ at 256.Un grup de puncte poate cont ine ıntre 1 si N puncte inclusiv.Daca exist a mai multe solut¸ii, programul va determina una singur˘ a.

Exemplu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 255/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 256/518

244 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

cost=new int[n+1][n+1];esteInArbore=new boolean [n+1];p=new int[n+1];d=new int[n+1];a1=new int[n];a2=new int[n];ac=new int[n];

for(i=1;i<=n;i++) for(j=1;j<=n;j++) cost[i][j]=oo;for(i=1;i<=n;i++) d[i]=oo;

costmax=0;for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost[i][j]=cost[j][i]=(int)st.nval;costmax+=cost[i][j];

// alg Primd[nodStart]=0;

for(k=1;k<=n;k++) // O(n)

min=oo;for(j=1;j<=n;j++) // O(n)

if(esteInArbore[j]) continue;if(min>d[j]) min=d[j]; jmin=j;

//for j

esteInArbore[jmin]=true;d[jmin]=0;costArbore+=min;

for(j=1;j<=n;j++) // actualizez distantele nodurilor // O(n)

if(esteInArbore[j]) continue; // j este deja in arboreif(cost[jmin][j]<oo) // am muchia (jmin,j)

if(d[jmin]+cost[jmin][j]<d[j])

d[j]=d[jmin]+cost[jmin][j];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 257/518

14.3. EXEMPLE 245

p[j]=jmin;

//for k

k=0;for(i=1;i<=n;i++)

if(p[i]!=0)

//System.out.println(i+" "+p[i]+" --> "+cost[i][p[i]]);k++;a1[k]=i;a2[k]=p[i];ac[k]=cost[i][p[i]];

//System.out.println("cost="+costArbore);

gravmax=costmax-costArbore; // deocamdata, ...

//System.out.println("gravmax ="+gravmax);

// trebuie sa adaug la gravmax primele ncc-1 costuri mari (sort!)// din arborele minim de acoperire

// sortez descrescator ac (pastrand corect a1 si a2)// care are n-1 elemente

for(k=1;k<=n-1;k++) // de n-1 ori (bule)for(i=1;i<=n-2;i++)

if(ac[i]<ac[i+1])

aux=ac[i]; ac[i]=ac[i+1]; ac[i+1]=aux;aux=a1[i]; a1[i]=a1[i+1]; a1[i+1]=aux;aux=a2[i]; a2[i]=a2[i+1]; a2[i+1]=aux;

// primele ncc-1 ...for(i=1;i<=ncc-1;i++) gravmax+=ac[i];

// sterg muchiile ramase in arbore ...for(i=ncc;i<=n-1;i++)

cost[a1[i]][a2[i]]=cost[a2[i]][a1[i]]=oo; //sterg

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 258/518

246 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

out.println(gravmax);

// determin numarul muchiilor ...nrm=0;for(i=1;i<=n-1;i++)

for(j=i+1;j<=n;j++)if(cost[i][j] < oo)

nrm++;out.println(nrm);

// afisez muchiile ...for(i=1;i<=n-1;i++)

for(j=i+1;j<=n;j++)if(cost[i][j] < oo)

out.println(i+" "+j);

out.close();//main

//class

14.3.15 Reactivi - OJI2004 cls 9

Intr-un laborator de analize chimice se utilizeaz˘ a N reactivi.

Se stie c a, pentru a evita accidentele sau deprecierea reactivilor, acestia tre-buie sa e stocat i ın condit ¸ii de mediu speciale. Mai exact, pentru ecare reactiv x,se precizeaz a intervalul de temperatur˘ a [min x ,max x ]ın care trebuie s˘a se ıncadrezetemperatura de stocare a acestuia.

Reactivii vor plasat¸i ın frigidere.Orice frigider are un dispozitiv cu ajutorul c˘ aruia putem stabili temperatura

(constant˘a) care va ın interiorul acelui frigider (exprimat˘ a ıntr-un num˘ ar ıntregde grade Celsius).

Cerint ¸aScriet i un program care s˘a determine num˘arul minim de frigidere necesare

pentru stocarea reactivilor chimici.

Date de intrareFisierul de intrare react.in contine:

−pe prima linie num˘arul natural N , care reprezint˘a num arul de reactivi;

−pe ecare dintre urm˘ atoarele N linii se aa min max (dou a numere ıntregiseparate printr-un spat ¸iu); numerele de pe linia x + 1 reprezint a temperaturaminim a, respectiv temperatura maxim˘ a de stocare a reactivului x.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 259/518

14.3. EXEMPLE 247

Date de iesireFisierul de iesire react.out va cont ine o singur a linie pe care este scris

num arul minim de frigidere necesar.

Restrict ii si precizari

• 1 ≤N ≤8000

• −100 ≤min x ≤max x ≤100 (numere ıntregi, reprezentˆ and grade Celsius),pentru orice x de la 1 la N

• un frigider poate cont¸ine un num˘ar nelimitat de reactivi

Exemplereact.in react.out react.in react.out react.in react.out3 2 4 3 5 2-10 10 2 5 -10 10

- 2 5 5 7 10 1220 50 10 20 -20 10

30 40 7 107 8

Timp maxim de execut ¸ie: 1 secund a/test

Indicat ¸ii de rezolvare - descriere solut ¸ie *

Solut ¸ie prezentat˘ a de Mihai Stroe, GInfo nr. 14/4Problema se poate rezolva prin metoda greedy .O variant˘a mai explicit a a enunt ului este urm˘atoarea:”Se consider˘ a N intervale pe o ax˘ a. S˘ a se aleag˘ a un num˘ ar minim de puncteastfel ıncˆat ecare interval s˘ a cont in˘ a cel put ¸in unul dintre punctele alese.”Facem o prim˘a observat ie: pentru orice solut ¸ie optim˘a exist a o solutie cu

acelasi num˘ar de puncte (frigidere), ın care ecare punct s˘ a e sfarsitul unui in-terval. Aceasta se poate obt ¸ine mutˆand ecare punct spre dreapta, pˆ an a cand arajunge la sf arsitul intervalului care se termin˘ a cel mai repede, dintre intervalelecare ıl cont¸in. Se observ a ca noua solut ie respect˘a restrict iile din enunt¸.

In continuare ne vom concentra pe g˘ asirea unei solut ii de acest tip.Sort am reactivii dup˘a sfarsitul intervalului. Pentru intervalul care se termin˘ a

cel mai repede, alegem ultimul punct al s˘ au ca temperatur˘ a a unui frigider. Seobserv a ca aceast a alegere este cea mai bun˘a, dintre toate alegerile unui punctın intervalul respectiv, ın sensul c˘ a mult imea intervalelor care cont ¸in punctul estemai mare (conform relat ¸iei de incluziune), decˆat mult imea corespunz˘atoare oric˘areialte alegeri. Acest fapt este adev˘ arat, deoarece mutarea punctului mai la stˆ anganu duce la selectarea unor noi intervale.

Intervalele care cont¸in punctul respectiv sunt eliminate (reactivii corespunz˘ atoripot plasat iıntr-un frigider), iar procesul continu˘ a cu intervalele r˘amase,ın acelasi

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 260/518

248 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

mod.

Analiza complexit˘ at iiNot am cu D num arul de temperaturi ıntregi din intervalul care cont ¸ine tem-

peraturile din enunt ¸. Se observ a ca D este cel mult 201.Citirea datelor de intrare are ordinul de complexitate O(N ).Sortarea intervalelor dup˘ a cap atul din dreapta are ordinul de complexitate

O(N ·logN ).Urmeaz a F pasi, unde F este num arul de frigidere selectate. Deoarece ecare

frigider este setat la o temperatur˘ a ıntreag˘ a, F ≤D .In cadrul unui pas, determinarea intervalului care se termin˘ a cel mai repede,

pe baza vectorului sortat, are ordinul de complexitate O(1). Eliminarea intervalelorcare cont in un anumit punct (sfˆ arsitul intervalului care se termin˘ a cel mai repede)are ordinul de complexitate O(N ).

Asarea rezultatului are ordinul de complexitate O(1).In concluzie, ordinul de complexitate al algoritmului de rezolvare a acesteiprobleme este O(N ·D + N · logN ); deoarece ın general D > logN , consider amordinul de complexitate ca ind O(N ·D ).

Codul sursa

import java.io.*;class Reactivi

static int n; // n=nr reactivi

static int ni=0; // ni=nr interschimbari in quickSortstatic int nf=0; // n=nr frigiderestatic int[] ngf; // ng=nr grade in frigiderstatic int[] x1,x2; // limite inferioara/superioara

public static void main(String[] args) throws IOException

int i,j;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("Reactivi.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("Reactivi.out")));st.nextToken(); n=(int)st.nval;x1=new int[n+1];x2=new int[n+1];ngf=new int[n+1];for(i=1;i<=n;i++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 261/518

14.3. EXEMPLE 249

st.nextToken(); x1[i]=(int)st.nval;st.nextToken(); x2[i]=(int)st.nval;

sol();out.println(nf);out.close();

// main

static void sol()

int i;quickSort(1,n);i=1; nf=1; ngf[nf]=x2[i];i++;while(i<n)

while((i<=n)&&(x1[i]<=ngf[nf])) i++;if(i<n) ngf[++nf]=x2[i++];

static void quickSort(int p, int u)

int i,j,aux;i=p; j=u;while(i<j)

while((i<j)&&((x2[i]<x2[j])||((x2[i]==x2[j])&&(x1[i]>=x1[j])))) i++;

if(i!=j)

aux=x1[i]; x1[i]=x1[j]; x1[j]=aux;aux=x2[i]; x2[i]=x2[j]; x2[j]=aux;

while((i<j)&&((x2[i]<x2[j])||

((x2[i]==x2[j])&&(x1[i]>=x1[j])))) j--;if(i!=j)

aux=x1[i]; x1[i]=x1[j]; x1[j]=aux;aux=x2[i]; x2[i]=x2[j]; x2[j]=aux;

if(p<i-1) quickSort(p,i-1);if(i+1<u) quickSort(i+1,u);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 262/518

250 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

14.3.16 Pal - ONI2005 cls 9

Autor: Silviu G˘ anceanu Print ul Algorel este ın ıncurc˘ atur˘a din nou: a fost prins de Spˆanul cel

Negru ın ıncercarea sa de a o salva pe print ¸es a si acum este ınchis ın Turnul celMare.

Algorel poate evada dac˘ a gaseste combinat ¸ia magic a cu care poate deschidepoarta turnului.

Print ul stie cum se formeaz˘a aceast a combinat ie magic a: trebuie s a utilizezetoate cifrele scrise pe usa turnului pentru a obt ¸ine dou a numere palindroame,astfel ıncˆat suma lor s a e minima, iar aceast˘a sum a este combinat¸ia magic a ce vadeschide usa.

Primul num˘ar palindrom trebuie s˘ a aib a cel put in L cifre, iar cel de-al doileapoate avea orice lungime diferit˘ a de 0. Numerele palindroame formate nu potıncepe cu cifra 0. Acum intervenit ¸i dumneavoastr˘ a ın poveste, ind prietenul s˘ aucel mai priceput ın algoritmi.

Prin noul super-telefon al s˘ au, print ul transmite num˘ arul de aparit¸ii a ecareicifre de pe usa turnului precum si lungimea minim˘ a L a primului num˘ar, iardumneavoastr˘a trebuie s a-i trimitet¸i cat mai repede numerele cu care poate obt ¸inecombinat ia magic a.

Cerint ¸aAv and datele necesare, aat ¸i dou a numere palindroame cu care se poate

obtine combinat¸ia magic a.Date de intrarePrima linie a sierului pal.in contine un num˘ar ıntreg L reprezentˆand lun-

gimea minim a a primului num˘ar. Urmeaz˘a 10 linii: pe linia i + 2 se va aa unnum ar ıntreg reprezentˆ and num arul de aparit¸ii ale cifrei i, pentru i cu valori de la0 la 9.

Date de iesirePrima linie a sierului de iesire pal.out contine primul num˘ar palidrom, iar

cea de-a doua linie cont ine cel de-al doilea num˘ar palindrom. Dac˘ a exist a maimulte solut ii se va scrie doar una dintre ele.

Restrict ii si precizari

• In total vor cel mult 100 de cifre• 1 ≤L < 100 si L va mai mic dec at num arul total de cifre

• Pentru datele de test va exista ıntotdeauna solut ¸ie: se vor putea forma dincifrele scrise pe usa turnului dou˘ a numere care ıncep cu o cifr˘a diferit a de 0, iarprimul num˘ar s a aib a cel put in L cifre

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 263/518

14.3. EXEMPLE 251

• Un num ar este palindrom dac˘ a el coincide cu r asturnatul s˘ au. De exemplu12321 si 7007 sunt numere palindroame, ın timp ce 109 si 35672 nu sunt.

• Pentru 30% dintre teste, num˘ arul total de cifre va cel mult 7; pentru alte40% din teste num˘arul total de cifre va cel mult 18, iar pentru restul de 30% dinteste num˘arul total de cifre va mai mare sau egal cu 30.

• Fiecare linie din sierul de intrare si din sierul de iesire se termin˘ a cumarcaj de sf arsit de linie.

Exemplupal.in pal.out Explicat ie5 10001 Pentru acest exemplu avem L = 5,3 222 3 cifre de 0, 2 cifre de 1si 3 cifre de 2.2 Cifrele de la 3 la 9 lipsesc3 de pe usa turnului.

00 Cele doua palindroame cu care0 se genereaza combinat ia magic a0 sunt 10001 si 222.0 Combinat ia magic a va suma acestora0 si anume 10223 (care este suma minim˘ a0 pe care o putem obt ine).

Timp maxim de execut ¸ie/test: 1 sec sub Windows si 1 sec sub Linux

Indicat ¸ii de rezolvare - descriere solut ¸ie

Solut ¸ia ocial˘ a, Silviu G˘ anceanu Problema se rezolv˘a utiliz and tehnica greedy. Not˘ am num arul total de cifrecu NC . Se observ a ca, pentru ca suma celor dou˘ a numere palindroame s˘ a eminim a, trebuie ca lungimea maxim˘ a a celor dou a numere s a e cat mai mic a.Asadar, pentru ınceput, se stabileste lungimea exact˘ a a primului num˘ar (care va cel mai lung), ın funct¸ie de L ın modul urm˘ ator:

1. dac a L < NC/ 2, atunci lungimea primului palindrom va aleas˘ a astfelınc at cele dou a numere s a e cat mai apropiate ca lungime

2. dac a L > = NC/ 2 apar cazuri particulare si se stabileste dac˘ a lungimeaprimului palindrom creste sau nu cu o unitate.

Av and lungimile numerelor stabilite putem merge mai departe utilzˆ and strate-gia greedy, observˆand c a cifrele mai mici trebuie s˘a ocupe pozit ii cat mai semni-cative. Pentru a realiza acest lucru se vor completa ın paralel cele dou˘ a numerecu cifrele parcurse ın ordine cresc˘ atoare stabilind ın care din cele dou˘ a numerese vor pozit iona. De asemenea, trebuie avut ın vedere ca niciunul din cele dou˘ anumere s a nu ınceap˘a cu cifra 0.

Datele de test au fost construite astfel ıncˆ at si solut ii neoptime s˘a obtin apuncte, gradat, ın funct ¸ie de optimiz˘arile efectuate asupra implement˘ arii.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 264/518

252 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

Codul sursa

import java.io.*; // la inceput cifre mici in p1class Pal // apoi in ambele in paralel!

static int L;static int NC=0;static int nc1,nc2;static int ncfi=0; // nr cifre cu frecventa imparastatic int[] fc=new int[10]; // frecventa cifrelorstatic int[] p1; // palindromul 1static int[] p2; // palindromul 2

public static void main(String []args) throws IOException

int i;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("pal.in")));PrintWriter out = new PrintWriter (

new BufferedWriter( new FileWriter("pal.out")));

st.nextToken();L=(int)st.nval;for(i=0;i<=9;i++) st.nextToken(); fc[i]=(int)st.nval;

for(i=0;i<=9;i++) NC+=fc[i]; // nr total cifre

for(i=0;i<=9;i++) ncfi=ncfi+(fc[i]%2); // nr cifre cu frecventa impara

nc1=L;nc2=NC-nc1;while(nc1<nc2) nc1++; nc2--;if((ncfi==2)&&(nc1%2==0)) nc1++; nc2--;

p1=new int[nc1];p2=new int[nc2];switch(ncfi)

case 0: impare0(); break;case 1: impare1(); break;case 2: impare2(); break;default: System.out.println("Date de intrare eronate!");

corectez(p1);corectez(p2);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 265/518

14.3. EXEMPLE 253

for(i=0;i<p1.length;i++) out.print(p1[i]);out.println();for(i=0;i<p2.length;i++) out.print(p2[i]);out.println();int[] p12=suma(p1,p2);// pentru ca in teste rezultat = suma!for(i=p12.length-1;i>=0;i--) out.print(p12[i]);out.println();out.close();

//main

static void impare0() // cea mai mare cifra la mijloc

int i,k1,k2;int imp1=nc1/2, imp2=nc2/2;

if(nc1%2==1) // numai daca nc1 si nc2 sunt impare !for(i=9;i>=0;i--)

if(fc[i]>0)

p1[imp1]=i; fc[i]--;p2[imp2]=i; fc[i]--;break;

k1=0;k2=0;

while(k1<nc1-nc2) incarcPozitia(k1,p1); k1++;// incarc numai p1while((k1<imp1)||(k2<imp2))

if(k1<imp1) incarcPozitia(k1,p1); k1++;if(k2<imp2) incarcPozitia(k2,p2); k2++;

static void impare1()

int i,k1,k2;int imp1=nc1/2, imp2=nc2/2;

for(i=0;i<=9;i++)if(fc[i]%2==1) p1[imp1]=i; fc[i]--; break;

for(i=0;i<=9;i++)if(fc[i]%2==1) p2[imp2]=i; fc[i]--; break;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 266/518

254 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

k1=0;k2=0;while(k1<nc1-nc2) incarcPozitia(k1,p1); k1++; // incarc numai p1while((k1<imp1)||(k2<imp2))

if(k1<imp1) incarcPozitia(k1,p1); k1++;if(k2<imp2) incarcPozitia(k2,p2); k2++;

static void impare2()

int i,k1,k2;int imp1=nc1/2, imp2=nc2/2;

for(i=0;i<=9;i++)if(fc[i]%2==1) p1[imp1]=i; fc[i]--; break;

for(i=0;i<=9;i++)if(fc[i]%2==1) p2[imp2]=i; fc[i]--; break;

k1=0;k2=0;while(k1<nc1-nc2) incarcPozitia(k1,p1); k1++;// incarc numai p1while((k1<imp1)||(k2<imp2))

if(k1<imp1) incarcPozitia(k1,p1); k1++;

if(k2<imp2) incarcPozitia(k2,p2); k2++;

static void corectez(int[] x)

int pozdif0,val, n=x.length;pozdif0=0;while(x[pozdif0]==0) pozdif0++;if(pozdif0>0)

val=x[pozdif0];x[0]=x[n-1]=val;x[pozdif0]=x[n-pozdif0-1]=0;

static void incarcPozitia(int k, int[] x)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 267/518

14.3. EXEMPLE 255

int i;int n=x.length;for(i=0;i<=9;i++)

if(fc[i]>0)

x[k]=i; fc[i]--;x[n-k-1]=i; fc[i]--;break;

static int[] suma(int[] x, int[] y)

int[] z=new int[(x.length>y.length) ? (x.length+1) : (y.length+1)];int k,t=0;for(k=0;k<=z.length-2;k++)

z[k]=t;if(k<x.length) z[k]+=x[k];if(k<y.length) z[k]+=y[k];t=z[k]/10;z[k]=z[k]%10;

z[z.length-1]=t;if(z[z.length-1]!=0) return z;

elseint[] zz=new int[z.length-1];for(k=0;k<zz.length;k++) zz[k]=z[k];return zz;

//class

14.3.17 Sant ¸ - ONI2006 cls 9

Cei n detinut i ai unei ınchisori, numerotat ¸i de la 1 la n, trebuie s a sape unsant dispus ın linie dreapt˘ a ıntre dou˘ a puncte A si B , situate la distant ¸a de 250km unul de cel alalt, pe care exist˘a 251 borne kilometrice numerotate de la 0 la250. Fiecare det inut are ıns˘ a o pretent ie, ”e doar democrat ¸ie, nu?”: el doreste s˘ asape doar undeva ın zona dintre borna x si borna y. Pe l anga aceste pretent ¸iiınchisoarea se confrunt˘ a si cu o alt a problem a: nu are sucient i paznici angajat ¸i.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 268/518

256 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

Cerint ¸a

Cunosc andu-se num˘arul n de detinut i si pretent ¸iile lor, s a se determine locul(locurile) unde vor pusi det ¸inut ii s a sape ıntr-o zi de munc a, respect andu-sepretent¸iile lor, astfel ıncˆ at num arul de paznici necesari pentru a p˘ azi cei n detinut isa e minim. Intervalul ın care poate p˘ azi un paznic nu poate cont ¸ine dou a saumai multe zone disjuncte dintre cele exprimate de det ¸inut i ın preferint ¸ele lor.

Date de intrareFisierul de intrare sant.in are pe prima linie num˘arul n de detinut i. Pe ecare

dintre urm˘atoarele n linii exist a cate dou a numere naturale, a i bi , separate printr-un spat iu ( a i ≤bi ), care reprezint˘a pretent¸ia det inutului. Mai exact pe linia i + 1(1 ≤ i ≤n) este descris a pretent¸ia det inutului cu num˘ arul de ordine i.

Date de iesire

Fisierul de iesire sant.out va cont ine pe prima linie num˘arul natural kreprezentˆand num arul minim de paznici necesari pentru paza celor n detinut i scosila lucru. Pe urm˘atoarele 2 k linii vor descrise locurile unde vor pusi s˘a sapedetinut ii, astfel: ecare pereche de linii (2 j, 2 j +1) va cont¸ine pe linia 2 j trei numerenaturale p xj yj , separate prin cˆate un spat¸iu reprezentˆ and num arul de ordine alpaznicului si bornele kilometrice x j c si yj unde va p azi paznicul p, iar pe linia2 j + 1 vor scrise numerele de ordine ale det ¸inut ilor care sap˘a ın aceast˘ a zona,separate prin cˆate un spat¸iu, ordonate cresc˘ ator.

Restrict ii si precizari

• 1 ≤n ≤10000

• 0 ≤a i ≤bi ≤250, pentru orice i, 1 ≤ i ≤n

• 0 ≤x j ≤yj ≤250, pentru orice j , 1 ≤ j ≤k

• un det inut poate s˘a sape si ıntr-un singur punct (”ın dreptul bornei kilome-trice numerotat˘ a cu x”)

• ın cazul ın care exist˘ a mai multe solut ii se va asa una singur˘ a

• numerele de ordine ale paznicilor vor scrise ın sier ın ordine cresc˘ atoare

• numerotarea paznicilor ıncepe de la 1

Exemplu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 269/518

14.3. EXEMPLE 257

.in .out Explicat ie3 2 sunt necesari 2 paznici: paznicul 1 va p˘azi ıntre0 20 1 8 13 borna 8 si borna 13, iar det inut ii p aziti sunt 1 si 2;8 13 1 2 paznicul 2 va pazi ıntre borna 30 si borna 60, iar30 60 2 30 60 detinutul p˘azit este 3

34 3 sunt necesari 3 paznici: paznicul 1 va p˘azi ıntre10 203 1 10 20 borna 10 si borna 20, iar det inutul p˘azit este 1;2 53 1 paznicul 2 va pazi la borna 5, iar det¸inut ii p aziti30 403 2 5 5 sunt 2 si 4; paznicul 3 va pazi ıntre borna 30 si5 7 33 2 4 borna 40, iar detinutul p˘azit este 3

3 30 403

5 2 sunt necesari 2 paznici: paznicul 1 va p˘azi la10 30 1 30 30 borna 30, iar detinut ii p aziti sunt 1, 2, 3 si 4;30 32 1 2 3 4 paznicul 2 va pazi ıntre borna 27 si borna 28,0 30 2 27 28 iar detinutul p˘azit este 527 30 527 28 !Solut ¸ia nu este unic˘ a!

Timp maxim de execut ¸ie/test: 1 secund a (Windows), 0 .5 secunde (Linux)

Indicat ¸ii de rezolvare - descriere solut ¸ie

Solut ¸ia comisiei Problema cere, de fapt, determinarea num˘ arului minim de intersect ii ıntre

segmentele determinate de kilometrul minim si maxim ıntre care sap˘ a un det inut.Pentru a le determina procedez astfel:

• ordonez intervalele cresc˘ ator dup˘a kilometrul minim si descresc˘ ator dup˘akilometrul maxim

• pun primul det¸inut (deci cel cu intervalul de s˘ apare cel mai mare) ın grijaprimului paznic

• pentru toate celelalte

– caut un paznic care mai p˘ azeste det¸inut i si care poate p˘azi si acestdet inut (adic˘a intersect ia segmentelor s˘a e nevid a)

– daca gasesc– ajustez intervalul de s˘ apare ca s a poat a sapa si acest det ¸inut

– altfel (dac a nu gasesc)

– mai am nevoie de un paznic si ıl dau ın grija acestuia

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 270/518

258 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

Datorit˘a faptului c a intervalele sunt sortate, cresc˘ ator dup˘a cap atul inferior,ın momentul cˆ and un interval nu se mai intersecteaz˘ a cu cel deja determinat, estesigur ca nici un alt interval ce ıl urmeaz˘ a nu se mai intersecteaz˘ a, lucru ce asigur˘adeterminarea num˘ arului minim de paznici.

Codul sursa

import java.io.*;class Sant

static int n;static int[] x1=new int[10001];static int[] x2=new int[10001];static int[] o=new int[10001];

static void qsort(int li,int ls)

int val,aux,i,j;

i=li;j=ls;val=x2[(i+j)/2];

while(i<j)

while(x2[i]<val) i++;while(x2[j]>val) j--;if(i<=j)

aux=x1[i]; x1[i]=x1[j]; x1[j]=aux;aux=x2[i]; x2[i]=x2[j]; x2[j]=aux;aux=o[i]; o[i]=o[j]; o[j]=aux;i++;j--;

// while

if(li<j) qsort(li,j);if(i<ls) qsort(i,ls);

// qsort(...)

public static void main(String[] args) throws IOException

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 271/518

14.3. EXEMPLE 259

int k,np,xp;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("sant.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("sant.out")));

st.nextToken(); n=(int)st.nval;for(k=1;k<=n;k++)

st.nextToken(); x1[k]=(int)st.nval;st.nextToken(); x2[k]=(int)st.nval;o[k]=k;

qsort(1,n);

np=1;xp=x2[1];for(k=2;k<=n;k++) if(x1[k]>xp) np++; xp=x2[k]; out.println(np);

// inca o data pentru ...!np=1;xp=x2[1];out.println(np+" "+xp+" "+xp);

out.print(o[1]+" ");for(k=2;k<=n;k++)

if(x1[k]>xp)

out.println();np++;xp=x2[k];out.println(np+" "+xp+" "+xp);out.print(o[k]+" ");

else out.print(o[k]+" ");

// for kout.close();

// main(...)// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 272/518

260 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

14.3.18 Cezar - OJI2007 cls 11

In Roma antic˘a exist a n asez ari senatoriale distincte, cˆ ate una pentru ecaredintre cei n senatori ai Republicii. Asez˘ arile senatoriale sunt numerotate de la 1la n, ıntre oricare dou˘ a asez ari exist and leg aturi directe sau indirecte. O leg˘ atur˘aeste direct˘a dac a ea nu mai trece prin alte asez˘ ari senatoriale intermediare. Ediliiau pavat unele dintre leg˘ aturile directe dintre dou˘ a asez ari (numind o astfel delegatur˘a pavat˘a ”strad˘a”), astfel ıncˆ at ıntre oricare dou˘ a asez ari senatoriale s˘aexiste o singur a succesiune de str˘azi prin care se poate a junge de la o asezaresenatorial˘a la cealalt a.

Tot i senatorii trebuie s˘ a participe la sedint ¸ele Senatului. In acest scop, ei sedeplaseaz a cu lectica. Orice senator care se deplaseaz˘ a pe o strad a plateste 1 banpentru c˘a a fost transportat cu lectica pe acea strad˘ a.

La alegerea sa ca prim consul, Cezar a promis c˘ a va dota Roma cu o lectic˘agratuit˘a care sa circule pe un num ar de k str azi ale Romei astfel ıncˆ at orice senatorcare va circula pe str˘azile respective, s a poat a folosi lectica gratuit˘a far a a pl ati.Str azile pe care se deplaseaz˘a lectica gratuit˘ a trebuie s a e legate ıntre ele (zborul,metroul sau teleportarea neind posibile la acea vreme).

In plus, Cezar a promis s˘a stabileasc˘a sediul salii de sedint e a Senatului ıntr-una dintre asez˘ arile senatoriale aate pe traseul lecticii gratuite. Problema este dea alege cele k str azi si amplasarea sediului s˘ alii de sedint¸e a Senatului astfel ıncˆ at,prin folosirea transportului gratuit, senatorii, ın drumul lor spre sala de sedint ¸e,sa faca economii cat mai ınsemnate. In calculul costului total de transport, pentrutot i senatorii, Cezar a considerat c˘ a ecare senator va c˘alatori exact o dat˘ a de laasezarea sa pˆan a la sala de sedint¸e a Senatului.

Cerint ¸aScriet i un program care determin˘ a costul minim care se poate obt ¸ine prinalegerea adecvat˘a a celor k str azi pe care va circula lectica gratuit˘ a si a locului deamplasare a s˘alii de sedint a a Senatului.

Date de intrareFisierul cezar.in contine

• pe prima linie dou˘a valori n k separate printr-un spat ¸iu reprezentˆ andnum arul total de senatori si num˘ arul de strazi pe care circul˘ a lectica gratuit˘ a

•pe urm atorele n−1 linii se aa cate dou a valori i j separate printr-un spat ¸iu,reprezentˆand numerele de ordine a dou˘ a asez ari senatoriale ıntre care exist˘ a strad˘a.

Date de iesire

Pe prima linie a sierului cezar.out se va scrie costul total minim al trans-port arii tuturor senatorilor pentru o alegere optim˘ a a celor k str azi pe care vacircula lectica gratuit˘ a si a locului unde va amplasat˘ a sala de sedint¸e a Senatu-lui.

Restrict ii si precizari

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 273/518

14.3. EXEMPLE 261

• 1 < n ≤10000, 0 < k < n

• 1 ≤ i, j ≤n , i = j• Oricare dou˘a perechi de valori de pe liniile 2 , 3,...,n din sierul de intrarereprezint˘a dou a str azi distincte.

• Perechile din sierul de intrare sunt date astfel ıncˆ at respect˘a condit iile dinproblem a.

• Pentru 25% din teste n ≤30, pentru 25% din teste 30 < n ≤1000, pentru25% din teste 1000 < n ≤ 3000, pentru 10% din teste 3000 < n ≤ 5000, pentru10% din teste 5000 < n ≤10000.

Exemplu

cezar.in cezar.out Explicat ¸ie13 3 11 Costul minim se obt ine, de exemplu, pentru1 2 alegerea celor 3 str azi ıntre asez˘ arile2 3 5-7, 7-8, 8-10 si a salii de sedint e a Senatului

2 8 ın asezarea 8 (dup˘ a cum este evident¸iat7 8 ın desen).7 55 4 Exist a si alte alegeri pentru care se obt ¸ine5 6 solutia 11.8 98 1010 1110 1210 13

Timp maxim de execut ¸ie/test: 0.5 secunde

Indicat ¸ii de rezolvare - descriere solut ¸ie *

O implementare posibil˘ a utilizeaz a metoda GREEDY, O(n∗(n −k)) sauO((n −k)∗log(n)).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 274/518

262 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

Se elimina succesiv, dintre frunzele existente la un moment dat, frunza decost minim. Toate nodurile au costul init ¸ial 1. La eliminarea unei frunze, se incre-menteaz a cu 1 costul tat˘alui acesteia. Validitatea metodei rezult˘ a din observat iaca, la eliminarea unei frunze oarecare, tat˘ al acesteia poate deveni frunz˘ a la r andullui, dar cu un cost strict mai mare decˆ at al frunzei eliminate.

Se poate ret ine arborele cu ajutorul listelor de adiacent ¸a (liniare sau organi-zate ca arbori de c˘autare), iar frunzele se pot memora ıntr-un minheap de costuri,structur˘a care se actualizeaz˘a ın timp logaritmic.

Codul sursa

Varianta 1:

import java.io.*;class cezar

static StreamTokenizer st;static PrintWriter out;

static int n, ns;

static int[] v1 = new int[10001];static int[] v2 = new int[10001];static int[] g = new int[10001]; // gradelestatic int[] ca = new int[10001]; // ca[k]=costul acumulat in nodul k !!!

static int[] nde = new int[10001]; // nde[k]=nr "descendenti" eliminati pana in k

static void citire() throws IOException

int i,j,k;

st.nextToken(); n=(int)st.nval;st.nextToken(); ns=(int)st.nval;

for(i=1;i<=n;i++) g[i]=ca[i]=nde[i]=0; // curatenie ...

for(k=1;k<=n-1;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;

v1[k]=i;v2[k]=j;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 275/518

14.3. EXEMPLE 263

g[i]++; g[j]++;

// citire(...)

static int tata(int i) // mai bine cu lista de adiacenta ...

int k,t;t=-1; // initializarea aiurea ...for(k=1;k<=n-1;k++) // n-1 muchii

if( (v1[k]==i) && (g[v2[k]] > 0) ) t=v2[k]; break;elseif( (v2[k]==i) && (g[v1[k]] > 0) ) t=v1[k]; break;

return t;

static void eliminm() // frunze(g=1) cu cost=min

int i, imin, timin;int min;

min=Integer.MAX_VALUE;imin=-1; // initializare aiurea ...for(i=1;i<=n;i++) // mai bine cu heapMIN ...

if(g[i]==1) // i=frunza

if(nde[i]+1<min) // ... aici este testul CORECT ... !!! min=nde[i]+1;imin=i;

timin=tata(imin);g[imin]--; g[timin]--;ca[timin]=ca[timin]+ca[imin]+nde[imin]+1;nde[timin]=nde[timin]+nde[imin]+1; // nr descendenti eliminati

// elimin()

public static void main(String[] args) throws IOException

int k,senat=0,cost=0;st=new StreamTokenizer(new BufferedReader(new FileReader("cezar20.in")));out=new PrintWriter(new BufferedWriter(new FileWriter("cezar.out")));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 276/518

264 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

citire();

for(k=1;k<=n-1-ns;k++) eliminm();

for(k=1;k<=n;k++)if(g[k]>0)

cost+=ca[k];senat=k;

System.out.println("\n"+cost+" "+senat);out.println(cost+" "+senat);out.close();//afisv(g,1,n);

// main// class

Varianta 2:

import java.io.*;class cezar // cost initial = 1 pentru toate nodurile ...

static StreamTokenizer st;static PrintWriter out;

static int n, ns,s=0;

static int[] v1 = new int[10001];static int[] v2 = new int[10001];static int[] g = new int[10001]; // gradelestatic int[] ca = new int[10001]; // ca[k]=costul acumulat in nodul k !!!

static void afisv(int[] v,int i1, int i2)

int i;for(i=i1;i<=i2;i++)

System.out.print(v[i]+" ");if(i%50==0) System.out.println();

System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 277/518

14.3. EXEMPLE 265

static void citire() throws IOException

int i,j,k;

st.nextToken(); n=(int)st.nval;st.nextToken(); ns=(int)st.nval;

for(i=1;i<=n;i++) // curatenie ...

g[i]=0;ca[i]=1; // cost initial in nodul i

for(k=1;k<=n-1;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;

v1[k]=i;v2[k]=j;g[i]++; g[j]++;

//afisv(v1,1,n-1);//afisv(v2,1,n-1);

//afisv(g,1,n);// citire(...)

static int tata(int i) // mai bine cu liste de adiacenta ...

int k,t;t=-1; // initializarea aiurea ...for(k=1;k<=n-1;k++) // este mai bine cu lista de adiacenta ?

if( (v1[k]==i) && (g[v2[k]]>0)) t=v2[k]; break;elseif( (v2[k]==i) && (g[v1[k]]>)) t=v1[k]; break;

return t;

static void eliminm() // frunze(g=1) cu cost=min

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 278/518

266 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

int i, imin, timin;int min;

min=Integer.MAX_VALUE;imin=-1; // initializare aiurea ...for(i=1;i<=n;i++) // mai bine cu heapMIN ...

if(g[i]==1) // i=frunzaif(ca[i]<min) // cost acumulat

min=ca[i];imin=i;

timin=tata(imin);

g[imin]--; g[timin]--;

ca[timin]=ca[timin]+min;s+=min;

//System.out.println(" Elimin nodul "+imin+// " timin = "+timin+" ca = "+ca[timin]);

// elimin()

public static void main(String[] args) throws IOException

int k,senat=0;st=new StreamTokenizer(new BufferedReader(new FileReader("cezar20.in")));out=new PrintWriter(new BufferedWriter(new FileWriter("cezar.out")));

citire();

for(k=1;k<=n-1-ns;k++)

eliminm();

//afisv(c,1,n);

for(k=1;k<=n;k++)if(g[k]>0)

senat=k;break;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 279/518

14.3. EXEMPLE 267

System.out.println("\n"+s+" "+senat);

out.println(s+" "+senat);out.close();

// main// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 280/518

268 CAPITOLUL 14. METODA OPTIMULUI LOCAL - GREEDY

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 281/518

Capitolul 15

Metoda backtracking

Metoda backtracking se utilizeaz a pentru determinarea unei submult ¸imi aunui produs cartezian de forma S 1 ×S 2 ×... ×S n (cu mult imile S k nite) careare anumite propriet˘ at i. Fiecare element ( s1 , s2 ,...,s n ) al submult imii produsuluicartezian poate interpretat ca solut ¸ie a unei probleme concrete.

In majoritatea cazurilor nu oricare element al produsului cartezian este solut ¸ieci numai cele care satisfac anumite restrict ii . De exemplu, problema determin˘ ariituturor combin˘ arilor de m elemente luate cˆate n (unde 1 ≤n ≤m) din mult imea

1, 2,...,m poate reformulat˘ a ca problema determin˘ arii submult¸imii produsuluicartezian 1, 2,...,m n denit a astfel:

(s1 , s2 ,...,s n )∈ 1, 2,...,m n

|s i = s j ,∀i = j, 1 ≤ i, j ≤n.Metoda se aplic˘a numai atunci cˆand nu exist˘a nici o alt a cale de rezolvare a

problemei propuse, deoarece timpul de execut ¸ie este de ordin exponent ¸ial.

15.1 Generarea produsului cartezian

Pentru ıncep˘ atori, nu metoda backtracking ın sine este dicil de ınt ¸eles cimodalitatea de generare a produsului cartezian.

15.1.1 Generarea iterativa a produsului cartezian

Presupunem c˘a mult imile S i sunt formate din numere ıntregi consecutivecuprinseıntre o valoare min si o valoare max . De exemplu, dac a min = 0 ,max = 9atunci S i = 0, 1, ..., 9. Dorim s a gener am produsul cartezian S 1 ×S 2 ×... ×S n

269

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 282/518

270 CAPITOLUL 15. METODA BACKTRACKING

(de exemplu, pentru n = 4). Folosim un vector cu n elemente a = ( a1 , a 2 ,...,a n )si vom atribui ec˘arei componente a

ivalori cuprinse ıntre min si max .

0 1 2 3 4 5

0 1 ... ... n n+1Ne trebuie un marcaj pentru a preciza faptul c˘ a o anumit˘a component˘a este

goal˘ a (nu are plasat˘ aın ea o valoare valid˘ a). In acest scop folosim variabila gol carepoate init ializat˘a cu orice valoare ıntreag˘ a care nu este ın intervalul [ min, max ].Este totusi util˘ a initializarea gol=min-1; .

Cum ıncepem generarea produsului cartezian?O prim a variant˘a este s a atribuim tuturor componentelor a i valoarea min si

avem astfel un prim element al produsului cartezian, pe care putem s˘ a-l as am.0 1 2 3 4 5

0 0 0 00 1 ... ... n n+1

Trebuie s a construim urm˘ atoarele elemente ale produsului cartezian. Esteutil a, ın acest moment, imaginea kilometrajelor de masini sau a contoarelor deenergie electic a, de ap a, de gaze, etc. Urm˘atoarea congurat ¸ie a acestora este

0 1 2 3 4 50 0 0 1

0 1 ... ... n n+1dup a care urmeaz˘a

0 1 2 3 4 50 0 0 2

0 1 ... ... n n+1Folosim o variabil˘a k pentru a urm˘ari pozit ia din vector pe care se schimb˘ a

valorile. La ınceput k = n si, pe aceast˘a pozit ie k, valorile se schimb a crescand dela min catre max . Se ajunge astfel la congurat¸ia ( k = 4 = n aici!)

0 1 2 3 4 50 0 0 9

0 1 ... ... n n+1Ce se ıntˆampl a mai departe? Apare congurat ¸ia

0 1 2 3 4 50 0 1 0

0 1 ... ... n n+1ıntr-un mod ciudat!

Ei bine, se poate spune c˘a aici este cheia metodei backtraching! Dac˘ a reusimsa ınt elegem acest pas de trecere de la o congurat ¸ie la alta si s˘a formaliz am ceam observat, atunci am descoperit singuri aceast˘ a metod a!

Pe pozit ia k = n, odat a cu aparit ia valorii 9 = max , s-au epuizat toatevalorile posibile, asa c˘a vom considera c a pozit ia k este goal a si vom trece pe opozitie mai la st anga, deci k = k −1 (acum k = 3).

0 1 2 3 4 50 0 0

0 1 ... ... n n+1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 283/518

15.1. GENERAREA PRODUSULUI CARTEZIAN 271

Pe pozit ia k = 3 se af a valoarea 0 care se va schimba cu urm˘ atoarea valoare(dac a exist a o astfel de valoare

≤max ), deci ın acest caz cu 1.

0 1 2 3 4 50 0 1

0 1 ... ... n n+1Dup a plasarea unei valori pe pozit ¸ia k, se face pasul spre dreapta ( k = k +1).

0 1 2 3 4 50 0 1

0 1 ... ... n n+1Aici (dac a nu am iesit ın afara vectorului, ın urma pasului f˘ acut spre dreapta!),

ın cazul nostru k = 4 si pozit¸ia este goal˘ a , se plaseaz a prima valoare valid˘ a (decivaloarea min ).

0 1 2 3 4 50 0 1 0

0 1 ... ... n n+1Cum trecerea de la o valoare la alta se face prin cresterea cu o unitate a valorii

vechi iar acum facem trecerea gol →min , ınt elegem de ce este util s a initializ amvariabila gol cu valoarea min −1.

Sa consider am ca s-a ajuns la congurat¸ia0 1 2 3 4 5

0 0 9 90 1 ... ... n n+1

Aici k = 4 = n si 9 = max . Pe pozit ia k nu se mai poate pune o nou˘a valoaresi atunci:

• se pune gol pe pozit ia k

• se face pasul spre st anga, deci k = k −1

0 1 2 3 4 50 0 90 1 ... ... n n+1

Aici k = 3 si 9 = max . Pe pozit ia k nu se mai poate pune o nou˘a valoare siatunci:

• se pune gol pe pozit ia k

• se face pasul spre st anga, deci k = k −10 1 2 3 4 5

0 00 1 ... ... n n+1

Aici k = 2 si 0 < max . Pe pozit ia k se poate pune o nou˘a valoare si atunci:

• se pune 0 + 1 = 1 = urm˘ atoarea valoare pe pozit ia k

•se face pasul spre dreapta, deci k = k + 10 1 2 3 4 5

0 10 1 ... ... n n+1

Aici k = 3 si gol =-1 < max . Pe pozit ia k se poate pune o nou˘a valoare:

• se pune gol +1= −1 + 1 = 0 = urm˘ atoarea valoare pe pozit ia k

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 284/518

272 CAPITOLUL 15. METODA BACKTRACKING

• se face pasul spre dreapta, deci k = k + 10 1 2 3 4 5

0 1 00 1 ... ... n n+1

Aici k = 4 si gol =-1 < max . Pe pozit ia k se poate pune o nou˘a valoare:

• se pune gol +1= −1 + 1 = 0 = urm˘ atoarea valoare pe pozit ia k

• se face pasul spre dreapta, deci k = k + 10 1 2 3 4 5

0 1 0 00 1 ... ... n n+1

iar aici k = n + 1 si am ajuns ın afara vectorului! Nu-i nimic! Se aseaz asolut¸ia 0100 si se face pasul la st anga. Aici k = 4 si 0 < max . Pe pozit ia k sepoate pune o nou˘a valoare:

•se pune 0 + 1 = 1 = urm˘ atoarea valoare pe pozit ia k

• se face pasul spre dreapta, deci k = k + 10 1 2 3 4 5

0 1 0 10 1 ... ... n n+1

A ap arut ın mod evident urm˘ atoarea regul˘a: ajung and pe pozit ia k ≤ n,ıncerc˘am sa punem urm˘atoarea valoare ( gol are ca ”urm˘atoarea valoare” pe min )pe aceast a pozitie si

• daca se poate: se pune urm˘atoarea valoare si se face pasul spre dreapta;

• daca nu se poate: se pune gol = min −1 si se face pasul spre st anga.Presupunem c˘a s-a ajuns la congurat¸ia

0 1 2 3 4 59 9 9 9

0 1 ... ... n n+1care se aseaz a ca solut ie. Ajungem la k = 4

0 1 2 3 4 59 9 9 9

0 1 ... ... n n+1se goleste pozit ia si ajungem la k = 3

0 1 2 3 4 59 9 9

0 1 ... ... n n+1se goleste pozit ia si ajungem la k = 2

0 1 2 3 4 59 9

0 1 ... ... n n+1se goleste pozit ia si ajungem la k = 1

0 1 2 3 4 59

0 1 ... ... n n+1se goleste pozit ia si ajungem la k = 0

0 1 2 3 4 5

0 1 ... ... n n+1iar aici k = 0 si am ajuns ın afara vectorului!

Nu-i nimic! Aici s-a terminat generarea produsului cartezian!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 285/518

15.1. GENERAREA PRODUSULUI CARTEZIAN 273

Putem descrie acum algoritmul pentru generarea produsului cartezian S n ,unde S =

min, min + 1 ,...,max

:

• structuri de date:

−a[1..n ] vectorul solut ie

−k ”pozit ia” ın vectorul solut ¸ie, cu convent iile k = 0 precizeaz˘a terminareagener arii, iar k = n + 1 precizeaz˘a faptul c a s-a construit o solut¸ie care poate asat˘a;

• proces de calcul:1. se construieste prima solut ¸ie2. se plaseaz a pozitia ın afara vectorului (ın dreapta)3. cat timp nu s-a terminat generarea

4. dac a este deja construit˘ a o solutie5. se aseaz a solut ia si se face pasul spre stˆanga6. altfel, dac a se poate m ari valoarea pe pozit¸ia curent˘a

7. se mareste cu 1 valoarea si se face pasul spre dreapta8. altfel, se goleste pozit ia curent˘a si se face pasul spre stˆanga

3’. revenire la 3.Implementarea acestui algoritm ın Java este urm˘ atoarea:

class ProdCartI1 // 134.000 ms pentru 8 cu 14

static int n=8, min=1, max=14, gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i, k;long t1,t2;t1=System.currentTimeMillis();for(i=1;i<=n;i++) a[i]=min;k=n+1;while (k>0)

if (k==n+1) /* afis(a); */ --k;else if (a[k]<max) ++a[k++]; else a[k--]=gol;

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 286/518

274 CAPITOLUL 15. METODA BACKTRACKING

O alt a variant˘a ar putea init¸ializarea vectorului solut ¸ie cu gol si plasareape prima pozit ie ın vector. Nu mai avemın acest caz o solut ¸ie gata construit˘ a daralgoritmul este acelasi. Implementarea ın acest caz este urm˘ atoarea:

class ProdCartI2 // 134.000 ms pentru 8 cu 14

static int n=8, min=1, max=14, gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i, k;long t1,t2;t1=System.currentTimeMillis();for(i=1;i<=n;i++) a[i]=gol;k=1;while (k>0)

if (k==n+1) /* afis(a); */ --k;else if (a[k]<max) ++a[k++]; else a[k--]=gol;

t2=System.currentTimeMillis();

System.out.println("Timp = "+(t2-t1)+" ms");

15.1.2 Generarea recursiva a produsului cartezian

class ProdCartR1 // 101.750 ms pentru 8 cu 14

static int n=8, min=1,max=14;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 287/518

15.1. GENERAREA PRODUSULUI CARTEZIAN 275

static void f(int k)

int i;if (k>n) /* afis(a); */ return; ;for(i=min;i<=max;i++) a[k]=i; f(k+1);

public static void main (String[] args)

long t1,t2;t1=System.currentTimeMillis();f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

class ProdCartR2 // 71.300 ms pentru 8 cu 14

static int n=8, min=1,max=14;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);

System.out.println();

static void f(int k)

int i;for(i=min;i<=max;i++) a[k]=i; if (k<n) f(k+1);

public static void main (String[] args)

long t1,t2;t1=System.currentTimeMillis();f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 288/518

276 CAPITOLUL 15. METODA BACKTRACKING

class ProdCartCar1

static char[] x;static int n,m;static char[] a=0,’A’,’X’;

public static void main(String[] args)

n=4; m=a.length-1;x=new char[n+1];f(1);

static void f(int k)

int i;for(i=1;i<=m;i++)

x[k]=a[i];if(k<n) f(k+1);

else afisv();

static void afisv()

int i;for(i=1; i<=n; i++)

System.out.print(x[i]);System.out.println();

//class

class ProdCartCar2

static char[] x;static int n;static int[] m;static char[][] a = 0,

0,’A’,’B’,0,’1’,’2’,’3’

;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 289/518

15.2. METODA BACTRACKING 277

public static void main(String[] args)

int i;n=a.length-1; m=new int[n+1];for(i=1;i<=n;i++) m[i]=a[i].length-1;x=new char[n+1];f(1);

static void f(int k)

int j;for(j=1;j<=m[k];j++)

x[k]=a[k][j];if(k<n) f(k+1); else afisv();

static void afisv()

int i;for(i=1; i<=n; i++) System.out.print(x[i]);System.out.println();

// class

15.2 Metoda bactracking

Se foloseste pentru rezolvarea problemelor careındeplinesc urm˘ atoarele condit¸ii:

1. nu se cunoaste o alt˘a metod a mai rapid˘a de rezolvare;

2. solutia poate pus˘a sub forma unui vector x = ( x1 , x2 ,...,x n ) cu x i ∈Ai ,i = 1 ,...,n ;

3. multimile Ai sunt nite.

Tehnica backtracking pleac˘ a de la urm atoarea premis˘ a:

dac˘ a la un moment dat nu mai am nici o sans˘ a s˘ a ajung la solut ia c˘ autat˘ a, renunt s˘ a continui pentru o valoare pentru care stiu c˘ a nu ajung la nici un rezultat .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 290/518

278 CAPITOLUL 15. METODA BACKTRACKING

Specicul metodei const˘a ın maniera de parcurgere a spat ¸iului solut iilor.

•solut iile sunt construite succesiv, la ecare etap˘ a ind completat˘a cate o

component˘a;

• alegerea unei valori pentru o component˘ a se face ıntr-o anumit˘ a ordineastfel ıncˆat s a e asigurat˘a o parcurgere sistematic˘ a a spat iului A1 ×A2 ×... ×An ;

• la completarea componentei k se verica dac a solut ia part¸ial a (x1 , x2 ,...,x k )verica condit iile induse de restrict ¸iile problemei (acestea sunt numite condit ii decontinuare );

• daca au fost ıncercate toate valorile corespunz˘ atoare componentei k si ınc˘anu a fost g a sit a o solutie, sau dacse doreste determinarea unei noi solut ¸ii, se revinela componenta anterioar˘ a (k−1) si se ıncearc˘ a urm atoarea valoare corespunz˘ a toareacesteia, s.a.m.d.

•procesul de c autare si revenire este continuat pˆ ana cand este g asit a o solutie(dac a este sucient˘a o solutie) sau p an a cand au foste testate toate congurat ¸iileposibile (dac a sunt necesare toate solut ¸iile).

In gur a este ilustrat modul de parcurgere a spat ¸iului solut iilor ın cazulgener arii produsului cartezian 0, 14 .

In cazul ın care sunt specicate restrict ¸ii (ca de exemplu, s˘a nu e dou acomponente al˘aturate egale) anumite ramuri ale structurii arborescente asociatesunt abandonate ınainte de a atinge lungimea n.

0 1

0

0

0

0

0

0 0 0

0 0 0 0 0 0

1

1 1

1 1 1 1

1 1 1 1 1 1 1

0

0 0

0 0

0 0

1

1 1

1 1

1 1

x1

x2

x3

x4

x1

x2

x3

x4

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 291/518

15.2. METODA BACTRACKING 279

In aplicarea metodei pentru o problem˘ a concret a se parcurg urm˘atoareleetape:

• se alege o reprezentare a solut ¸iei sub forma unui vector cu n componente;

• se identic a mult imile A1 , A2 ,...,A n si se stabileste o ordine ˆntre elementecare s a indice modul de parcurgere a ec˘ arei mult imi;

• pornind de la restrict ¸iile problemei se stabilesc condit ¸iile de validitate alesolut iilor part¸iale (condit¸iile de continuare).

In aplicat iile concrete solut¸ia nu este obt¸inut˘a numai ın cazul ın care k = nci este posibil s a e satisf acut a o condit ie de gasire a solut iei pentru k < n (pentruanumite probleme nu toate solut ¸iile cont in acelasi num˘ ar de elemente).

15.2.1 Bactracking iterativ

Structura general˘ a a algoritmului este:for(k=1;k < =n;k++) x[k]=gol; init ¸iarizarea vectorului solut ¸iek=1; pozit ionare pe prima component˘ awhile (k> 0) cat timp exist˘a componente de analizat

if (k==n+1) dac˘ a x este solut ie

as(x); –k; atunci: asare solut ¸ie si pas stˆangaelse altfel:

if(x[k]< max[k]) dac a exist a elemente de ıncercatif(posibil(1+x[k])) dac˘ a 1+x[k] este valid˘a

++x[k++]; atunci m˘ aresc si fac pas dreaptaelse ++x[k]; altfel m˘aresc si r aman pe pozitie

else x[k–]=gol; altfel golesc si fac pas dreaptaVectorul solut ie x contine indicii din mult¸imile A1 , A2 ,...,A n . Mai precis,x[k] = i ınseamn˘a ca pe pozit ia k din solut ia x se aa a i din Ak .

15.2.2 Backtracking recursiv

Varianta recursiv˘ a a algoritmului backtracking poate realizat˘ a dup a oschem a asem anatoare cu varianta recursiv˘ a. Principiul de funct¸ionare al functieif (primul apel este f (1)) corespunz˘ator unui nivel k este urm atorul:

−ın situat ¸ia ın care avem o solut ¸ie, o as am si revenim pe nivelul anterior;

−ın caz contrar, se init ¸ializeaz a nivelul si se caut˘a un succesor;

− cand am g asit un succesor, veric˘am dac a este valid. In caz armativ,procedura se autoapeleaz˘ a pentru k + 1; ın caz contrar urmˆ and a se continuacautarea succesorului;

− daca nu avem succesor, se trece la nivelul inferior k −1 prin iesirea dinprocedura recursiv˘ a f .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 292/518

280 CAPITOLUL 15. METODA BACKTRACKING

15.3 Probleme rezolvate

15.3.1 Generarea aranjamentelor

Reprezentarea solut iilor : un vector cu n componente.Mult ¸imile Ak : 1, 2,...,m .Restrict iile si condit iile de continuare : Daca x = ( x1 , x2 ,...,x n ) este o solut ie

ea trebuie s a respecte restrict ¸iile: x i = x j pentru oricare i = j . Un vector cu kelemente ( x1 , x2 ,...,x k ) poate conduce la o solut¸ie numai dac˘a satisface condit iilede continuare x i = x j pentru orice i = j , unde i, j ∈ 1, 2,...,k .

Condit ia de g˘ asire a unei solut ii : Orice vector cu n componente care respect˘ arestrict iile este o solut ie. C and k = n + 1 a fost g asit a o solutie.

Prelucrarea solut ¸iilor : Fiecare solut ie obt inut˘a este asat˘ a.

class GenAranjI1

static int n=2, min=1,max=4, gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++)System.out.print(a[i]);

System.out.println();

static boolean gasit(int val, int pozmax)

for(int i=1;i<=pozmax;i++)if (a[i]==val) return true;

return false;

public static void main (String[] args)

int i, k;for(i=1;i<=n;i++) a[i]=gol;k=1;while (k>0)

if (k==n+1) afis(a); --k;else

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 293/518

15.3. PROBLEME REZOLVATE 281

if(a[k]<max)

if(!gasit(1+a[k],k-1)) ++a[k++]; // maresc si pas dreaptaelse ++a[k]; // maresc si raman pe pozitie

else a[k--]=gol;

class GenAranjI2

static int n=2, min=1,max=4;static int gol=min-1;static int[] a=new int[n+1];

static void afis()

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

static boolean posibil(int k)

for(int i=1;i<k;i++) if (a[i]==a[k]) return false;return true;

public static void main (String[] args)

int i, k;boolean ok;for(i=1;i<=n;i++) a[i]=gol;k=1;while (k>0)

ok=false;while (a[k] < max) // caut o valoare posibila

++a[k];ok=posibil(k);if(ok) break;

if(!ok) k--;else if (k == n) afis();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 294/518

282 CAPITOLUL 15. METODA BACKTRACKING

else a[++k]=0;

class GenAranjR1

static int n=2, m=4, nsol=0;static int[] a=new int[n+1];

static void afis()

System.out.print(++nsol+" : ");for(int i=1;i<=n;i++) System.out.print(a[i]+" ");

System.out.println();

static void f(int k)

int i,j;boolean gasit;for(i=1; i<=m; i++)

if(k>1) // nu este necesar !

gasit=false;

for(j=1;j<=k-1;j++)if(i==a[j])

gasit=true;break; // in for j

if(gasit) continue; // in for i

a[k]=i;if(k<n) f(k+1); else afis();

public static void main(String[] args)

f(1);

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 295/518

15.3. PROBLEME REZOLVATE 283

class GenAranjR2

static int[] a;static int n,m;

public static void main(String[] args)

n=2; m=4;a=new int[n+1];f(1);

static void f(int k)

boolean ok;int i,j;for(i=1;i<=m;i++)

ok=true; // k=1 ==> nu am in stanga ... for nu se executa !for(j=1;j<k;j++)

if(i==a[j])

ok=false;break;

if(!ok) continue;a[k]=i;if(k<n) f(k+1);

else afisv();

static void afisv()

int i;for(i=1; i<=n; i++)

System.out.print(a[i]);System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 296/518

284 CAPITOLUL 15. METODA BACKTRACKING

15.3.2 Generarea combinarilor

Sunt prezentate mai multe variante (iterative si recursive) cu scopul de avedea diferite modalit˘ at i de a c astiga timp ın execut ¸ie (mai mult sau mai put ¸insemnicativ!).

class GenCombI1a // 4550 ms cu 12 22 // 40 ms cu 8 14 fara afis // 7640 ms cu 8 14 cu afis

static int n=8, min=1,max=14;static int gol=min-1,nv=0;static int[] a=new int[n+1];

static void afis(int[] a)

int i;System.out.print(++nv+" : ");for(i=1;i<=n;i++)

System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i, k;long t1,t2;

t1=System.currentTimeMillis();for(i=0;i<=n;i++)a[i]=gol; // initializat si a[0] care nu se foloseste!!

k=1;while (k>0)

if (k==n+1) afis(a); --k; else

if(a[k]<max)if(1+a[k]>a[k-1])

++a[k++]; // maresc si pas dreapta (k>1) ...else ++a[k]; // maresc si raman pe pozitie

else a[k--]=gol;

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 297/518

15.3. PROBLEME REZOLVATE 285

class GenCombI1b // 3825 ms 12 22 sa nu mai merg la n+1 !!!!

static int n=12, min=1,max=22;static int gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i;long t1,t2;t1=System.currentTimeMillis();for(i=0;i<=n;i++) a[i]=gol; // initializat si a[0] care nu se foloseste!!int k=1;while (k>0)

if(a[k]<max)if(1+a[k]>a[k-1])

if(k<n) ++a[k++]; // maresc si pas dreapta (k>1) ...else ++a[k]; /* afis(a); */// maresc, afisez si raman pe pozitie

else ++a[k]; // maresc si raman pe pozitie

else a[k--]=gol;t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// class

class GenCombI2a // 1565 ms 12 22

static int n=12, min=1,max=22;static int gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 298/518

286 CAPITOLUL 15. METODA BACKTRACKING

public static void main (String[] args)

int i, k;long t1,t2;t1=System.currentTimeMillis();for(i=0;i<=n;i++)

a[i]=gol; // initializat si a[0] care nu se foloseste!!k=1;while (k>0)if (k==n+1) /* afis(a); */ --k;else

if(a[k]<max-(n-k)) // optimizat !!!if(1+a[k]>a[k-1]) ++a[k++]; // maresc si pas dreapta (k>1) ...else ++a[k]; // maresc si raman pe pozitie

else a[k--]=gol;t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

class GenCombI2b // 1250 ms 12 22

static int n=12, min=1,max=22;

static int gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++)System.out.print(a[i]);

System.out.println();

public static void main (String[] args)

int i, k; long t1,t2;t1=System.currentTimeMillis();for(i=0;i<=n;i++)

a[i]=gol; // initializat si a[0] care nu se foloseste!!k=1;while (k>0)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 299/518

15.3. PROBLEME REZOLVATE 287

if(a[k]<max-(n-k)) // optimizat !!!

if(1+a[k]>a[k-1])if(k<n) ++a[k++]; // maresc si pas dreapta (k>1) ...else ++a[k]; /* afis(a); */// maresc, afisez si raman pe pozitie

else ++a[k]; // maresc si raman pe pozitieelse a[k--]=gol;

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

class GenCombI3a // 835 ms 12 22

static int n=12, min=1, max=22, gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i, k; // si mai optimizat !!!long t1,t2; t1=System.currentTimeMillis();for(i=0;i<=n;i++)

a[i]=i-gol-1; // initializat si a[0] care nu se foloseste!!k=1;while (k>0)

if (k==n+1) /* afis(a); */ --k;else

if(a[k]<max-(n-k)) // optimizat !!!if(1+a[k]>a[k-1]) ++a[k++]; // maresc si pas dreapta (k>1) ...else ++a[k]; // maresc si raman pe pozitie

else a[k--]=k-gol-1; // si mai optimizat !!!

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 300/518

288 CAPITOLUL 15. METODA BACKTRACKING

class GenCombI3b // 740 ms 12 22

static int n=12, min=1, max=22, gol=min-1;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

public static void main (String[] args)

int i, k;long t1,t2;t1=System.currentTimeMillis();for(i=0;i<=n;i++) a[i]=i-gol-1; // si mai optimizat !!!k=1;while (k>0)

if(a[k]<max-(n-k)) // optimizat !!!

++a[k]; // marescif(a[k]>a[k-1])if(k<n) k++; // pas dreapta

/* else afis(a); */ // afisez

else a[k--]=k-gol-1; // si mai optimizat !!!t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

class GenCombR1a // 2640 ms 12 22

static int[] x;static int n,m;

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();n=12; m=22;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 301/518

15.3. PROBLEME REZOLVATE 289

x=new int[n+1];f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

static void f(int k)

for(int i=1;i<=m;i++)

if(k>1) if(i<=x[k-1]) continue;x[k]=i;if(k<n) f(k+1);/* else afisv(); */

static void afisv()

for(int i=1; i<=n; i++) System.out.print(x[i]);System.out.println();

class GenCombR1b // 2100 ms 12 22

static int n=12,m=22;static int[] a=new int[n+1];

static void afis(int[] a)

for(int i=1;i<=n;i++) System.out.print(a[i]);System.out.println();

static void f(int k)

for(int i=1;i<=m;i++ )

if (i<=a[k-1]) continue; // a[0]=0 deci merge !a[k]=i;if(k<n) f(k+1); /* else afis(a); */

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 302/518

290 CAPITOLUL 15. METODA BACKTRACKING

public static void main (String [] args)

long t1,t2;t1=System.currentTimeMillis();f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

//main//class

class GenCombR2a // 510 ms 12 22

static int n=12, m=22, nsol=0, ni=0; ;static int[] x=new int[n+1];

static void afisx()

System.out.print(++nsol+" ==> ");for(int i=1;i<=n;i++) System.out.print(x[i]+" ");System.out.println();

static void afis(int k) // pentru urmarirea executiei ! // ni = numar incercari !!!

int i;

System.out.print(++ni+" : ");for(i=1;i<=k;i++) System.out.print(x[i]+" ");System.out.println();

static void f(int k)

for(int i=k; i<=m-n+k; i++) // imbunatatit !

if(k>1)

// afis(k-1);if(i<=x[k-1]) continue;

x[k]=i;if(k<n) f(k+1); /* else afisx(); */

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 303/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 304/518

292 CAPITOLUL 15. METODA BACKTRACKING

f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// class

class GenCombR3a // 165 ms 12 22

static int n=12;static int m=22;static int[] x=new int[n+1];static int nsol=0,ni=0;

static void afisx()

int i;System.out.print(++nsol+" ==> ");for(i=1;i<=n;i++) System.out.print(x[i]+" ");System.out.println();

static void afis(int k)

int i;System.out.print(++ni+" : ");for(i=1;i<=k;i++) System.out.print(x[i]+" ");

System.out.println();

static void f(int k)

int i;for (i=x[k-1]+1; i<=m-n+k; i++) // si mai imbunatatit !!!

if(k>1)

// afis(k-1);if(i<=x[k-1]) continue;

x[k]=i;if(k<n) f(k+1); /* else afisx(); */

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 305/518

15.3. PROBLEME REZOLVATE 293

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// class

class GenCombR3b // 140 ms 12 22

static int n=12;static int m=22;

static int[] x=new int[n+1];static int nsol=0;

static void afisx()

int i;System.out.print(++nsol+" : ");for(i=1;i<=n;i++) System.out.print(x[i]+" ");System.out.println();

static void f(int k)

int i;for (i=x[k-1]+1; i<=m-n+k; i++)

x[k]=i;if(k<n) f(k+1); /* else afisx(); */

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();f(1);t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 306/518

294 CAPITOLUL 15. METODA BACKTRACKING

15.3.3 Problema reginelor pe tabla de sah

O problem a clasica de generare a congurat ¸iilor ce respect˘a anumite restrict ¸iieste cea a amplas˘arii damelor pe o tabl˘a de sah astfel ıncˆ at s a nu se atace reciproc.

Reprezentarea solut iei : un vector x unde x i reprezint˘a coloana pe care se a aregina dac a linia este i.

Restrict ii si condit ii de continuare : x i = x j pentru oricare i = j (reginele nuse atac a pe coloan a) si |x i −x j | = |i − j | (reginele nu se atac˘a pe diagonal a).

Sunt prezentate o variant˘ a iterativ˘a si una recursiv˘a.

class RegineI1

static int[] x;static int n,nv=0;

public static void main(String[] args)

n=5;regine(n);

static void regine(int n)

int k;boolean ok;

x=new int[n+1];for(int i=0;i<=n;i++) x[i]=i;k=1;x[k]=0;while (k>0)

ok=false;while (x[k] <= n-1) // caut o valoare posibila

++x[k];ok=posibil(k);if(ok) break;

if(!ok) k--;else if (k == n) afis();

else x[++k]=0;

//regine()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 307/518

15.3. PROBLEME REZOLVATE 295

static boolean posibil(int k)

for(int i=1;i<=k-1;i++)if ((x[k]==x[i])||((k-i)==Math.abs(x[k]-x[i]))) return false;

return true;

static void afis()

int i;System.out.print(++nv+" : ");for(i=1; i<=n; i++) System.out.print(x[i]+" ");System.out.println();

// class

class RegineR1

static int[] x;static int n,nv=0;

public static void main(String[] args)

n=5;

x=new int[n+1];f(1);

static void f(int k)

boolean ok;int i,j;for(i=1;i<=n;i++)

ok=true;for(j=1;j<k;j++)if((i==x[j])||((k-j)==Math.abs(i-x[j]))) ok=false; break;if(!ok) continue;x[k]=i;if(k<n) f(k+1); else afisv();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 308/518

296 CAPITOLUL 15. METODA BACKTRACKING

static void afisv()

int i;System.out.print(++nv+" : ");for(i=1; i<=n; i++) System.out.print(x[i]+" ");System.out.println();

15.3.4 Turneul calului pe tabla de sah

import java.io.*;class Calut

static final int LIBER=0,SUCCES=1,ESEC=0,NMAX=8;static final int[] a=0,2,1,-1,-2,-2,-1,1,2; // miscari posibile pe Oxstatic final int[] b=0,1,2,2,1,-1,-2,-2,-1; // miscari posibile pe Oystatic int[][] tabla=new int[NMAX+1][NMAX+1]; // tabla de sahstatic int n,np,ni=0; // np=n*n

public static void main(String[] args) throws IOException

BufferedReader br=new BufferedReader(

new InputStreamReader(System.in));while ((n<3)||(n>NMAX))

System.out.print("Dimensiunea tablei de sah [3.."+NMAX+"] : ");n=Integer.parseInt(br.readLine());

np=n*n;for(int i=0;i<=n;i++)

for(int j=0;j<=n;j++) tabla[i][j]=LIBER;tabla[1][1]=1;if(incerc(2,1,1)==SUCCES) afisare();

else System.out.println("\nNu exista solutii !!!");System.out.println("\n\nNumar de incercari = "+ni);

// main

static void afisare()

System.out.println("\r----------------------------------");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 309/518

15.3. PROBLEME REZOLVATE 297

for(int i=1;i<=n;i++)

System.out.println();for(int j=1;j<=n;j++) System.out.print("\t"+tabla[i][j]);

// afisare()

static int incerc(int i, int x, int y)

int xu,yu,k,rezultatIncercare; ni++;k=1;rezultatIncercare=ESEC;while ((rezultatIncercare==ESEC)&&(k<=8))// miscari posibile cal

xu=x+a[k]; yu=y+b[k];if((xu>=1)&&(xu<=n)&&(yu>=1)&&(yu<=n))

if(tabla[xu][yu]==LIBER)

tabla[xu][yu]=i;// afisare();if (i<np)

rezultatIncercare=incerc(i+1,xu,yu);if(rezultatIncercare==ESEC) tabla[xu][yu]=LIBER;

else rezultatIncercare=SUCCES;

k++;// whilereturn rezultatIncercare;

// incerc()// class

Pe ecran apar urm˘ atoarele rezultate:

Dimensiunea tablei de sah [3..8] : 5----------------------------------

1 6 15 10 2114 9 20 5 1619 2 7 22 118 13 24 17 425 18 3 12 23

Numar de incercari = 8839

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 310/518

298 CAPITOLUL 15. METODA BACKTRACKING

15.3.5 Problema colorarii hart ¸ilor

Se consider a o hart a cu n t ari care trebuie colorat˘ a folosind m < n culori,astfel ıncˆat oricare dou˘a t ari vecine s a e colorate diferit. Relat ¸ia de vecin atatedintre t ari este ret inut˘a ıntr-o matrice n ×n ale carei elemente sunt:

vi,j =1 daca i este vecin a cu j0 daca i nu este vecin a cu j

Reprezentarea solut iilor : O solutie a problemei este o modalitate de col-orare a t a rilor si poate reprezentat˘ a printru-un vector x = ( x1 , x2 ,...,x n ) cux i ∈ 1, 2,...,m reprezentˆand culoarea asociat˘ a t arii i. Mult imile de valor aleelementelor sint A1 = A2 = ... = An = 1, 2,...,m .

Restrict ii si condit ii de continuare : Restrict ia ca dou a t ari vecine s a e col-orate diferit se specic˘a prin: x i = x j pentru orice i si j avand proprietatea vi,j = 1.Condit ia de continuare pe care trebuie s˘ a o satisfac a solut ia part¸ial a ( x1 , x2 ,...,x k )este: xk = x i pentru orice i < k cu proprietatea c˘ a vi,k = 1.

class ColorareHartiI1

static int nrCulori=3;// culorile sunt 1,2,3static int[][] harta=

// CoCaIaBrTu2,1,1,1,1,// Constanta (0)1,2,1,0,0,// Calarasi (1)1,1,2,1,0,// Ialomita (2)

1,0,1,2,1,// Braila (3)1,0,0,1,2 // Tulcea (4);

static int n=harta.length;static int[] culoare=new int[n];static int nrVar=0;

public static void main(String[] args)

harta();if(nrVar==0)

System.out.println("Nu se poate colora !"); // main

static void harta()

int k; // indicele pentru taraboolean okk;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 311/518

15.3. PROBLEME REZOLVATE 299

k=0; // prima pozitieculoare[k]=0; // tara k nu este colorata (inca)while (k>-1) // -1 = iesit in stanga !!!

okk=false;while(culoare[k] < nrCulori)// selectez o culoare

++culoare[k];okk=posibil(k);if (okk) break;

if (!okk)

k--;else if (k == (n-1))

afis();else culoare[++k]=0;

// harta

static boolean posibil(int k)

for(int i=0;i<=k-1;i++)if((culoare[k]==culoare[i])&&(harta[i][k]==1))

return false;return true;

// posibil

static void afis()

System.out.print(++nrVar+" : ");for(int i=0;i<n;i++)

System.out.print(culoare[i]+" ");System.out.println();

// scrieRez // class

Pentru 3 culori rezultatele care apar pe ecran sunt:

1 1 2 3 2 32 1 3 2 3 23 2 1 3 1 34 2 3 1 3 15 3 1 2 1 26 3 2 1 2 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 312/518

300 CAPITOLUL 15. METODA BACKTRACKING

class ColorareHartiR1

static int[] x;static int[][] a=

0,0,0,0,0,0,0,2,1,1,1,1,// Constanta (1)0,1,2,1,0,0,// Calarasi (2)0,1,1,2,1,0,// Ialomita (3)0,1,0,1,2,1,// Braila (4)0,1,0,0,1,2 // Tulcea (5)

;static int n,m,nv=0;

public static void main(String[] args)

n=a.length-1; m=3; // nr culorix=new int[n+1];f(1);

static void f(int k)

boolean ok;int i,j;

for(i=1;i<=m;i++)ok=true;for(j=1;j<k;j++)

if((i==x[j])&&(a[j][k]==1)) ok=false; break;if(!ok) continue;x[k]=i;if(k<n) f(k+1); else afisv();

static void afisv()

System.out.print(++nv+" : ");for(int i=1; i<=n; i++) System.out.print(x[i]+" ");System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 313/518

15.3. PROBLEME REZOLVATE 301

15.3.6 Problema vecinilor

Un grup de n persoane sunt asezate pe un rˆ and de scaune. Intre oricare doivecini izbucnesc conicte. Rearanjat ¸i persoanele pe scaune astfel ıncˆ at ıntre oricaredoi vecini ”certat¸i” s a existe una sau cel mult dou˘ a persoane cu care nu au apucatsa se certe! Asat¸i toate variantele de reasezare posibile.

Vom rezolva problema prin metada backtracking. Presupunem c˘ a persoanelesunt numerotate la ınceput, de la stanga la dreapta cu 1 , 2,...,n . Consider am casolut ie un vector x cu n componente pentru care x i reprezint˘a ”pozit ia pe care seva aa persoana i dup a reasezare”.

Pentru k > 1 dat, condit iile de continuare sunt:

a) x j = xk , pentru j = 1 ,...,k −1 (x trebuie s a e permutare)

b) |xk −xk−1| = 2 sau 3 (ıntre persoana k si vecinul s au anterior trebuie s˘ a seae una sau dou˘a persoane)

In locul solutiei x vom lista permutarea y = x−1 unde yi reprezint˘a persoanacare se aseaz a pe locul i.

class VeciniR1

static int[] x;static int n,m,nsol=0;

public static void main(String[] args)

n=7, m=7;x=new int[n+1];f(1);

static void f(int k)

boolean ok;int i,j;for(i=1;i<=m;i++)

ok=true;for(j=1;j<k;j++) if(i==x[j]) ok=false; break;if(!ok) continue;if((Math.abs(i-x[k-1])!=2)&&(Math.abs(i-x[k-1])!=3)) continue;x[k]=i;if(k<n) f(k+1); else afis();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 314/518

302 CAPITOLUL 15. METODA BACKTRACKING

static void afis()

int i;System.out.print(++nsol+" : ");for(i=1; i<=n; i++) System.out.print(x[i]+" ");System.out.println();

import java.io.*;class Vecini

static int nrVar=0,n;static int[] x,y;

public static void main(String[] args) throws IOException

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

while ((n<3)||(n>50))

System.out.print("numar persoane [3..50] : ");n=Integer.parseInt(br.readLine());

x=new int[n];y=new int[n];reasez(0);if(nrVar==0) System.out.println("Nu se poate !!!");

// main

static void reasez(int k)

int i,j;boolean ok;if (k==n) scrieSolutia();// n=in afara vectorului !!!else for(i=0;i<n;i++)

ok=true;j=0;while ((j<k-1) && ok) ok=(i != x[j++]);if (k>0)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 315/518

15.3. PROBLEME REZOLVATE 303

ok=(ok&&((Math.abs(i-x[k-1])==2)||(Math.abs(i-x[k-1])==3)));if (ok) x[k]=i; reasez(k+1);

// reasez

static void scrieSolutia()

int i;for(i=0;i<n;i++) y[x[i]]=i;// inversarea permutarii !!!System.out.print(++nrVar+" : ");for(i=0;i<n;i++)

System.out.print(++y[i]+" "); // ca sa nu fie 0,1,...,n-1System.out.println(); // ci 1,2,...,n (la afisare)

// scrieRez // class

15.3.7 Problema labirintului

Se da un labirint sub form˘ a de matrice cu m linii si n coloane. Fiecare elemental matricei reprezint˘ a o camer a a labirintului. Intr-una din camere, de coordonatex0 si y0 se ga seste un om. Se cere s a se ga seasca toate iesirile din labirint.

O prim a problem a care se pune este precizarea modului de codicare aiesirilor din ecare camer˘ a a labirintului.

Dintr-o pozit¸ie oarecare ( i, j ) din labirint, deplasarea se poate face ın patrudirect ii: Nord, Est, Sud si Vest considerate ın aceast˘ a ordine (putem alege oricare

alt a ordine a celor patru direct ¸ii, dar odat˘a aleas a aceasta se p astreaz a pan a lasfarsitul problemei).Fiecare camer˘a din labirint poate caracterizat˘ a printr-un sir de patru cifre

binare asociate celor patru direct ¸ii, av and semnicat¸ie faptul c a acea camer a aresau nu iesiri pe direct¸iile considerate.

De exemplu, dac˘a pentru camera cu pozit ¸ia (2 , 4) exist a iesiri la N si S, ei ıiva corespunde sirul 1010 care reprezint˘ a num arul 10 ın baza zece.

Prin urmare, codic˘ am labirintul printr-o matrice a[i][ j ] cu elemente ıntre 1sai 15. Pentru a testa usor iesirea din labirint, matricea se bordeaz˘ a cu dou a liniisi dou a coloane de valoare egal˘a cu 16.

Ne punem problema determin˘ arii iesirilor pe care le are o camer˘a.O camer a are iesirea numai spre N dac˘ a si numai dac˘a a[i][ j ]&&8 = 0.Drumul parcurs la un moment dat se ret ¸ine ıntr-o matrice cu dou˘ a linii, d,

ın care:

−d[1][k] reprezint a linia camerei la care s-a ajuns la pasul k;

−d[2][k] reprezint a coloana camerei respective.La gasirea unei iesiri din labirint, drumul este asat.Principiul algoritmului este urm˘ atorul:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 316/518

304 CAPITOLUL 15. METODA BACKTRACKING

− se testeaz a dac a s-a iesit din labiritn (adic˘ a a[i][ j ] = 16);

−ın caz armativ se aseaz˘ a drumul g asit;

−ın caz contrar se procedeaz˘ a astfel:

• se retin ın matricea d coordonatele camerei vizitate;

• se verica dac a drumul arcurs a mai trecut prin aceast˘ a camer a, caz ıncare se iese din procedur˘a;

• se testeaz a pe r and iesirile spre N, E, S, V si acolo unde este g˘ asit a o astfelde iesire se reapeleaz˘a procedura cu noile coordonate;

• ınaintea iesirii din procedur˘ a se decrementeaz˘a valoarea lui k.

import java.io.*;class Labirint

static final char coridor=’.’, start=’x’,gard=’H’, pas=’*’, iesire=’E’;

static char[][] l;static int m,n,x0,y0;static boolean ok;

public static void main(String[] args) throws IOException

int i,j,k;StreamTokenizer st = new StreamTokenizer(

new BufferedReader(new FileReader("labirint.in")));st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;

l=new char[m][n];for(i=0;i<m;i++)

st.nextToken();for(j=0;j<n;j++) l[i][j]=st.sval.charAt(j);

st.nextToken(); x0=(int)st.nval;st.nextToken(); y0=(int)st.nval;

ok=false;gi(x0,y0);l[x0][y0]=start;PrintWriter out = new PrintWriter(

new BufferedWriter(new FileWriter("labirint.out")));for(i=0;i<m;i++)

if (i>0) out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 317/518

15.3. PROBLEME REZOLVATE 305

for(j=0;j<n;j++) out.print(l[i][j]);if (!ok) out.println("NU exista iesire !");out.close();

// main()

static void gi(int x,int y)

if ((x==0)||(x==n-1)||(y==0)||(y==m-1)) ok=true;else

l[x][y]=pas;if(l[x][y+1]==coridor||l[x][y+1]==iesire) gi(x,y+1);if(!ok&&(l[x+1][y]==coridor||l[x+1][y]==iesire)) gi(x+1,y);if(!ok&&(l[x][y-1]==coridor||l[x][y-1]==iesire)) gi(x,y-1);if(!ok&&(l[x-1][y]==coridor||l[x-1][y]==iesire)) gi(x-1,y);l[x][y]=coridor;

if (ok) l[x][y]=pas;

// class

De exemplu, pentru sierul de intrare: labirint.in

8 8HHHHHHEH

H....H.HH.HHHH.HH.HHHH.HH....H.HH.HHHH.HH......HHHHHHHEH2 2

se obtine sierul de iesire: labirint.out

HHHHHHEHH....H.HH*xHHH.HH*HHHH.HH*...H.HH*HHHH.HH******HHHHHHH*H

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 318/518

306 CAPITOLUL 15. METODA BACKTRACKING

15.3.8 Generarea partit ¸iilor unui numar natural

Sa se aseze toate modurile de descompunere a unui num˘ ar natural n casuma de numere naturale.

Vom folosi o procedur˘a f care are doi parametri: componenta la care s-aajuns ( k) si o valoare v (care cont ine diferent a care a mai r˘amas p an a la n).

Init ial, procedura este apelat˘ a pentru nivelul 1 si valoarea n. Imediat ce esteapelat˘a, procedura va apela o alta pentru asarea vectorului (init ¸ial aseaz˘a n).

Din valoarea care se g aseste pe un nivel, S [k], se scad pe r and valorile1, 2,...,S [k]−1, valori cu care se apeleaz˘a procedura pentru nivelul urm˘ ator.

La revenire se reface valoarea existent˘ a.

class PartitieNrGenerare // n = suma de numere

static int dim=0, nsol=0, n=6;static int[] x=new int[n+1];

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();f(n,n,1);t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp = "+(t2-t1)+"\n");

static void f(int val, int maxp, int poz)

if(maxp==1) nsol++; dim=poz-1; afis2(val,maxp); return; if(val==0) nsol++; dim=poz-1; afis1(); return; int maxok=min(maxp,val);for(int i=maxok;i>=1;i--)

x[poz]=i;f(val-i,min(val-i,i),poz+1);

static void afis1()

System.out.print("\n"+nsol+" : ");for(int i=1;i<=dim;i++) System.out.print(x[i]+" ");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 319/518

15.3. PROBLEME REZOLVATE 307

static void afis2(int val,int maxip)

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");for(i=1;i<=val;i++) System.out.print("1 ");

static int min(int a,int b) return (a<b)?a:b;

Pentru descompunerea ca sum˘ a de numere impare, programul este:

class PartitieNrImpare1 // n = suma de numere impare // nsol = 38328320 1Gata!!! timp = 8482

static int dim=0,nsol=0;static int[] x=new int[161];

public static void main(String[] args)

long t1,t2;int n=160, maxi=((n-1)/2)*2+1;t1=System.currentTimeMillis();f(n,maxi,1);t2=System.currentTimeMillis();

System.out.println("nsol = "+nsol+" timp = "+(t2-t1)+"\n");

static void f(int val, int maxip, int poz)

if(maxip==1)

nsol++;// dim=poz-1;// afis2(val,maxip);

return;if(val==0)

nsol++;// dim=poz-1; afis1();return;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 320/518

308 CAPITOLUL 15. METODA BACKTRACKING

int maxi=((val-1)/2)*2+1;int maxiok=min(maxip,maxi);for(int i=maxiok;i>=1;i=i-2)

x[poz]=i;f(val-i,min(maxiok,i),poz+1);

static void afis1()

System.out.print("\n"+nsol+" : ");for(int i=1;i<=dim;i++) System.out.print(x[i]+" ");

static void afis2(int val,int maxip)

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");for(i=1;i<=val;i++) System.out.print("1 ");

static int max(int a,int b) return (a>b)?a:b; static int min(int a,int b) return (a<b)?a:b;

// class

O versiune optimizat˘ a este:

class PartitieNrImpare2 // n = suma de numere impare ; // optimizat timp la jumatate !!!

static int dim=0,nsol=0; // nsol = 38328320 2Gata!!! timp = 4787static int[] x=new int[161];

public static void main(String[] args)

long t1,t2;int n=160, maxi=((n-1)/2)*2+1;t1=System.currentTimeMillis();f(n,maxi,1);t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp= "+(t2-t1));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 321/518

15.3. PROBLEME REZOLVATE 309

static void f(int val, int maxip, int poz)

if(maxip==1)

nsol++;// dim=poz-1; afis2(val);return;

if(val==0)

nsol++;// dim=poz-1; afis1();return;

int maxi=((val-1)/2)*2+1;int maxiok=min(maxip,maxi);for(int i=maxiok;i>=3;i=i-2)

x[poz]=i;f(val-i,i,poz+1);

nsol++;// dim=poz-1;// afis2(val);

static void afis1()

System.out.print("\n"+nsol+" : ");for(int i=1;i<=dim;i++) System.out.print(x[i]+" ");

static void afis2(int val)

System.out.print("\n"+nsol+" : ");for(int i=1;i<=dim;i++) System.out.print(x[i]+" ");for(int i=1;i<=val;i++) System.out.print("1 ");

static int max(int a,int b) return (a>b)?a:b; static int min(int a,int b) return (a<b)?a:b;

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 322/518

310 CAPITOLUL 15. METODA BACKTRACKING

15.3.9 Problema parantezelor

Problema cere generarea tuturor combinat ¸iilor de 2 n paranteze ( n parantezede deschidere si n paranteze de ınchidere) care se ınchid corect.

class ParantezeGenerare // 2*n paranteze

static int nsol=0;static int n=4;static int n2=2*n;static int[] x=new int[n2+1];

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();f(1,0,0);t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp = "+(t2-t1)+"\n");

static void f(int k, int npd, int npi)

if(k>n2) afis();else

if(npd<n) x[k]=1; f(k+1,npd+1,npi); if(npi<npd) x[k]=2; f(k+1,npd,npi+1);

static void afis()

int k;System.out.print(++nsol+" : ");for(k=1;k<=n2;k++)

if(x[k]==1) System.out.print("( ");else System.out.print(") ");

System.out.println();

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 323/518

15.3. PROBLEME REZOLVATE 311

15.3.10 Algoritmul DFS de parcurgere a grafurilor

Algoritmul DFS de parcurgerea in adˆ ancime a grafurilor neorientate folosestetehnica backtrackink.

import java.io.*; // arborele DFS (parcurgere in adancime)class DFS // momentele de descoperire si finalizare a nodurilor // drum intre doua varfuri

static final int WHITE=0, GRAY=1, BLACK=2;static int n,m,t;static int[] d,f,p,color; // descoperit,finalizat,predecesor,culoarestatic int[][] a;

public static void main(String[] args) throws IOException

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("dfs.in")));

int i,j,k,nods,nodd; // nods=nod_start_DFS, nod_destinatie (drum!)

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;st.nextToken(); nods=(int)st.nval;st.nextToken(); nodd=(int)st.nval;

a=new int[n+1][n+1];

d=new int[n+1];f=new int[n+1];p=new int[n+1];color=new int[n+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=1;a[j][i]=1;

for(i=1;i<=n;i++) // oricum erau initializati implicit, dar ... !!!

color[i]=WHITE;p[i]=-1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 324/518

312 CAPITOLUL 15. METODA BACKTRACKING

t=0;dfs(nods);

System.out.print("drum : "); drum(nodd); System.out.println();System.out.print("Descoperit :\t"); afisv(d);System.out.print("Finalizat :\t"); afisv(f);

//main

static void dfs(int u)

int v;color[u]=GRAY;d[u]=++t;for(v=1;v<=n;v++) // listele de adiacenta ... !!!if(a[u][v]==1) // v in Ad(u) !!!

if(color[v]==WHITE)

p[v]=u;dfs(v);

color[u]=BLACK;f[u]=++t;

//dfs

static void drum(int u) // nod_sursa ---> nod_destinatie

if(p[u]!=-1) drum(p[u]);System.out.print(u+" ");

// drum(...)

static void afisv(int[] x)

int i;for(i=1;i<=n;i++) System.out.print(x[i]+"\t");System.out.println();

//class

/*6 7 3 4 drum : 3 1 41 4 Descoperit : 2 5 1 3 4 84 6 Finalizat : 11 6 12 10 7 96 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 325/518

15.3. PROBLEME REZOLVATE 313

5 32 51 34 5*/

15.3.11 Determinarea componentelor conexeimport java.io.*; // determinarea componentelor conexeclass CompConexe

static int n,m,ncc;static int [] cc;static int[][] a;

public static void main(String[] args) throws IOException

int i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("compConexe.in")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

a=new int[n+1][n+1];

for(k=1;k<=m;k++)st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=a[j][i]=1;

cc=new int[n+1];

ncc=0;for(i=1;i<=n;i++)

if(cc[i]==0)

ncc++;conex(i);

for(i=1;i<=ncc;i++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 326/518

314 CAPITOLUL 15. METODA BACKTRACKING

System.out.print(i+" : ");for(j=1;j<=n;j++)

if(cc[j]==i)System.out.print(j+" ");

System.out.println();

//main

static void conex(int u)

cc[u]=ncc;for(int v=1;v<=n;v++)

if((a[u][v]==1)&&(cc[v]==0))conex(v);

//conex//class

/*9 7 1 : 1 2 31 2 2 : 4 52 3 3 : 6 7 8 93 14 56 77 8

8 9*/

15.3.12 Determinarea componentelor tare conexe// determinarea componentelor tare conexe (in graf orientat!)// Algoritm: 1. dfs(G) pentru calculul f[u]// 2. dfs(G_transpus) in ordinea descrescatoare a valorilor f[u]// OBS: G_transpus are arcele din G "intoarse ca sens"// Lista este chiar o sortare topologica !!!

import java.io.*;class CompTareConexe

static final int WHITE=0, GRAY=1, BLACK=2;static int n,m,t=0,nctc,pozLista;static int [] ctc,f,color,lista;static int[][] a; // matricea grafului

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 327/518

15.3. PROBLEME REZOLVATE 315

static int[][] at; // matricea grafului transpus (se poate folosi numai a !)

public static void main(String[] args) throws IOException

int i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("compTareConexe.in")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

a=new int[n+1][n+1]; at=new int[n+1][n+1]; ctc=new int[n+1];f=new int[n+1]; lista=new int[n+1]; color=new int[n+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=1;at[j][i]=1; // transpusa

for(i=1;i<=n;i++) color[i]=WHITE;

pozLista=n;for(i=1;i<=n;i++) if(color[i]==WHITE) dfsa(i);

nctc=0;for(i=1;i<=n;i++) color[i]=WHITE;for(i=1;i<=n;i++)

if(color[lista[i]]==WHITE) nctc++; dfsat(lista[i]);

for(i=1;i<=nctc;i++)

System.out.print(i+" : ");for(j=1;j<=n;j++) if(ctc[j]==i) System.out.print(j+" ");System.out.println();

//main

static void dfsa(int u)

int v;color[u]=GRAY;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 328/518

316 CAPITOLUL 15. METODA BACKTRACKING

for(v=1;v<=n;v++) if((a[u][v]==1)&&(color[v]==WHITE)) dfsa(v);color[u]=BLACK; f[u]=++t; lista[pozLista--]=u;

static void dfsat(int u) // se poate folosi "a" inversand arcele !

int j;color[u]=GRAY;ctc[u]=nctc;for(j=1;j<=n;j++)if((at[u][lista[j]]==1)&&(color[lista[j]]==WHITE)) dfsat(lista[j]); //"at"//if((a[lista[j]][u]==1)&&(color[lista[j]]==WHITE)) dfsat(lista[j]); //"a"color[u]=BLACK;

//class

/*9 10 1 : 6 7 81 2 2 : 92 3 3 : 4 53 1 4 : 1 2 34 56 77 88 95 4

7 68 7*/

15.3.13 Sortare topologica

Folosind parcurgerea ın adancime

// Sortare Topologica = ordonare lineara a varfurilor (in digraf)// (u,v)=arc ==> "... u ... v ..." in lista ("u se termina inaintea lui v")// Algoritm: 1. DFS pentru calcul f[u], u=nod// 2. cand u=terminat ==> plasaz in lista pe prima pozitie libera// de la sfarsit catre inceput// Solutia nu este unica (cea mai mica lexicografic = ???)// O(n*n)= cu matrice de adiacenta// O(n+m)= cu liste de adiacenta

import java.io.*;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 329/518

15.3. PROBLEME REZOLVATE 317

class SortTopoDFS

static final int WHITE=0, GRAY=1, BLACK=2;static int n,m,t,pozl; // varfuri, muchii, time, pozitie in listastatic int[] d; // descoperitstatic int[] f; // finalizatstatic int[] color; // culoarestatic int[] lista; // listastatic int[][] a; // matricea de adiacenta

public static void main(String[] args) throws IOException

int i,j,k,nods; // nods=nod_start_DFSStreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("sortTopo.in")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

a=new int[n+1][n+1]; d=new int[n+1]; f=new int[n+1];color=new int[n+1]; lista=new int[n+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;

a[i][j]=1;

for(i=1;i<=n;i++) color[i]=WHITE;t=0;pozl=n;for(nods=1;nods<=n;nods++)

if(color[nods]==WHITE) dfs(nods);

for(i=1;i<=n;i++) System.out.print(lista[i]+" ");System.out.println();

//main

static void dfs(int u)

int v;color[u]=GRAY;d[u]=++t;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 330/518

318 CAPITOLUL 15. METODA BACKTRACKING

for(v=1;v<=n;v++) // mai bine cu liste de adiacenta ... !!!if(a[u][v]==1) // v in Ad(u) !!!

if(color[v]==WHITE) dfs(v);color[u]=BLACK;f[u]=++t;lista[pozl]=u;--pozl;

//dfs//class

/*6 4 5 6 3 4 1 26 31 23 45 6*/

Folosind gradele interioare

// Sortare Topologica = ordonare lineara a varfurilor (in digraf)// (u,v)=arc ==> "... u ... v ..." in lista ("u se termina inaintea lui v")// Algoritm: cat_timp exista noduri neplasate in lista// 1. aleg un nod u cu gi[u]=0 (gi=gradul interior)// 2. u --> lista (pe cea mai mica pozitie neocupata)// 3. decrementez toate gi[v], unde (u,v)=arc

// OBS: pentru prima solutie lexicografic: aleg u="cel mai mic" (heap!)// OBS: Algoritm="stergerea repetata a nodurilor de grad zero"

import java.io.*;class SortTopoGRAD

static final int WHITE=0, BLACK=1; // color[u]=BLACK ==> u in listastatic int n,m,pozl; // varfuri, muchii, pozitie in listastatic int[] color; // culoarestatic int[] lista; // listastatic int[] gi; // grad interiorstatic int[][] a; // matricea de adiacenta

public static void main(String[] args) throws IOException

int u,i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("sortTopo.in")));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 331/518

15.3. PROBLEME REZOLVATE 319

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

a=new int[n+1][n+1];color=new int[n+1];lista=new int[n+1];gi=new int[n+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=1;gi[j]++;

for(i=1;i<=n;i++) color[i]=WHITE;pozl=1;for(k=1;k<=n;k++) // pun cate un nod in lista

u=nodgi0(); micsorezGrade(u);lista[pozl++]=u;color[u]=BLACK;

for(i=1;i<=n;i++) System.out.print(lista[i]+" ");System.out.println();

//main

static int nodgi0() // nod cu gradul interior zero

int v,nod=-1;for(v=1;v<=n;v++) // coada cu prioritati (heap) este mai buna !!!if(color[v]==WHITE)

if(gi[v]==0) nod=v; break;return nod;

static void micsorezGrade(int u)

int v;for(v=1;v<=n;v++) // lista de adiacenta este mai buna !!!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 332/518

320 CAPITOLUL 15. METODA BACKTRACKING

if(color[v]==WHITE)if(a[u][v]==1) gi[v]--;

//class

/*6 4 1 2 5 6 3 46 31 23 45 6*/

15.3.14 Determinarea nodurilor de separareimport java.io.*; // determinarea nodurilor care strica conexitateaclass NoduriSeparare // in graf neorientat conex

static int n,m;static int [] cc;static int[][] a;

public static void main(String[] args) throws IOException

int i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("noduriSeparare.in")));PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("noduriSeparare.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;a=new int[n+1][n+1];for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;a[i][j]=a[j][i]=1;

for(i=1;i<=n;i++) if(!econex(i)) System.out.print(i+" ");out.close();

//main

static boolean econex(int nodscos)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 333/518

15.3. PROBLEME REZOLVATE 321

int i, ncc=0;int[] cc=new int[n+1];

for(i=1;i<=n;i++)if(i!=nodscos)

if(cc[i]==0)

ncc++;if(ncc>1) break;conex(i,ncc,cc,nodscos);

if(ncc>1) return false; else return true;

// econex()

static void conex(int u,int et,int[]cc,int nodscos)

cc[u]=et;for(int v=1;v<=n;v++)

if(v!=nodscos)if((a[u][v]==1)&&(cc[v]==0)) conex(v,et,cc,nodscos);

//conex//class

15.3.15 Determinarea muchiilor de rupereimport java.io.*; // determinarea muchiilor care strica conexitatea

class MuchieRupere // in graf neorientat conexstatic int n,m; static int [] cc; static int[][]a;

public static void main(String[] args) throws IOException

int i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("muchieRupere.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("muchieRupere.out")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;a=new int[n+1][n+1];for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 334/518

322 CAPITOLUL 15. METODA BACKTRACKING

a[i][j]=1; a[j][i]=1;for(i=1;i<=n;i++)

for(j=i+1;j<=n;j++)

if(a[i][j]==0) continue;a[i][j]=a[j][i]=0;if(!econex()) System.out.println(i+" "+j);a[i][j]=a[j][i]=1;

out.close();

//main

static boolean econex()

int i, ncc;cc=new int[n+1];ncc=0;for(i=1;i<=n;i++)

if(cc[i]==0)

ncc++;if(ncc>1) break;conex(i,ncc);

if(ncc==1) return true; else return false;// econex()

static void conex(int u,int et)

cc[u]=et;for(int v=1;v<=n;v++)

if((a[u][v]==1)&&(cc[v]==0))conex(v,et);

//conex//class

/*9 10 1 87 2 2 75 1 3 91 8 7 9

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 335/518

15.3. PROBLEME REZOLVATE 323

9 46 96 44 19 59 79 3*/

15.3.16 Determinarea componentelor biconexe// Componenta biconexa = componenta conexa maximala fara muchii de rupereimport java.io.*; // noduri = 1,...,nclass Biconex // liste de adiacenta pentru graf

// vs=varf stiva; m=muchii; ncb=nr componente biconexe// ndr=nr descendenti radacina (in arbore DFS), t=time in parcurgerea DFS

static final int WHITE=0, GRAY=1,BLACK=2;static int n,ncb,t,ndr,vs,m=0,root; // root=radacina arborelui DFSstatic int[][] G; // liste de adiacentastatic int[] grad,low,d; // grad nod, low[], d[u]=moment descoperire nod ustatic int[][] B; // componente biconexestatic int[] A; // puncte de articularestatic int[] color; // culoarea noduluistatic int[] fs,ts; // fs=fiu stiva; ts=tata stiva

public static void main(String[] args) throws IOException

init();root=3; // radacina arborelui (de unde declansez DFS)vs=0; // pozitia varfului stivei unde este deja incarcat un nod (root)fs[vs]=root; // pun in stiva "root" sits[vs]=0; // tata_root=0 (nu are!)t=0; // initializare time; numerotarea nodurilor in DFS

dfs(root,0); // (u,tatau) tatau=0 ==> nu exista tatauif(ncb==1) System.out.println("Graful este Biconex");else

System.out.println("Graful NU este Biconex");if(ndr>1) A[root]=1;System.out.print("Puncte de articulare : ");afisv(A);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 336/518

324 CAPITOLUL 15. METODA BACKTRACKING

System.out.print("Numar componente Biconexe : ");System.out.println(ncb);for(int i=1;i<=ncb;i++)

System.out.print("Componenta Biconexa "+i+" : ");afisv(B[i]);

//main()

static int minim(int a, int b) return a<b?a:b; // minim()

static void init() throws IOException

int i,j,k;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("biconex.in")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

d=new int[n+1]; // vectorii sunt initializati cu zerolow=new int[n+1]; grad=new int[n+1]; color=new int[n+1]; // 0=WHITE !A=new int[n+1]; G=new int[n+1][n+1]; B=new int[n+1][n+1];fs=new int[m+1]; ts=new int[m+1];

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;G[i][++grad[i]]=j; G[j][++grad[j]]=i;

//Init()

static void dfs(int u, int tatau) /* calculeaza d si low */

int fiuu,i;

d[u]=++t;color[u]=GRAY;low[u]=d[u];

for(i=1;i<=grad[u];i++)

fiuu=G[u][i]; // fiuu = un descendent al lui u

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 337/518

15.3. PROBLEME REZOLVATE 325

if(fiuu==tatau) continue; // este aceeasi muchieif((color[fiuu]==WHITE)|| // fiuu nedescoperit sau

(d[fiuu]<d[u])) // (u,fiuu) este muchie de intoarcere

/* insereaza in stiva muchia (u,fiuu) */vs++;fs[vs]=fiuu;ts[vs]=u;

if(color[fiuu]==WHITE) /* fiuu nu a mai fost vizitat */

if(u==root) ndr++; // root=caz special (maresc nrfiiroot)

dfs(fiuu,u);

// acum este terminat tot subarborele cu radacina fiuu !!!low[u]=minim(low[u],low[fiuu]);if(low[fiuu]>=d[u])

// "=" ==> fiuu intors in u ==> ciclu "agatat" in u !!!// ">" ==> fiuu nu are drum de rezerva !!!

/* u este un punct de articulatie; am identificat o componenta

biconexa ce contine muchiile din stiva pana la (u,fiuu) */if(low[fiuu]!=low[u]) // (u,fiuu) = bridge (pod)

System.out.println("Bridge: "+fiuu+" "+u);if(u!=root) A[u]=1; // root = caz special

compBiconexa(fiuu,u);else // (u,fiuu) = back edge

low[u]=minim(low[u],d[fiuu]);color[u]=BLACK;

// dfs(...)

static void compBiconexa(int fiu, int tata)

int tatas,fius;ncb++;do

tatas=ts[vs]; fius=fs[vs];vs--;B[ncb][tatas]=1; B[ncb][fius]=1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 338/518

326 CAPITOLUL 15. METODA BACKTRACKING

while(!((tata==tatas)&&(fiu==fius))); // compBiconexa(...)

static void afisv(int[] x) // indicii i pentru care x[i]=1;

for(int i=1;i<=n;i++) if(x[i]==1) System.out.print(i+" ");System.out.println();

// afisv(...)//class

/*8 9 <-- n m Bridge: 8 11 8 8 Bridge: 5 31 2 | Graful NU este Biconex1 3 6 1 Puncte de articulare : 1 3 53 4 | \ / \ Numar componente Biconexe : 42 4 | 5 --- 3 2 Componenta Biconexa 1 : 1 83 5 | / \ / Componenta Biconexa 2 : 1 2 3 45 7 7 4 Componenta Biconexa 3 : 5 6 75 6 Componenta Biconexa 4 : 3 56 7*/

15.3.17 Triangulat ¸ii - OJI2002 clasa a X-a

O triangulat¸ie a unui poligon convex este o mult¸ime format˘a din diagonaleale poligonului care nu se intersecteaz˘ a ın interiorul poligonului ci numai ın vˆ arfurisi care ımpart toat˘ a suprafat a poligonului ın triunghiuri.

Fiind dat un poligon cu n varfuri notate 1 , 2,...,n sa se genereze toatetriangulat¸iile distincte ale poligonului. Dou˘ a triangulat¸ii sunt distincte dac˘ a diferaprin cel put in o diagonal˘a.

Datele de intrare : ın sierul text triang.in se aa pe prima linie un singurnum ar natural reprezentˆ and valoarea lui n (n ≤11).

Datele de iesire : ın sierul text triang.out se vor scrie:- pe prima linie, num˘arul de triangulat ¸ii distincte;- pe ecare din urm atoarele linii c ate o triangulat ¸ie descris a prin diagonalele

ce o compun. O diagonal˘a va precizat˘a prin dou a numere reprezentˆ and cele dou avarfuri care o denesc; cele dou˘a numere ce denesc o diagonal˘a se despart princel put in un spat¸iu, iar ıntre perechile de numere ce reprezint˘ a diagonalele dintr-otriangulat¸ie se va l asa de asemenea minimum un spat ¸iu.

Exemplu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 339/518

15.3. PROBLEME REZOLVATE 327

triang.in triang.out5 5

1 3 1 42 4 2 55 2 5 33 5 3 14 2 1 4

Timp maxim de executare:

7 secunde/test pe un calculator la 133 MHz.3 secunde/test pe un calculator la peste 500 MHz.

Rezolvare detaliat˘ a

Se genereaza toate combinatiile de diagonale care formeaza o triangulat ¸ie.

import java.io.*; // merge si n=12 in 3 secclass Triangulatii

static int n; // numar varfuri poligonstatic int ndt=n-3; // numar diagonale in triangulatie

static int nd=n*(n-3)/2; // numarul tuturor diagonalelorstatic int[] x;static int[] v1,v2;static int nsol=0;static PrintWriter out;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("triang.in")));out=new PrintWriter(new BufferedWriter(new FileWriter("triang.out")));st.nextToken(); n=(int)st.nval;ndt=n-3;nd=n*(n-3)/2;x=new int[ndt+1];v1=new int[nd+1];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 340/518

328 CAPITOLUL 15. METODA BACKTRACKING

v2=new int[nd+1];

if(n==3) out.println(0);else

out.println(catalan(n-2));diagonale();f(1);

out.close();t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" Timp = "+(t2-t1));

static void afisd() throws IOException

int i;++nsol;for(i=1;i<=ndt;i++) out.print(v1[x[i]]+" "+v2[x[i]]+" ");out.println();

static void diagonale()

int i,j,k=0;i=1;

for(j=3;j<=n-1;j++) v1[++k]=i; v2[k]=j;

for(i=2;i<=n-2;i++)for(j=i+2;j<=n;j++)v1[++k]=i; v2[k]=j;

static boolean seIntersecteaza(int k, int i)

int j; // i si x[j] sunt diagonalele !!!for(j=1;j<=k-1;j++)if(((v1[x[j]]<v1[i])&&(v1[i]<v2[x[j]])&&(v2[x[j]]<v2[i]) )||

((v1[i]<v1[x[j]])&&(v1[x[j]]<v2[i])&&(v2[i]<v2[x[j]])))return true;

return false;

static void f(int k) throws IOException

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 341/518

15.3. PROBLEME REZOLVATE 329

int i;for(i=x[k-1]+1; i<=nd-ndt+k; i++)

if(seIntersecteaza(k,i)) continue;x[k]=i;if(k<ndt) f(k+1); else afisd();

static int catalan(int n)

int rez;int i,j;int d;int[] x=new int[n+1];int[] y=new int[n+1];

for(i=2;i<=n;i++) x[i]=n+i;for(j=2;j<=n;j++) y[j]=j;

for(j=2;j<=n;j++)for(i=2;i<=n;i++)

d=cmmdc(y[j],x[i]);y[j]=y[j]/d;x[i]=x[i]/d;

if(y[j]==1) break;rez=1;for(i=2;i<=n;i++) rez*=x[i];return rez;

static int cmmdc (int a,int b)

int d,i,c,r;if(a>b) d=a;i=b; elsed=b;i=a;while(i!=0) c=d/i; r=d%i; d=i; i=r;return d;

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 342/518

330 CAPITOLUL 15. METODA BACKTRACKING

15.3.18 Partit ¸ie - ONI2003 clasa a X-a

Se deneste o partit ¸ie a unui num˘ar natural n ca ind o scriere a lui n subforma:

n = n1 + n2 + ... + n k , (k ≥1)

unde n1 , n 2 ,...,nk sunt numere naturale care veric˘ a urm atoarea relat ¸ie:

n1 ≥n2 ≥ ... ≥n i ≥ ... ≥nk ≥1

Cerint ¸aFiind dat un num˘ ar natural n, sa se determine cˆate partit¸ii ale lui se pot

scrie, conform cerint¸elor de mai sus, stiind c˘ a oricare num˘ar n i dintr-o partit ¸ie

trebuie s a e un num ar impar.Datele de intrareFisierul partitie.in contine pe prima linie num˘arul n

Datele de iesireFiserul partitie.out va cont ine pe prima linie num˘ arul de partit¸ii ale lui n

conform cerint elor problemei.

Restrict ii si precizari

• 1 ≤N ≤160

Exemplupartitie.in partitie.out

7 5Explicat ii:Cele cinci partit¸ii sunt:

• 1+1+1+1+1+1+1

• 1+1+1+1+3

• 1+1+5

• 1+3+3

• 7

Timp maxim de executare: 3 secunde/test

Indicat ¸ii de rezolvare *

Stelian Ciurea Problema se poate rezolva ın mai multe moduri:Solut ia comisiei se bazeaz a pe urm atoarele formule si teoreme de combina-

toric a:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 343/518

15.3. PROBLEME REZOLVATE 331

− num arul de partit ¸ii ale unui num˘ar n ın k part i (nu neap˘arat distincte)este

P (n, k ) = P (n −k, 1) + P (n −k, 2) + ... + P (n −k, k)

cu P (n, 1) = P (n, n ) = 1 si P (n, k ) = 0 dac a n < k .

−num arul de partit¸ii ale unui num˘a n ın k part i distincte este

P (n, k ) = P (n −k(k −1)/ 2, k)

−num arul de partit¸ii ale unui num˘ar n ın k part i impare care se pot si repetaeste egal cu num arul de partit¸ii ale unui num˘ar n ın k part i distincte.

Problema se poate rezolva si prin backtracking; f˘ ar a prea mari optimiz˘ ari sepoate obt ine rezultatul ın mai put ¸in de 3 secunde pentru n < 120. Pentru valorimai mari ale lui n , se poate l asa programul s˘a ruleze si se ret in rezultatele ıntr-unvector cu valori init¸iale.

Rezultatul pentru n = 160 are 8 cifre, deci nu este necesar˘ a implementareaoperat iilor cu numere mari!

Mihai Stroe, GInfo nr. 13/6 - octombrie 2003 Problema se poate rezolva ın mai multe moduri.O idee bun a de rezolvare a problemei const ın folosirea metodei program˘ arii

dinamice . Se poate construi o matrice A, unde Ai,k reprezint˘a num arul de partit ¸iiale num arului i cu numere impare, din care ultimul este cel mult egal cu k. Unelement din A se calculeaz a observ and c a o partit ie a lui i cu numere impare, celmult egale cu k, este format˘a dintr-un un num˘ ar M , mai mic sau egal cu k, si altenumere, mai mici sau egale cu M . De aici rezult a relat ia:

Ai,k

=M =1 ,...,k ; M ≤ i ;

M = impar

Ai−M,M

Init ial A0,0 este 1. La implementare, pentru a economisi spat ¸iu, se poate alegeo variant˘a ın care Ai,k sa reprezinte num˘arul de partit¸ii ale lui i cu numere impare,din care ultimul este cel mult egal cu al k-lea num ar impar, adic˘a 2 ·k −1.

Dup a calcularea elementelor matricei, solut ¸ia pentru num˘ aul i se gaseste ınAi,i . Aceste valori pot salvate ıntrun vector de constante, care este transformatıntr-un nou program, ın acelasi mod ca la problema ”Circular” de la clasa a IX-a.Aceast a metod a conduce la o rezolvare instantanee a testelor date ın concurs.

O alt a metod a, bazat˘a pe vectorul de constante, ar ınsemnat generareasolut iilor folosind metoda backtracking . Un backtracking l˘asat s a se execute ıntimpul concursului ar putut genera solut ¸iile pentru toate valorile lui N , dup acare se putea folosi metoda vectorului de constante, ın timp ce un backtrackingfolosit ca solut ie a problemei ar obinut punctajul maxim doar pentru testele micisi medii (pentru valori ale lui N mai mici dec at 130).

Limitele problemei si timpul de execuie de 3 secunde permit rezolv˘ arii prinbacktracking s bt ¸inerea unui punctaj mult ¸umitor.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 344/518

332 CAPITOLUL 15. METODA BACKTRACKING

Analiza complexit˘ at ii

Pentru o rezolvare care se bazeaz˘ a pe metoda vectorului de constante, ordinulde complexitate al solut ¸iei nale ar fost O(1); solut ia const˘a ınn citirea valoriilui N si asarea rezultatului memorat.

Solutia descris a anterior, bazat˘ a pe metoda program˘ arii dinamice, are ordinulde complexitate O(n3). Invit am cititorul s˘a caute metode mai eciente.

Ordinul de complexitate al unei solut ¸ii care se bazeaz a pe metoda backtrack-ing este exponent ial.

Codul sursa

class PartitieNrGenerare // n = suma de numere

static int dim=0,nsol=0;static int n=6;static int[] x=new int[n+1];

public static void main(String[] args)

long t1,t2;t1=System.currentTimeMillis();f(n,n,1);t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp = "+(t2-t1)+"\n");

// main(...)

static void f(int val, int maxp, int poz)

if(maxp==1)

nsol++;dim=poz-1;afis2(val,maxp);return;

if(val==0)

nsol++;dim=poz-1;afis1();return;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 345/518

15.3. PROBLEME REZOLVATE 333

int i;int maxok=min(maxp,val);for(i=maxok;i>=1;i--)

x[poz]=i;f(val-i,min(val-i,i),poz+1);

// f(...)

static void afis1()

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");

// afis1()

static void afis2(int val,int maxip)

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");for(i=1;i<=val;i++) System.out.print("1 ");

afis2(...)

static int min(int a,int b) return (a<b)?a:b;

// class

class PartitieNrImpare1 // n = suma de numere impare // nsol = 38328320 timp = 8482

static int dim=0,nsol=0;static int[] x=new int[161];

public static void main(String[] args)

long t1,t2;int n=160;int maxi=((n-1)/2)*2+1;t1=System.currentTimeMillis();f(n,maxi,1);t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp = "+(t2-t1)+"\n");

// main(...)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 346/518

334 CAPITOLUL 15. METODA BACKTRACKING

static void f(int val, int maxip, int poz)

if(maxip==1)

nsol++;// dim=poz-1;// afis2(val,maxip);return;

if(val==0)

nsol++;// dim=poz-1;// afis1();return;

int maxi=((val-1)/2)*2+1;int maxiok=min(maxip,maxi);int i;for(i=maxiok;i>=1;i=i-2)

x[poz]=i;f(val-i,min(maxiok,i),poz+1);

// f(...)

static void afis1()

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");

// afis1()

static void afis2(int val,int maxip)

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");for(i=1;i<=val;i++) System.out.print("1 ");

// afis2(...)

static int max(int a,int b) return (a>b)?a:b;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 347/518

15.3. PROBLEME REZOLVATE 335

static int min(int a,int b) return (a<b)?a:b; // class

import java.io.*;class PartitieNrImpare2 // n = suma de numere impare ; // nsol = 38328320 timp = 4787

static int dim=0,nsol=0;static int[] x=new int[161];

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int n,i;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("partitie.in")));PrintWriter out=new PrintWriter(new BufferedWriter(

new FileWriter("partitie.out")));

st.nextToken(); n=(int)st.nval;

int maxi=((n-1)/2)*2+1;f(n,maxi,1);

out.print(nsol);

out.close();t2=System.currentTimeMillis();System.out.println("nsol = "+nsol+" timp= "+(t2-t1));

// main(...)

static void f(int val, int maxip, int poz)

if(maxip==1)

nsol++;dim=poz-1;afis2(val);return;

if(val==0)

nsol++;dim=poz-1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 348/518

336 CAPITOLUL 15. METODA BACKTRACKING

//afis1();return;

int maxi=((val-1)/2)*2+1;int maxiok=min(maxip,maxi);int i;for(i=maxiok;i>=3;i=i-2)

x[poz]=i;f(val-i,i,poz+1);

nsol++;dim=poz-1;

//afis2(val);// f(...)

static void afis1()

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");

// afis1()

static void afis2(int val)

int i;System.out.print("\n"+nsol+" : ");for(i=1;i<=dim;i++) System.out.print(x[i]+" ");for(i=1;i<=val;i++) System.out.print("1 ");

// afis2(...)

static int max(int a,int b) return (a>b)?a:b;

static int min(int a,int b) return (a<b)?a:b; // class

15.3.19 Scut ¸a - ONI2003 clasa a X-a

Majoritatea participant ¸ilor la ONI2003 au auzit, ın copil˘ arie, povestea Scut¸eiRosii. Pentru cei care o stiu, urmeaz˘ a partea a doua; pentru cei care nu o stiu, nuva faceti griji, cunoasterea ei nu este necesar˘ a pentru a rezolva aceast˘ a problem a.Povestea nu spune ce s-a ıntˆ amplat pe drumul pe care Scut ¸a Rosie s-a ıntors de

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 349/518

15.3. PROBLEME REZOLVATE 337

la bunicut a. Vet i aa am anunte ın continuare.Pe drum, ea s-a ıntˆ alnit cu Lupul (fratele lupului care a p˘ ar asit povestea

ın prima parte). Acesta dorea s˘ a o man ance, dar a decis s˘a-i acorde o sans˘a descapare, provocˆand-o la un concurs de cules ciupercut ¸e.

Scuta Rosie se a˘a ın pozit¸ia (1 , 1) a unei matrice cu N linii si N coloane,ın ecare pozit¸ie a matricei ind amplasate ciupercut ¸e. Lupul se a a ın pozit¸ia(1, 1) a unei alte matrice similare. Pe parcursul unui minut, atˆ at Scut a, c at siLupul se deplaseaz˘a ıntr-una din pozit ¸iile vecine (pe linie sau pe coloan˘a) si culegciupercut ele din pozit ia respectiv˘a. Dac a Scuta Rosie ajunge ıntr-o pozit ie ıncare nu sunt ciupercut ¸e, va pierde jocul. Dac˘a la sfarsitul unui minut ea are maiput ine ciupercut¸e dec at Lupul, ea va pierde jocul de asemenea. Jocul ıncepe dup˘ ace amandoi participant ¸ii au cules ciupercut¸ele din pozit iile lor init iale (nu conteaz˘acine are mai multe la ınceputul jocului, ci doar dup˘ a un num ar ıntreg strict pozitivde minute de la ınceput). Dac˘ a Scuta Rosie pierde jocul, Lupul o va mˆ anca.

Inainte de ınceperea jocului, Scut ¸a Rosie l-a sunat pe Vˆ an ator, care i-apromis c a va veni ıntr-un sfert de ora (15 minute) pentru a o salva. Deci Scut ¸aRosie va liber˘a sa plece dac a nu va pierde jocul dup˘a 15 minute.

Din acest moment, scopul ei este nu numai s˘ a r aman a ın viat¸a, ci si sa culeag acat mai multe ciupercut ¸e, pentru a le duce acas˘ a (dup a ce va veni, v an atorul nu ova mai l asa sa culeag a).

Lupul, cunoscut pentru l˘ acomia sa proverbial˘a, va alege la ecare minut mu-tarea ın cˆampul vecin cu cele mai multe ciupercut ¸e (matricea sa este dat˘ a astfelınct s˘a nu existe mai multe posibilit˘ at i de alegere la un moment dat).

Povestea spune c˘a Scuta Rosie a plecat acas˘ a cu cosulet ul plin de ciupercut¸e,folosind indicat iile date de un program scris de un concurent la ONI 2003 (nu vomda detalii suplimentare despre alte aspecte, cum ar c˘ alatoria ın timp, pentru

a nu complica inutil enunt ¸ul problemei). S˘a fost acest program scris de c˘atredumneavoastr˘a? Vom vedea...Cerint ¸aScriet i un program care s˘a o ajute pe Scut a Rosie s˘a ramana ın joc si s a

culeaga cat mai multe ciupercut ¸e la sfarsitul celor 15 minute!Date de intrareFisierul scuta.in are urm atoarea structur˘ a:N - dimensiunea celor dou˘a matricea11 a12 ...a 1n -matricea din care culege Scut ¸a Rosiea21 a22 ...a 2n...an 1an 2 ...a nnb11 b12 ...b1n - matricea din care culege Lupulb21 b22 ...b2n...bn 1bn 2 ...bnnDate de iesireFisierul scuta.out are urm atoarea structur˘ a:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 350/518

338 CAPITOLUL 15. METODA BACKTRACKING

NR - numarul total de ciupercut ¸e culese

d1d2 ...d15 - direct iile pe care s-a deplasat Scut ¸a Rosie, separate prin cˆ ate unspat iu (direct¸iile pot N, E, S, V indicˆand deplas˘ari spre Nord, Est, Sud, Vest;pozitia (1 , 1) este situat˘a ın colt ul de Nord-Vest al matricei)

Restrict ¸ii

• 4 ≤N ≤10;

• valorile din ambele matrice sunt numere naturale mai mici decˆ at 256;

• nici Scuta Rosie si nici Lupul nu vor p˘ ar asi matricele corespunz˘ atoare;

• dup a ce unul din juc atori culege ciupercut¸ele dintr-o pozit¸ie, ın pozit¸iarespectiv˘a raman 0 ciupercut e;

• pe testele date, Scut¸a Rosie va avea ıntotdeauna posibilitatea de a rezista15 minute.

Exemplu

scuta.in scuta.out4 1372 2 3 4 SSSEEENVVNEENVV5 6 7 89 10 11 1213 14 15 161 2 3 45 6 7 89 10 11 1213 14 15 16

Explicat ¸ie:Scuta Rosie a efectuat aceleasi mut˘ ari cu cele efectuate de Lup si a avut tot

timpul o ciupercut¸a ın plus. In nal ea a cules toate ciupercut ¸ele din matrice.Timp maxim de executare: 1 secund a/test

Indicat ¸ii de rezolvare *

Mihai Stroe, GInfo nr. 13/6 - octombrie 2003 Problema se rezolv˘a folosind metoda backtracking ın plan.Se observa ca mut arile Lupului sunt independente de mut˘ arile Scut ei , astfel

ele pot determinate imediat dup˘ a citirea datelor.In acest punct al rezolv˘ arii, Scut a trebuie s a mute la ecare moment, astfel

ınc at s a raman a ın joc, iar ın nal s˘ a str anga cat mai multe ciupercut ¸e. Restrict¸iilesunt date de enunt ¸ul problemei si de num˘ arul de ciupercut¸e culese de Lup, careeste cunoscut la ecare moment.

Rezolvarea prin metoda backtracking ıncearc˘a la ecare pas, pe r and, ecaremutare din cele cel mult patru posibile (teoretic; de fapt, cel mult trei mut˘ ari suntposibile ın ecare moment, deoarece Scut ¸a nu se va ıntoarce ın pozit ¸ia din caretocmai a venit).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 351/518

15.3. PROBLEME REZOLVATE 339

Se urmareste respectarea restrict ¸iilor impuse. In momentul g˘asirii unei solut ii,aceasta este comparat˘ a cu solut ia optim˘a gasit a pan a atunci si dac˘ a este mai bun˘aeste ret inut˘a.

Inca nu a fost g asit a o rezolvare polinomial˘a pentru aceast˘ a problem a (si esteimprobabil ca o astfel de rezolvare s˘ a existe), dar limitele mici si faptul c˘ a num arulde mut ari disponibile ıncepe s˘ a scad a destul de repede, ın multe cazuri permit untimp de execut ie foarte bun.

Analiza complexit˘ at iiFie M num arul de mut˘ari pe care le are de efectuat Scut ¸a.Operat iile de citire si scriere a datelor au ordinul de complexitate O(N 2),

respectiv O(M ), deci nu vor luate ın calcul. Ordinul de complexitate este dat derezolvarea prin metoda backtracking .

Av and ın vedere c˘a la ecare pas Scut a poate alege dintre cel mult 3 mut˘ ari(deoarece nu se poate ıntoarce ın pozit ¸ia din care a venit), ordinul de complexitatear O(3M ). De fapt, num˘arul maxim de st˘ari examinate este mult mai mic; deexemplu, primele dou˘a mut ari ofer a dou a variante de alegere ın loc de trei. Alterestrict ii apar datorit˘ a limit arii la o matrice de 10 ·10 elemente.

Cum num arul M este cunoscut si mic, s-ar putea considera c˘ a ordinul decomplexitate este limitat superior, deci constant (constanta introdus˘ a ind totusidestul de mare).

Codul sursa

import java.io.*;

class Scufitastatic int n, maxc=0;static int[][] a,b;static int[] x,y;static char[] tc=new char[16];static char[] tmax=new char[16];

public static void main(String[] args) throws IOException

int i,j;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("scufita.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("scufita.out")));

st.nextToken(); n=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 352/518

340 CAPITOLUL 15. METODA BACKTRACKING

a=new int[n+2][n+2];b=new int[n+2][n+2];x=new int[17];y=new int[17];

for(i=1;i<=n;i++)for(j=1;j<=n;j++) st.nextToken(); a[i][j]=(int)st.nval;

for(i=1;i<=n;i++)for(j=1;j<=n;j++) st.nextToken(); b[i][j]=(int)st.nval;

culegeLupul(1,1,1);f(1,1,1);

out.println(maxc);for(i=1;i<=15;i++) out.print(tmax[i]);out.println();out.close();

// main()

static void f(int i, int j, int k) throws IOException

int aij=a[i][j];

x[k]=x[k-1]+a[i][j];a[i][j]=0;

if(k==16)if(x[16]>maxc)

maxc=x[16];for(int ii=1;ii<=15;ii++) tmax[ii]=tc[ii];

a[i][j]=aij;return;

if((a[i-1][j]>0)&&(a[i-1][j]+x[k]>=y[k+1])) tc[k]=’N’; f(i-1,j,k+1); if((a[i+1][j]>0)&&(a[i+1][j]+x[k]>=y[k+1])) tc[k]=’S’; f(i+1,j,k+1); if((a[i][j-1]>0)&&(a[i][j-1]+x[k]>=y[k+1])) tc[k]=’V’; f(i,j-1,k+1); if((a[i][j+1]>0)&&(a[i][j+1]+x[k]>=y[k+1])) tc[k]=’E’; f(i,j+1,k+1);

a[i][j]=aij;//f(...)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 353/518

15.3. PROBLEME REZOLVATE 341

static void culegeLupul(int i, int j, int k)

if(k>16) return;y[k]=y[k-1]+b[i][j];b[i][j]=0;if((b[i-1][j]>b[i+1][j])&&(b[i-1][j]>b[i][j-1])&&(b[i-1][j]>b[i][j+1]))

culegeLupul(i-1,j,k+1);else if((b[i+1][j]>b[i][j-1])&&(b[i+1][j]>b[i][j+1]))

culegeLupul(i+1,j,k+1);else if(b[i][j-1]>b[i][j+1])

culegeLupul(i,j-1,k+1);else culegeLupul(i,j+1,k+1);

// culegeLupul(...)// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 354/518

342 CAPITOLUL 15. METODA BACKTRACKING

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 355/518

Capitolul 16

Programare dinamica

16.1 Prezentare generala

Folosirea tehnicii program˘ arii dinamice solicit˘a experient a, intuit ie si abilit˘atimatematice. De foarte multe ori rezolv˘ arile date prin aceast˘ a tehnic a au ordin decomplexitate polinomial.

In literatura de specialitate exist˘ a dou a variante de prezentare a acesteitehnici. Prima dintre ele este mai degrab˘ a de natur˘a deductiv˘a pe cand a doua

foloseste g andirea inductiv˘ a.Prima variant˘ a se bazeaz a pe conceptul de subproblem˘ a . Sunt considerate

urm atoarele aspecte care caracterizeaz˘ a o rezolvare prin programare dinamic˘ a:

• Problema se poate descompune recursiv ın mai multe subprobleme care suntcaracterizate de optime part iale , iar optimul global se obtine prin combinarea acestor optime part iale .

• Subproblemele respective se suprapun . La un anumit nivel, dou˘ a sau maimulte subprobleme necesit˘ a rezolvarea unei aceeasi subprobleme. Pentru aevita risipa de timp rezultat˘ a ın urma unei implement˘ ari recursive, optimelepart iale se vor ret ine treptat, ın maniera bottom-up, ın anumite structuri dedate (tabele).

A doua variant˘a de prezentare face apel la conceptele intuitive de sistem, staresi decizie. O problem˘a este abordabil˘a folosind tehnica program˘ arii dinamice dac˘asatisface principiul de optimalitate sub una din formele prezentate ın continuare.

Fie secvent a de st ari S 0 , S 1 ,...,S n ale sistemului.

343

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 356/518

344 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

• Daca d1 , d2 ,...,d n este un sir optim de decizii care duc la trecerea sistemuluidin starea S

0ın starea S

n, atunci pentru orice i (1

≤i

≤n) d

i +1, d

i+2,...,dn

este un sir optim de decizii care duc la trecerea sistemului din starea S iın starea S n . Astfel, decizia di depinde de deciziile anterioare di+1 ,...,d n .Spunem c a se aplic a metoda ınainte .

• Daca d1 , d2 ,...,d n este un sir optim de decizii care duc la trecerea sistemuluidin starea S 0 ın starea S n , atunci pentru orice i (1 ≤ i ≤n) d1 , d2 ,...,d i esteun sir optim de decizii care duc la trecerea sistemului din starea S 0 ın stareaS i . Astfel, decizia di+1 depinde de deciziile anterioare d1 ,...,d i . Spunem c ase aplica metoda ınapoi .

• Daca d1 , d2 ,...,d n este un sir optim de decizii care duc la trecerea sistemuluidin starea S 0 ın starea S n , atunci pentru orice i (1 ≤ i ≤n) di +1 , di+2 ,...,d neste un sir optim de decizii care duc la trecerea sistemului din starea S i ınstarea S n si d1 , d2 ,...,d i este un sir optim de decizii care duc la trecereasistemului din starea S 0 ın starea S i . Spunem c a se aplica metoda mixt˘ a .

Indiferent de varianta de prezentare, rezolvarea prin programare dinamic˘ apresupune g˘asirea si rezolvarea unui sistem de recurent e. In prima variant˘ a avemrecurent e ıntre subprobleme , ın a doua variant˘ a avem recurent e ın sirul de decizii .In afara cazurilor ın care recurent ¸ele sunt evidente, este necesar˘ a si o justicaresau o demonstrat ¸ie a faptului c˘a aceste recurent¸e sunt cele corecte.

Deoarece rezolvarea prin recursivitate duce de cele mai multe ori la ordin decomplexitate exponent ¸ial, se folosesc tabele auxiliare pentru ret¸inerea optimelorpart iale iar spat¸iul de solut ii se parcurge ın ordinea cresc˘ atoare a dimensiunilorsubproblemelor. Folosirea acestor tabele d˘ a si numele tehnicii respective.

Aseman ator cu metoda ”divide et impera”, programarea dinamic˘ a rezolv aproblemele combinˆand solut iile unor subprobleme. Deosebirea const˘ a ın faptul c˘a”divide et impera” partit ¸ioneaz˘a problemaın subprobleme independente , le rezolva(de obicei recursiv) si apoi combin˘ a solut iile lor pentru a rezolva problema initial˘ a,ın timp ce programarea dinamic˘ a se aplica problemelor ale c aror subprobleme nu sunt independente , ele avand ”sub-subprobleme” comune. In aceast a situat ie, serezolva ecare ”sub-subproblem˘ a” o singur a dat a si se foloseste un tablou pentrua memora solut ia ei, evit andu-se recalcularea ei de cˆ ate ori subproblema reapare.

Algoritmul pentru rezolvarea unei probleme folosind programarea dinamic˘ ase dezvolta ın 4 etape:

1. caracterizarea unei solut ¸ii optime (identicarea unei modalit˘ ati optime derezolvare, care satisface una dintre formele principiului optimalit˘ at ii ),

2. denirea recursiv˘a a valorii unei solut ii optime,

3. calculul efectiv al valorii unei solut¸ii optime,

4. reconstituirea unei solut ¸ii pe baza informat¸iei calculate.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 357/518

16.2. PROBLEME REZOLVATE 345

16.2 Probleme rezolvate

16.2.1 Inmult ¸irea optimala a matricelor

Consider am n matrice A1 , A2 ,...,A n , de dimensiuni d0 ×d1 , d1 ×d2 , ...,dn −1 ×dn . Produsul A1 ×A2 ×... ×An se poate calcula ın diverse moduri, aplicˆ andasociativitatea operat ¸iei de ınmultire a matricelor.

Numim ınmult ire elementar˘ a ınmult¸irea a dou˘a elemente.In funct ie de modul de parantezare difer˘ a num arul de ınmult ¸iri elementare

necesare pentru calculul produsului A1 ×A2 ×... ×An .Se cere parantezare optimal˘ a a produsului A1

×A2

×...

×An (pentru care

costul , adic a num arul total de ınmult ¸iri elementare, s˘ a e minim).Exemplu :Pentru 3 matrice de dimensiuni (10 , 1000), (1000, 10) si (10 , 100), produsul

A1 ×A2 ×A3 se poate calcula ın dou˘ a moduri:

1. (A1 ×A2) ×A3 necesit and 1000000+10000=1010000 ınmult ¸iri elementare

2. A1 ×(A2 ×A3), necesit and 1000000+1000000=2000000 ınmult ¸iri.

Reamintim c˘a num arul de ınmult ¸iri elementare necesare pentru a ınmult ¸i omatrice A, avand n linii si m coloane, cu o matrice B , avand m linii si p coloane,este n∗m∗ p.

Solutie

1. Pentru a calcula A1 ×A2 ×...×An , ın nal trebuie s˘ a ınmult¸im dou a matrice,deci vom paranteza produsul astfel: ( A1 ×A2 ×... ×Ak ) ×(Ak+1 ×... ×An ).Aceast a observat ie se aplic a si produselor dintre paranteze. Prin urmare,subproblemele problemei init ¸iale constau ın determinarea parantez˘ arii opti-male a produselor de matrice de forma Ai ×Ai+1 ×... ×Aj , 1 ≤ i ≤ j ≤n.Observ am ca subproblemele nu sunt independente. De exemplu, calculareaprodusului Ai ×Ai+1 ×...×Aj si calcularea produsului Ai +1 ×Ai +2 ×...×Aj +1 ,au ca subproblem˘a comun a calcularea produsului Ai+1 ×... ×Aj .

2. Pentru a ret¸ine solut iile subproblemelor, vom utiliza o matrice M , cu n liniisi n coloane, cu semnicatia:

M [i][ j ] = num arul minim de ınmult ¸iri elementare necesare pentru a calculaprodusul Ai ×Ai+1 ×... ×Aj , 1 ≤ i ≤ j ≤n.

Evident, num˘arul minim de ınmult ¸iri necesare pentru a calcula A1 ×A2 ×... ×An este M [1][n].

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 358/518

346 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

3. Pentru ca parantezarea s˘ a e optimal a, parantezarea produselor A1 ×A2 ×...

×A

ksi A

k +1 ×...

×A

ntrebuie s a e de asemenea optimal˘a. Prin urmare

elementele matricei M trebuie s a satisfac a urmatoarea relat ¸ie de recurent¸a:

M [i][i] = 0, i = 1 , 2,...,n.

M [i][ j ] = mini≤k<j M [i][k] + M [k + 1][ j ] + d[i −1]×d[k]×d[ j ]

Cum interpret˘ am aceast˘a relat ie de recurent¸ a? Pentru a determina num˘ arulminim de ınmult ¸iri elementare pentru calculul produsului Ai ×Ai+1 ×...×Aj ,xam pozit ia de parantezare k ın toate modurile posibile (ıntre i si j −1), sialegem varianta care ne conduce la minim. Pentru o pozit ¸ie k xata, costulparantez˘arii este egal cu numarul de ınmult ¸iri elementare necesare pentrucalculul produsului Ai ×Ai+1 ×...×Ak , la care se adaug a num arul de ınmult ¸irielementare necesare pentru calculul produsului Ak +1

×...

×Aj si costul

ınmult¸irii celor dou a matrice rezultate ( di−1 ×dk ×dj ).Observ am ca numai jum˘atatea de deasupra diagonalei principale din M esteutilizat˘a. Pentru a construi solut ¸ia optim˘a este util a si ret inerea indicelui k,pentru care se obtine minimul. Nu vom considera un alt tablou, ci-l vomret ine, pe pozit ia simetric˘a fat a de diagonala principala ( M [ j ][i]).

4. Rezolvarea recursiv˘a a relat iei de recurent¸a este inecient˘a, datorit˘a faptu-lui ca subproblemele se suprapun, deci o abordare recursiv˘ a ar conduce larezolvarea aceleiasi subprobleme de mai multe ori. Prin urmare vom rezolvarelat ia de recurent¸a ın mod bottom-up: (determin˘ am parantezarea optimal˘ aa produselor de dou˘a matrice, apoi de 3 matrice, 4 matrice, etc).

import java.io.*;class InmOptimalaMatrice

static int nmax=20;static int m[][]=new int[100][100];static int p[]=new int[100];static int n,i,j,k,imin,min,v;

public static void paranteze(int i,int j)

int k;if(i<j)

k=m[j][i];if(i!=k)

System.out.print("(");paranteze(i,k);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 359/518

16.2. PROBLEME REZOLVATE 347

System.out.print(")");//ifelse paranteze(i,k);

System.out.print(" * ");

if(k+1!=j)

System.out.print("(");paranteze(k+1,j);System.out.print(")");

//ifelse paranteze(k+1,j);

//ifelse System.out.print("A"+i);

//paranteze

public static void main(String[]args) throws IOException

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

System.out.print("numarul matricelor: ");n=Integer.parseInt(br.readLine());

System.out.println("Dimensiunile matricelor:");for(i=1;i<=n+1;i++)

System.out.print("p["+i+"]=");p[i]=Integer.parseInt(br.readLine());

for(i=n;i>=1;i--)for(j=i+1;j<=n;j++)

min=m[i][i]+m[i+1][j]+p[i]*p[i+1]*p[j+1];imin=i;for(k=i+1;k<=j-1;k++)

v=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];if(min>v) min=v; imin=k;

m[i][j]=min; m[j][i]=imin;

//for i,j

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 360/518

348 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

System.out.println("Numarul minim de inmultiri este: "+m[1][n]);System.out.print("Ordinea inmultirilor: ");paranteze(1,n);System.out.println();

//main//class/*numarul matricelor: 8Dimensiunile matricelor:p[1]=2p[2]=8p[3]=3p[4]=2p[5]=7p[6]=2p[7]=5p[8]=3p[9]=7Numarul minim de inmultiri este: 180Ordinea inmultirilor: ((((A1 * A2) * A3) * (A4 * A5)) * (A6 * A7)) * A8*/

16.2.2 Subsir crescator maximal

Fie un sir A = ( a1, a

2,...,a

n). Numim subsir al sirului A o succesiune de

elemente din A, ın ordinea ın care acestea apar ın A:

a i 1 , a i 2 ,...,a i k , unde 1 ≤ i1 < i 2 < ... < i k ≤n.

Se cere determinarea unui subsir cresc˘ ator al sirului A, de lungime maxim˘a.De exemplu, pentru

A = (8 , 3, 6, 50, 10, 8, 100, 30, 60, 40, 80)

o solutie poate (3, 6, 10, 30, 60, 80).

Rezolvare1. Fie Ai 1 = ( a i 1

≤a i 2

≤...

≤a i k ) cel mai lung subsir cresc ator al

sirului A. Observ am c a el coincide cu cel mai lung subsir cresc ator al sirului(a i 1 , a i 1 +1 ,...,a n ). Evident Ai 2 = ( a i 2 ≤ a i 3 ≤ ... ≤ a i k ) este cel mai lung subsircrescator al lui ( a i 2 , a i 2 +1 ,...,a n ), etc. Prin urmare, o subproblem˘ a a problemeiinit iale const˘a ın determinarea celui mai lung subsir cresc˘ ator care ıncepe cu a i ,i = 1,..,n .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 361/518

16.2. PROBLEME REZOLVATE 349

Subproblemele nu sunt independente: pentru a determina cel mai lung subsircrescator care ıncepe cu a

i, este necesar s a determin˘am cele mai lungi subsiruri

crescatoare care ıncep cu a j , a i ≤a j , j = i + 1 ,.. ,n .2. Pentru a ret¸ine solut iile subproblemelor vom considera doi vectori l si poz,

ecare cu n componente, avˆand semnicat¸ia:l[i] =lungimea celui mai lung subsir cresc˘ ator care ıncepe cu a[i]; poz[i] =pozit ia elementului care urmeaz˘ a dup a a[i] ın cel mai lung subsir

crescator care ıncepe cu a[i], daca un astfel de element exist˘ a, sau −1 daca unastfel de element nu exist˘a.

3. Relat ia de recurent¸a care caracterizeaz˘ a substructura optimal˘ a a problemeieste:

l[n] = 1; poz[n] = −1;

l[i] = maxj = i +1 ,n 1 + l[ j ]|a[i] ≤a[ j ]

unde poz[i] = indicele j pentru care se obt¸ine maximul l[i].Rezolvam relat ia de recurent¸a ın mod bottom-up:

int i, j;l[n]=1;poz[n]=-1;for (i=n-1; i>0; i--)

for (l[i]=1, poz[i]=-1, j=i+1; j<=n; j++)if (a[i] <= a[j] && l[i]<1+l[j])

l[i]=1+l[j];poz[i]=j;

Pentru a determina solut ¸ia optim˘a a problemei, determin˘ am valoarea maxim˘adin vectorul l, apoi as am solut ia, ıncepˆand cu pozit ia maximului si utilizˆ andinformat iile memorate ın vectorul poz:

//determin maximul din vectorul lint max=l[1], pozmax=1;for (int i=2; i<=n; i++)

if (max<l[i])

max=l[i]; pozmax=i;cout<<"Lungimea celui mai lung subsir crescator: " <<max;cout<<"\nCel mai lung subsir:\n";for (i=pozmax; i!=-1; i=poz[i]) cout<<a[i]<<’ ’;

Secvent ele de program de mai sus sunt scrise ın c/C++.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 362/518

350 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

Programele urm˘ atoare sunt scrise ın Java:

import java.io.*;class SubsirCrescatorNumere

static int n;static int[] a;static int[] lg;static int[] poz;

public static void main(String []args) throws IOException

int i,j;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("SubsirCrescatorNumere.in")));PrintWriter out = new PrintWriter (

new BufferedWriter( new FileWriter("SubsirCrescatorNumere.out")));

st.nextToken();n=(int)st.nval;a=new int[n+1];lg=new int[n+1];poz=new int[n+1];for(i=1;i<=n;i++) st.nextToken(); a[i]=(int)st.nval; int max,jmax;lg[n]=1;for(i=n-1;i>=1;i--)

max=0;jmax=0;for(j=i+1;j<=n;j++)

if((a[i]<=a[j])&&(max<lg[j])) max=lg[j]; jmax=j; if(max!=0) lg[i]=1+max; poz[i]=jmax;

else lg[i]=1; max=0; jmax=0;for(j=1;j<=n;j++)

if(max<lg[j]) max=lg[j]; jmax=j; out.println(max);int k;j=jmax;for(k=1;k<=max;k++) out.print(a[j]+" "); j=poz[j]; out.close();

//main//class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 363/518

16.2. PROBLEME REZOLVATE 351

import java.io.*;class SubsirCrescatorLitere

public static void main(String[] args) throws IOException

int n,i,j,jmax,k,lmax=-1,pozmax=-1;int [] l,poz;String a;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("SubsirCrescatorLitere.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("SubsirCrescatorLitere.out")));st.nextToken();a=st.sval;n=a.length();out.println(a+" "+n);l=new int[n];//l[i]=lg.celui mai lung subsir care incepe cu a[i]poz=new int[n];//poz[i]=pozitia elementului care urmeaza dupa a[i]for(i=0;i<n;i++) poz[i]=-1;l[n-1]=1;poz[n-1]=-1;for(i=n-2;i>=0;i--)

jmax=i;for(j=i+1;j<n;j++)

if((a.charAt(i)<=a.charAt(j))&&(1+l[j]>1+l[jmax])) jmax=j;l[i]=1+l[jmax];poz[i]=jmax;if(l[i]>lmax) lmax=l[i]; pozmax=i;

out.print("Solutia ");k=pozmax;out.print("("+l[pozmax]+") : ");for(j=1;j<=lmax;j++)

out.print(a.charAt(k));k=poz[k];

out.close();

// main// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 364/518

352 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

16.2.3 Sum˘ a maxima ın triunghi de numere

Sa consider am un triunghi format din n linii (1 < n ≤ 100), ecare liniecontin and numere ıntregi din domeniul [1 , 99], ca ın exemplul urm˘ator:

73 8

8 1 02 7 4 4

4 5 2 6 5

Tabelul 16.1: Triunghi de numere

Problema const˘ a ın scrierea unui program care s˘ a determine cea mai maresuma de numere aate pe un drum ıntre num˘ arul de pe prima linie si un num˘ arde pe ultima linie. Fiecare num˘ ar din acest drum este situat sub precedentul, last anga sau la dreapta acestuia. (IOI, Suedia 1994)

Rezolvare1. Vom ret ine triunghiul ıntr-o matrice p˘ atratic˘a T , de ordin n, sub diagonala

principal a. Subproblemele problemei date constau ın determinarea sumei maximecare se poate obt¸ine din numere aate pe un drumıntre numarul T [i][ j ], pan a la unnum ar de pe ultima linie, ecare num˘ ar din acest drum ind situat sub precedentul,la st anga sau la dreapta sa. Evident, subproblemele nu sunt independente: pentrua calcula suma maxim˘a a numerelor de pe un drum de la T [i][ j ] la ultima linie,trebuie s a calcul am suma maxim˘a a numerelor de pe un drum de la T [i + 1][ j ] la

ultima linie si suma maxim˘ a a numerelor de pe un drum de la T [i + 1][ j + 1] laultima linie.2. Pentru a ret ¸ine solut iile subproblemelor, vom utiliza o matrice S , p atratic˘a

de ordin n, cu semnicat iaS [i][ j ] = suma maxim˘a ce se poate obt ine pe un drum de la T [i][ j ] la un

element de pe ultima linie, respectˆ and condit iile problemei.Evident, solut¸ia problemei va S [1][1].3. Relat ia de recurent¸a care caracterizeaz˘ a substructura optimal˘ a a problemei

este:S [n][i] = T [n][i], i = 1, 2,...,n

S [i][ j ] = T [i][ j ] + max S [i + 1][ j ], S [i + 1][ j + 1]4. Rezolvam relat ia de recurent¸a ın mod bottom-up:

int i, j;for (i=1; i<=n; i++) S[n][i]=T[n][i];for (i=n-1; i>0; i--)

for (j=1; j<=i; j++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 365/518

16.2. PROBLEME REZOLVATE 353

S[i][j]=T[i][j]+S[i+1][j];if (S[i+1][j]<S[i+1][j+1])

S[i][j]=T[i][j]+S[i+1][j+1]);

Exercit iu: Asat i si drumul ın triunghi pentru care se obt ¸ine solut ia optim˘a.

16.2.4 Subsir comun maximal

Fie X = ( x1 , x2 ,...,x n ) si Y = ( y1 , y2 ,...,y m ) dou a siruri de n, respectiv mnumere ıntregi. Determinat ¸i un subsir comun de lungime maxim˘ a.

Exemplu Pentru X = (2 , 5, 5, 6, 2, 8, 4, 0, 1, 3, 5, 8) si Y = (6 , 2, 5, 6, 5, 5, 4, 3, 5, 8) o

solut ie posibil a este: Z = (2 , 5, 5, 4, 3, 5, 8).Solutie1. Not am cu X k = ( x1 , x2 ,...,x k ) (prexul lui X de lungime k) si cu Y h =

(y1 , y2 ,...,y h ) prexul lui Y de lungime h. O subproblem˘a a problemei date const˘ aın determinarea celui mai lung subsir comun al lui X k , Y h . Notam cu LCS (X k , Y h )lungimea celui mai lung subsir comun al lui X k , Y h .

Utiliz and aceste notat ¸ii, problema cere determinarea LCS (X n , Y m ), precumsi un astfel de subsir.

Observat ie1. Daca X k = Y h atunci

LCS (X k , Y h ) = 1 + LCS (X k−1 , Y h−1).

2. Daca Xk = Y h atunci

LCS (Xk ,Yh) = max( LCS (X k−1 , Y h ),LCS (X k , Y h−1)) .

Din observat ia precedent˘ a deducem c a subproblemele problemei date nu suntindependente si c˘ a problema are substructur˘ a optimal a.

2. Pentru a ret¸ine solut iile subproblemelor vom utiliza o matrice cu n +1 liniisi m + 1 coloane, denumit˘ a lcs . Linia si coloana 0 sunt utilizate pentru init ¸ializarecu 0, iar elementul lcs[k][h] va lungimea celui mai lung subsir comun al sirurilorX k si Y h .

3. Vom caracteriza substructura optimal˘ a a problemei prin urm˘ atoarea relat ¸iede recurent a:

lcs[k][0] = lcs[0][h] = 0, k = 1, 2,.. ,n , h = 1, 2,.. ,m lcs[k][h] = 1 + lcs[k −1][h −1], dac a x[k] = y[h]

max lcs [k][h −1],lcs [k −1][h], dac a x[k] <> y [h]

Rezolvam relat ia de recurent¸a ın mod bottom-up :

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 366/518

354 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

for (int k=1; k<=n; k++)for (int h=1; h<=m; h++)

if (x[k]==y[h])lcs[k][h]=1+lcs[k-1][h-1];

elseif (lcs[k-1][h]>lcs[k][h-1])

lcs[k][h]=lcs[k-1][h];else

lcs[k][h]=lcs[k][h-1];

Deoarece nu am utilizat o structur˘ a de date suplimentar˘ a cu ajutorul c˘areiasa memor am solut ia optim˘a, vom reconstitui solut ¸ia optim˘a pe baza rezultatelormemorate ın matricea lcs . Prin reconstituire vom obt ¸ine solut ia ın ordine invers˘ a,din acest motiv vom memora solutia ıntr-un vector, pe care ıl vom asa de la

sfarsit c˘atre ınceput:cout<<"Lungimea subsirului comun maximal: " <<lcs[n][m];int d[100];cout<<"\nCel mai lung subsir comun este: \n";for (int i=0, k=n, h=m; lcs[k][h]; )

if (x[k]==y[h])

d[i++]=x[k];k--;h--;

else

if (lcs[k][h]==lcs[k-1][h])k--;

elseh--;

for (k=i-1;k>=0; k--)cout<< d[k] <<’ ’;

Secvent ele de cod de mai sus sunt scrise ın C/C++. Programul urm˘ ator estescris ın Java si determin˘ a toate solut¸iile. Sunt determinate cea mai mic˘ a si cea maimare solut ie, ın ordine lexicograc˘ a. De asemenea sunt asate matricele auxiliarede lucru pentru a se putea urm˘ arii mai usor modalitatea de determinare recursiv˘ aa tuturor solut ¸iilor.

import java.io.*; // SubsirComunMaximalclass scm

static PrintWriter out;static int [][] a;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 367/518

16.2. PROBLEME REZOLVATE 355

static char [][] d;

static String x,y;static char[] z,zmin,zmax;static int nsol=0,n,m;static final char sus=’|’, stanga=’-’, diag=’*’;

public static void main(String[] args) throws IOException

citire();n=x.length(); m=y.length();out=new PrintWriter(new BufferedWriter( new FileWriter("scm.out")));

int i,j; matrad();out.println(a[n][m]);afism(a);afism(d);

z=new char[a[n][m]+1];zmin=new char[z.length];zmax=new char[z.length];

System.out.println("O solutie oarecare");osol(n,m);// o solutie

System.out.println("\nToate solutiile");toatesol(n,m,a[n][m]);// toate solutiileout.println(nsol);System.out.print("SOLmin = ");afisv(zmin);System.out.print("SOLmax = ");afisv(zmax);out.close();

static void citire() throws IOException

BufferedReader br=new BufferedReader(new FileReader("scm.in"));x=br.readLine();y=br.readLine();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 368/518

356 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

static void matrad()

int i,j;a=new int[n+1][m+1];d=new char[n+1][m+1];for(i=1;i<=n;i++)

for(j=1;j<=m;j++)if(x.charAt(i-1)==y.charAt(j-1)) // x.charAt(i)==y.charAt(j) !

a[i][j]=1+a[i-1][j-1];d[i][j]=diag;

else

a[i][j]=max(a[i-1][j],a[i][j-1]);if(a[i-1][j]>a[i][j-1]) d[i][j]=sus; else d[i][j]=stanga;

static void osol(int lin, int col)

if((lin==0)||(col==0)) return;

if(d[lin][col]==diag)osol(lin-1,col-1);

else

if(d[lin][col]==sus)osol(lin-1,col);else osol(lin,col-1);

if(d[lin][col]==diag) System.out.print(x.charAt(lin-1));

static void toatesol(int lin, int col,int k)

int i,j;if(k==0)

System.out.print(++nsol+" ");afisv(z);zminmax();return;

i=lin+1;while(a[i-1][col]==k)//merg in sus

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 369/518

16.2. PROBLEME REZOLVATE 357

i--;j=col+1;while(a[i][j-1]==k) j--;if( (a[i][j-1]==k-1)&&(a[i-1][j-1]==k-1)&&(a[i-1][j]==k-1))

z[k]=x.charAt(i-1);toatesol(i-1,j-1,k-1);

//while

static void zminmax()

if(nsol==1)

copiez(z,zmin);copiez(z,zmax);

else

if(compar(z,zmin)<0)copiez(z,zmin);

elseif(compar(z,zmax)>0) copiez(z,zmax);

static int compar(char[] z1, char[] z2)//-1=<; 0=identice; 1=>int i=1;while(z1[i]==z2[i]) i++;// z1 si z2 au n componente 1..nif(i>n)

return 0;else

if(z1[i]<z2[i])return -1;

else return 1;

static void copiez(char[] z1, char[] z2)

int i;for(i=1;i<z1.length;i++) z2[i]=z1[i];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 370/518

358 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

static int max(int a, int b)

if(a>b) return a; else return b;

static void afism(int[][]a)// difera tipul parametrului !!!

int n=a.length;int i,j,m; m=y.length();

System.out.print(" ");for(j=0;j<m;j++) System.out.print(y.charAt(j)+" ");System.out.println();

System.out.print(" ");for(j=0;j<=m;j++) System.out.print(a[0][j]+" ");System.out.println();

for(i=1;i<n;i++)

System.out.print(x.charAt(i-1)+" "); m=a[i].length;

for(j=0;j<m;j++) System.out.print(a[i][j]+" ");System.out.println();

System.out.println("\n");

static void afism(char[][]d)// difera tipul parametrului !!!

int n=d.length;int i,j,m; m=y.length();

System.out.print(" ");for(j=0;j<m;j++) System.out.print(y.charAt(j)+" ");System.out.println();

System.out.print(" ");for(j=0;j<=m;j++) System.out.print(d[0][j]+" ");System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 371/518

16.2. PROBLEME REZOLVATE 359

for(i=1;i<n;i++)

System.out.print(x.charAt(i-1)+" "); m=d[i].length;

for(j=0;j<m;j++) System.out.print(d[i][j]+" ");System.out.println();

System.out.println("\n");

static void afisv(char[]v)

int i;for(i=1;i<=v.length-1;i++) System.out.print(v[i]);for(i=1;i<=v.length-1;i++) out.print(v[i]);System.out.println();out.println();

Pe ecran apar urm˘ atoarele rezultate:

1 3 2 4 6 5 a c b d f e0 0 0 0 0 0 0 0 0 0 0 0 0

1 0 1 1 1 1 1 1 1 1 1 1 1 12 0 1 1 2 2 2 2 2 2 2 2 2 2

3 0 1 2 2 2 2 2 2 2 2 2 2 24 0 1 2 2 3 3 3 3 3 3 3 3 35 0 1 2 2 3 3 4 4 4 4 4 4 46 0 1 2 2 3 4 4 4 4 4 4 4 4a 0 1 2 2 3 4 4 5 5 5 5 5 5b 0 1 2 2 3 4 4 5 5 6 6 6 6c 0 1 2 2 3 4 4 5 6 6 6 6 6d 0 1 2 2 3 4 4 5 6 6 7 7 7e 0 1 2 2 3 4 4 5 6 6 7 7 8f 0 1 2 2 3 4 4 5 6 6 7 8 8

1 3 2 4 6 5 a c b d f e

1 * - - - - - - - - - - -2 | - * - - - - - - - - -3 | * - - - - - - - - - -4 | | - * - - - - - - - -

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 372/518

360 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

5 | | - | - * - - - - - -6 | | - | * - - - - - - -a | | - | | - * - - - - -b | | - | | - | - * - - -c | | - | | - | * - - - -d | | - | | - | | - * - -e | | - | | - | | - | - *f | | - | | - | | - | * -

O solutie oarecare1346acdfToate solutiile1 1346acdf2 1246acdf3 1345acdf4 1245acdf5 1346abdf6 1246abdf7 1345abdf8 1245abdf9 1346acde10 1246acde11 1345acde12 1245acde13 1346abde

14 1246abde15 1345abde16 1245abdeSOLmin = 1245abdeSOLmax = 1346acdf

16.2.5 Distant ¸a minima de editare

Fie d(s1, s2) distant¸a de editare (denit˘ a ca ind num arul minim de operat¸iide stergere , inserare si modicare ) dintre sirurile de caractere s1 si s2. Atunci:

d(”” , ””) = 0 (16.2.1)d(s, ””) = d(”” , s) = |s|, (16.2.2)

Av and ın vedere ultima operat ¸ie efectuat˘a asupra primului sir de caractere,la sfarsitul acestuia (dar dup˘ a modic arile efectuate deja), obt ¸inem:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 373/518

16.2. PROBLEME REZOLVATE 361

d(s1 + ch1 , s2 + ch2) = min

d(s1 + ch1 , s2) + 1 , inserare ch2

d(s1 , s 2 + ch2) + 1 , stergere ch1

d(s1 , s 2) +0 daca ch1 = ch2 , nimic !1 daca ch1 = ch2 , ınlocuire

(16.2.3)

Folosim o matrice c[0..|s1|][0..|s2|] unde c[i][ j ] def = d(s1[1..i ], s 2[1..j ]).Algoritmul ın pseudocod este:

m[0][0]=0;for(i=1; i<=length(s1); i++) m[i][0]=i;for(j=1; j<=length(s2); j++) m[0][j]=j;

for(i=1; i<=length(s1); i++)for(j=1;j<=length(s2); j++)

val=(s1[i]==s2[j]) ? 0 : 1; m[i][j]=min( m[i-1][j-1]+val, m[i-1][j]+1, m[i][j-1]+1 );

Programul surs˘ a:

import java.io.*;class DistEdit

static final char inserez=’i’, // inserez inaintea pozitieisterg=’s’, modific=’m’,nimic=’ ’; // caracter !!!

static final char sus=’|’,stanga=’-’,diags=’x’;

static int na,nb;static int [][] c; // c[i][j] = cost a1..ai --> b1..bjstatic char [][] op; // op = operatia efectuatastatic char [][] dir; // dir = directii pentru minim !!!

static String a,b; // a--> b

public static void main(String[] args) throws IOException

int i,j,cmin=0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 374/518

362 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

BufferedReader br=new BufferedReader(new FileReader("distedit.in"));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("distedit.out")));

a=br.readLine();b=br.readLine();na=a.length();nb=b.length();

c=new int[na+1][nb+1];op=new char[na+1][nb+1];dir=new char[na+1][nb+1];

System.out.println(a+" --> "+na);System.out.println(b+" --> "+nb);

for(i=1;i<=na;i++)

c[i][0]=i; // stergeri din a; b=vid !!!op[i][0]=sterg; // s_idir[i][0]=sus;

for(j=1;j<=nb;j++)

c[0][j]=j; // inserari in a; a=vid !!!op[0][j]=inserez; //t_jdir[0][j]=stanga;

op[0][0]=nimic;dir[0][0]=nimic;

for(i=1;i<=na;i++)

for(j=1;j<=nb;j++)

if(a.charAt(i-1)==b.charAt(j-1))

c[i][j]=c[i-1][j-1];op[i][j]=nimic;dir[i][j]=diags;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 375/518

16.2. PROBLEME REZOLVATE 363

else

cmin=min(c[i-1][j-1],c[i-1][j],c[i][j-1]);c[i][j]=1+cmin;if(cmin==c[i][j-1]) // inserez t_j

op[i][j]=inserez;dir[i][j]=stanga;

elseif(cmin==c[i-1][j]) // sterg s_i

op[i][j]=sterg;dir[i][j]=sus;

elseif(cmin==c[i-1][j-1]) //s_i-->t_j

op[i][j]=modific;dir[i][j]=diags;

// else

// for j// for i

afismi(c,out);

afismc(dir,out);afismc(op,out);

afissol(na,nb,out);out.println("\nCOST transformare = "+c[na][nb]);out.close();System.out.println("COST transformare = "+c[na][nb]);

// main

static void afismc(char[][] x, PrintWriter out)

int i,j;out.print(" ");for(j=1;j<=nb;j++) out.print(b.charAt(j-1));for(i=0;i<=na;i++)

out.println();if(i>0) out.print(a.charAt(i-1)); else out.print(" ");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 376/518

364 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

for(j=0;j<=nb;j++) out.print(x[i][j]);out.println("\n");

// afismc(...)

static void afismi(int[][] x, PrintWriter out)

int i,j;out.print(" ");for(j=1;j<=nb;j++) out.print(b.charAt(j-1));for(i=0;i<=na;i++)

out.println();if(i>0) out.print(a.charAt(i-1)); else out.print(" ");for(j=0;j<=nb;j++) out.print(x[i][j]);

out.println("\n");

// afismi(...)

static void afissol(int i,int j, PrintWriter out)

if(i==0&&j==0) return;if(dir[i][j]==diags) afissol(i-1,j-1,out);else

if(dir[i][j]==stanga) afissol(i,j-1,out);else

if(dir[i][j]==sus) afissol(i-1,j,out);

if((i>0)&&(j>0))

if(op[i][j]==sterg)out.println(i+" "+a.charAt(i-1)+" "+op[i][j]);

elseif(op[i][j]==inserez)

out.println(" "+op[i][j]+" "+j+" "+b.charAt(j-1));else

out.println(i+" "+a.charAt(i-1)+" "+op[i][j]+" "+j+" "+b.charAt(j-1));elseif(i==0)

out.println(i+" "+a.charAt(i)+" "+op[i][j]+" "+j+" "+b.charAt(j-1));elseif(j==0)

out.println(i+" "+a.charAt(i-1)+" "+op[i][j]+" "+j+" "+b.charAt(j));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 377/518

16.2. PROBLEME REZOLVATE 365

//afissol(...)

static int min(int a, int b) return a<b ? a:b; static int min(int a, int b, int c) return min(a,min(b,c));

// class

Rezultate asate ın sierul de iesire:

altruisti0123456789

a1012345678l2101234567g3211234567o4322234567r5433234567i6544333456t7654444445 m8765555555i9876665665

altruisti---------

a|x--------l||x-------g|||x------o||||x-----

r||||x-----i|||||xx--xt|||x|||xx- m|||||||||xi||||||x-|x

altruistiiiiiiiiii

as iiiiiiiilss iiiiiiigsssmiiiiiiossssmiiiiirssss iiiiiisssssm iitsss sssm i msssssssssmissssss is

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 378/518

366 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

1 a 1 a2 l 2 l3 g m 3 t4 o s5 r 4 r

i 5 u6 i 6 i

i 7 s7 t 8 t8 m s9 i 9 i

COST transformare = 5

16.2.6 Problema rucsacului (0 −1)

import java.io.*;class Rucsac01

public static void main(String[] args) throws IOException

int n,m;int i,j;int[] g,v;

int[][] c;

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("rucsac.out")));

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("rucsac.in")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

g=new int[n+1];v=new int[n+1];c=new int[n+1][m+1];

for(i=1;i<=n;i++) st.nextToken(); g[i]=(int)st.nval; for(i=1;i<=n;i++) st.nextToken(); v[i]=(int)st.nval;

for(i=1; i<=n; i++) c[i][0]=0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 379/518

16.2. PROBLEME REZOLVATE 367

for(j=0; j<=m; j++) c[0][j]=0;

for(i=1; i<=n; i++)for(j=1; j<=m; j++)

if(g[i]>j)c[i][j]=c[i-1][j];

elsec[i][j]=max( c[i-1][j], c[i-1][j-g[i]] + v[i] );

out.println(c[n][m]);out.close();

// main(...)

static int max(int a, int b)

if(a>b) return a; else return b;// max(...)

16.2.7 Problema schimbului monetar

import java.io.*;class Schimb

public static void main(String[] args) throws IOExceptionint v,n;int i,j;int[] b, ns;

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("schimb.out")));

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("schimb.in")));

st.nextToken(); v=(int)st.nval;st.nextToken(); n=(int)st.nval;

b=new int[n+1];ns=new int[v+1];

for(i=1;i<=n;i++) st.nextToken(); b[i]=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 380/518

368 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

ns[0]=1;for(i=1; i<=n; i++)

for(j=b[i]; j<=v; j++)ns[j]+=ns[j-b[i]];

out.println(ns[v]);out.close();

// main// class

16.2.8 Problema traversarii matricei

Traversarea unei matrice de la Vest la Est; sunt permise deplas˘ ari spre veciniiunei pozit ii (chiar si deplas˘ ari prin ”exteriorul” matricei).

import java.io.*;class Traversare

public static void main(String[] args) throws IOException

int m,n;int i,j,imin;int[][] a,c,t;int[] d;int cmin,minc;

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("traversare.out")));

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("traversare.in")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;

a=new int[m][n];c=new int[m][n];t=new int[m][n];d=new int[n];

for(i=0;i<m;i++)for(j=0;j<n;j++)

st.nextToken();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 381/518

16.2. PROBLEME REZOLVATE 369

a[i][j]=(int)st.nval;

for(i=0;i<m;i++) c[i][0]=a[i][0];for(j=1; j<n; j++)

for(i=0; i<m; i++)

minc=min(c[(i+m-1)%m][j-1], c[i][j-1], c[(i+1)%m][j-1]);c[i][j]=a[i][j]+minc;if(minc==c[(i+m-1)%m][j-1]) t[i][j]=((i+m-1)%m)*n+(j-1);else

if(minc==c[i][j-1]) t[i][j]=i*n+(j-1);else t[i][j]=((i+1)%m)*n+(j-1);

imin=0;cmin=c[0][n-1];for(i=1;i<m;i++)

if(c[i][n-1]<cmin)

cmin=c[i][n-1];imin=i;

out.println(cmin);

d[n-1]=imin*n+(n-1);

j=n-1;i=imin;while(j>0)

i=t[i][j]/n;j--;d[j]=i*n+j;

for(j=0;j<n;j++) out.println((1+d[j]/n)+" "+(1+d[j]%n));out.close();

// main(...)

static int min(int a, int b)

if(a<b) return a; else return b;

static int min(int a, int b, int c)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 382/518

370 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

return min(min(a,b),c);

// class/*traversare.in traversare.out3 4 62 1 3 2 2 11 3 5 4 1 23 4 2 7 3 3

1 4*/

16.2.9 Problema segmentarii vergelei

Scopul algoritmului este de a realiza n t aieturi, dea lungul unei vergele ınlocuri pre-specicate, cu efort minim (sau cost ). Costul ec arei operat ii de t aiereeste proport¸ional cu lungimea vergelei care trebuie t˘ aiat a. In viat a real a, ne putemimagina costul ca ind efortul depus pentru a plasa vergeaua (sau un bustean!) ınmasina de t˘aiat.

Consider am sirul de numere naturale 0 < x 1 < x 2 < ... < x n < x n +1 ın carexn +1 reprezint˘a lungimea vergelei iar x1 , x2 ,...,x n reprezint˘a abscisele punctelorın care se vor realiza t˘ aieturile (distant ¸ele fat a de cap atul ”din stˆanga” al vergelei).

Not am prin c[i][ j ] (i < j ) costul minim necesar realiz arii tuturor t˘ aieturilorsegmentului de vergea [ x i ..x j ].

Evident c[i][i + 1] = 0 pentru c˘a nu este necesar˘a nici o t aietur a.Pentru j > i sa presupunem c˘a realiz am prima t˘aietur a ın xk (i < k < j ). Dinvergeaua [ x i ...x j ] obtinem dou˘a bucat i mai mici: [x i ...x k ] si [xk ...x j ]. Costul pentrut aierea vergelei [ x i ...x j ] este format din costul transportului acesteia la masina det aiat ( x j −x i ) + costul t˘aierii vergelei [x i ...x k ] (adica c[i][k]) si + costul t˘aieriivergelei [xk ...x j ] (adica c[k][ j ]).

Dar, ce valoare are k? Evident, k trebuie s a aib a acea valoare care s˘a mini-mizeze expresia c[i][k] + c[k][ j ]. Obtinem:

c[i][ j ] = x j −x i + mini<k<j c[i][k] + c[k][ j ]

import java.io.*;class Vergea

static int n,nt=0;static int x[];static int c[][];static int t[][];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 383/518

16.2. PROBLEME REZOLVATE 371

static BufferedReader br; // pentru "stop" (pentru depanare!)

public static void main(String[]args) throws IOException

int i,j,h,k,min,kmin;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("vergea.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("vergea.out")));br=new BufferedReader(new InputStreamReader(System.in));

st.nextToken(); n=(int)st.nval;x=new int[n+2];c=new int[n+2][n+2];t=new int[n+2][n+2];

for(i=1;i<=n+1;i++) st.nextToken(); x[i]=(int)st.nval;

System.out.println("n="+n);System.out.print("x: ");for(i=1;i<=n+1;i++) System.out.print(x[i]+" ");System.out.println();

for(i=0;i<=n;i++) c[i][i+1]=0;

j=-1;for(h=2;h<=n+1;h++) // lungimea vargelei

for(i=0;i<=n+1-h;i++) // inceputul vargelei

j=i+h; // sfarsitul vargeleic[i][j]=x[j]-x[i]; min=Integer.MAX_VALUE;kmin=-1;for(k=i+1;k<=j-1;k++)

if(c[i][k]+c[k][j]<min)

min=c[i][k]+c[k][j];kmin=k;

c[i][j]+=min;t[i][j]=kmin;

//for i

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 384/518

372 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

// for h

out.println(c[0][n+1]);out.close();

afism(c); afism(t);System.out.println("Ordinea taieturilor: \n");taieturi(0,n+1);System.out.println();

//main

public static void taieturi(int i,int j) throws IOException

if(i>=j-1) return;int k;k=t[i][j];System.out.println((++nt)+" : "+i+".."+j+" --> "+k);//br.readLine(); // "stop" pentru depanare !if((i<k)&&(k<j)) taieturi(i,k); taieturi(k,j);

//taieturi

static void afism(int[][] x) // pentru depanare !

int i,j;for(i=0;i<=n+1;i++)

for(j=0;j<=n+1;j++) System.out.print(x[i][j]+" ");System.out.println();System.out.println();

// afism(...)//class/*n=5x: 2 4 5 8 12 15

0 0 4 8 16 27 380 0 0 3 9 19 290 0 0 0 4 12 220 0 0 0 0 7 170 0 0 0 0 0 70 0 0 0 0 0 00 0 0 0 0 0 0

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 385/518

16.2. PROBLEME REZOLVATE 373

0 0 1 1 2 3 40 0 0 2 3 4 40 0 0 0 3 4 40 0 0 0 0 4 40 0 0 0 0 0 50 0 0 0 0 0 00 0 0 0 0 0 0

Ordinea taieturilor:

1 : 0..6 --> 42 : 0..4 --> 23 : 0..2 --> 14 : 2..4 --> 35 : 4..6 --> 5*/

16.2.10 Triangularizarea poligoanelor convexe

Consider am un poligon convex cu n varfuri numerotate cu 1, 2, ..., n (ın gur˘an = 9) si dorim s˘a obtinem o triangularizare ın care suma lungimilor diagonalelortrasate s˘a e minim a (ca si cum am dori s˘a consum am cat mai put¸in tus pentrutrasarea acestora!).

11

2 2

3 3

4 45 56 6

7 7

8 899

12

3

4 56

89

6

7

8

7

8

5 5

1 9 1 9

5 5

Evident, orice latur˘ a a poligonului face parte dintr-un triunghi al triangulat ¸iei.Consider am la ınceput latura [1 , 9]. Sa presupunem c˘a ıntr-o anumit˘ a triangulat¸ieoptim a latura [1 , 9] face parte din triunghiul [1 , 5, 9]. Diagonalele triangulat ¸ieioptime vor genera o triangulat ¸ie optim˘a a poligoanelor convexe [1 , 2, 3, 4, 5] si

[5, 6, 7, 8, 9]. Au aparut astfel dou˘a subprobleme ale problemei init ¸iale.Sa not am prin p(i ,k, j ) perimetrul triunghiului [ i ,k, j ] (i < k < j ) isi prin

c[i][ j ] costul minim al triagulat ¸iei poligonului convex [ i, i + 1 ,...,j ] (unde i < j ).Atunci:

c[i][ j ] = 0, dac a j = i + 1

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 386/518

374 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

si

c[i][ j ] = mini≤k<j p(i ,k, j ) + c[i][k] + c[k][ j ], dac a i < j ≤n

16.2.11 Algoritmul Roy-Floyd-Warshall

// Lungime drum minim intre oricare doua varfuri in graf orientat ponderat.// OBS: daca avem un drum de lungime minima de la i la j atunci acest drum// va trece numai prin varfuri distincte, iar daca varful k este varf intermediar,// atunci drumul de la i la k si drumul de la k la j sunt si ele minime// (altfel ar exista un drum mai scurt de la i la j); astfel, este indeplinit// "principiul optimalitatii"

import java.io.*;class RoyFloydWarshall // O(n^3)

static final int oo=0x7fffffff;static int n,m;static int[][] d;

public static void main(String[]args) throws IOException

int i,j,k;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("RoyFloydWarshall.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("RoyFloydWarshall.out")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

d=new int[n+1][n+1];

for(i=1;i<=n;i++) for(j=1;j<=n;j++) d[i][j]=oo;for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); d[i][j]=d[j][i]=(int)st.nval;

for(k=1;k<=n;k++)for(i=1;i<=n;i++) // drumuri intre i si j care trec

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 387/518

16.2. PROBLEME REZOLVATE 375

for(j=1;j<=n;j++) // numai prin nodurile 1, 2, ..., kif((d[i][k]<oo)&&(d[k][j]<oo))

if(d[i][j]>d[i][k]+d[k][j]) d[i][j]=d[i][k]+d[k][j];

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)if(d[i][j]<oo) System.out.print(d[i][j]+" ");else System.out.print("*"+" ");

System.out.println();out.close();

//main//class

/*6 61 2 3 2 3 1 * * *1 3 1 3 4 2 * * *2 3 2 1 2 2 * * *4 5 1 * * * 2 1 25 6 3 * * * 1 2 34 6 2 * * * 2 3 4*/

16.2.12 Oracolul decide - ONI2001 cls 10

prof. Doru Popescu Anastasiu, Slatina La un concurs particip˘ a N concurent i. Fiecare concurent primeste o foaie de

hartie pe care va scrie un cuvˆ ant av and cel mult 100 de caractere (litere mici alealfabetului englez). Cuvintele vor distincte.

Pentru departajare, concurent ¸ii apeleaz a la un oracol. Acesta produce si elun cuvnt. Va cˆastiga concurentul care a scris cuvˆ antul ”cel mai apropiat” de aloracolului.

Gradul de ”apropiere” dintre dou˘ a cuvinte este lungimea subcuvˆ antului co-mun de lungime maxim˘a. Prin subcuvˆant al unui cuvˆant dat se ınt ¸elege un cuv antcare se poate obt ine din cuv antul dat, eliminˆ and 0 sau mai multe litere si p˘ astr andordinea literelor r˘amase.

Cerint ¸aSe cunosc cuv antul c0 produs de oracol si cuvintele ci , i = 1 ,...,N scrise de

concurent i. Pentru a ajuta comisia s˘ a desemneze c astig˘atorul, se cere ca pentruecare i sa identicat¸i pozit iile literelor ce trebuie sterse din c0 si din ci astfel ıncˆatprin stergere s˘ a se obtin a unul dintre subcuvintele comune de lungime maxim˘ a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 388/518

376 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

Date de intrareFisier de intrare: ORACOL.INLinia 1: N num ar natural nenul, reprezentˆ and num arul concurent¸ilor;Linia 2: c0 cuvantul produs de oracol;Liniile 3..N+2: cuvant pe aceste N linii se aa cuvintele scrise de cei

N concurent i, un cuv ant pe o linie;Date de iesireFisier de iesire: ORACOL.OUTLiniile 1..2*N: pozit ¸iile literelor ce trebuie sterse pe ecare linie i

(i = 1 , 3, ..., 2∗N −1) se vor scrie numere naturale nenule, separate prin cˆ ateun spat iu, reprezentˆ and pozit iile de pe care se vor sterge litere din cuvˆ antul pro-dus de oracol; pe ecare linie j ( j = 2 , 4,..., 2∗N ) se vor scrie numere naturalenenule, separate prin cˆ ate un spat¸iu, reprezentˆ and pozit iile de pe care se vor stergelitere din cuv antul concurentului cu num˘ arul j/ 2.

Restrict ¸ii2 ≤N ≤100Daca exist a mai multe solut¸ii, ın sier se va scrie una singur˘ a.Daca dintr-un cuvˆant nu se va t˘aia nici o liter a, linia respectiv˘a din sierul

de intrare va r˘amane vid a.Exemplu

ORACOL.IN ORACOL.OUT poate cont ¸ine solut ia:3 3abc 3 4abxdaabxyc 1 4 5acb 3

2Timp maxim de executare/test: 1 secund a

Codul sursa

Varianta 1:

import java.io.*; // subsir comun maximal - problema clasica ...class Oracol // varianta cu mesaje pentru depanare ...

static final char sus=’|’, stanga=’-’, diag=’*’;static int[][] a;static char[][] d;

static String x,y;static boolean[] xx=new boolean[101];static boolean[] yy=new boolean[101];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 389/518

16.2. PROBLEME REZOLVATE 377

static char[] z;static int m,n,nc;

public static void main(String[] args) throws IOException

int i,j,k;BufferedReader br=new BufferedReader(new FileReader("oracol.in"));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("oracol.out")));

nc=Integer.parseInt(br.readLine());

x=br.readLine().replace(" ",""); // elimina spatiile ... de la sfarsit ! m=x.length();

for(k=1;k<=nc;k++)

y=br.readLine().replaceAll(" ",""); // elimina spatiile ... daca sunt!n=y.length();

matrad();afism(a);afism(d);

System.out.print("O solutie oarecare: ");z=new char[a[m][n]+1];

for(i=1;i<=m;i++) xx[i]=false;for(j=1;j<=n;j++) yy[j]=false;osol(m,n);System.out.println("\n");

for(i=1;i<=m;i++) if(!xx[i]) out.print(i+" ");out.println();for(j=1;j<=n;j++) if(!yy[j]) out.print(j+" ");out.println();

out.close();System.out.println("\n");

// main(...)

static void matrad()

int i,j;a=new int[m+1][n+1];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 390/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 391/518

16.2. PROBLEME REZOLVATE 379

System.out.print(" ");for(j=0;j<=n;j++) System.out.print(a[0][j]+" ");System.out.println();

for(i=1;i<=m;i++)

System.out.print(x.charAt(i-1)+" ");for(j=0;j<=n;j++) System.out.print(a[i][j]+" ");System.out.println();

System.out.println("\n");

// afism(int[][]...)

static void afism(char[][] d) // difera tipul parametrului

int i,j;System.out.print(" ");for(j=0;j<n;j++) System.out.print(y.charAt(j)+" ");System.out.println();

System.out.print(" ");for(j=0;j<=n;j++) System.out.print(d[0][j]+" ");System.out.println();

for(i=1;i<=m;i++)

System.out.print(x.charAt(i-1)+" ");for(j=0;j<=n;j++) System.out.print(d[i][j]+" ");System.out.println();

System.out.println("\n");

// afism(char[][]...)// class

Varianta 2:

import java.io.*; // problema reala ...class Oracol

static final char sus=’|’, stanga=’-’, diag=’*’;static int[][] a;static char[][] d;static String x,y;static boolean[] xx=new boolean[101];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 392/518

380 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

static boolean[] yy=new boolean[101];static int m,n,nc;

public static void main(String[] args) throws IOException

int i,j,k;BufferedReader br=new BufferedReader(new FileReader("oracol.in"));PrintWriter out=new PrintWriter(

new BufferedWriter( new FileWriter("oracol.out")));

nc=Integer.parseInt(br.readLine());

x=br.readLine().replace(" ",""); // elimina spatiile ... de la sfarsit ! m=x.length();

for(k=1;k<=nc;k++)

y=br.readLine().replaceAll(" ",""); // elimina spatiile ... daca sunt!n=y.length();

matrad();for(i=1;i<=m;i++) xx[i]=false;for(j=1;j<=n;j++) yy[j]=false;osol(m,n);

for(i=1;i<=m;i++) if(!xx[i]) out.print(i+" ");

out.println();for(j=1;j<=n;j++) if(!yy[j]) out.print(j+" ");out.println();

out.close();

// main(...)

static void matrad()

int i,j;a=new int[m+1][n+1];d=new char[m+1][n+1];for(i=1;i<=m;i++)for(j=1;j<=n;j++)if(x.charAt(i-1)==y.charAt(j-1))

a[i][j]=1+a[i-1][j-1];d[i][j]=diag;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 393/518

16.2. PROBLEME REZOLVATE 381

else

a[i][j]=max(a[i-1][j],a[i][j-1]);if(a[i-1][j]>a[i][j-1]) d[i][j]=sus; else d[i][j]=stanga;

// matrad()

static void osol(int lin, int col)

if((lin==0)||(col==0)) return;if(d[lin][col]==diag) osol(lin-1,col-1); elseif(d[lin][col]==sus) osol(lin-1,col); else osol(lin,col-1);if(d[lin][col]==diag) xx[lin]=yy[col]=true;

// osol(...)

static int max(int a, int b)

if(a>b) return a; else return b;// max(...)

// class

16.2.13 Pav˘ ari - ONI2001 clasa a X-a

prof. Doru Popescu Anastasiu, Slatina Se da un dreptunghi cu lungimea egal˘ a cu 2N centimetri si l˘at imea egal a cu

3 centimetri .

Cerint ¸aSa se determine num˘arul M al pav arilor distincte cu dale dreptunghiulare

care au lungimea egal˘a cu un centimetru si l˘ at imea egal a cu 2 centimetri.

Datele de intrareFisier de intrare: pavari.inLinia 1: N - num ar natural nenul, reprezentˆ annd jum˘atatea lungimii drep-

tunghiului.

Datele de iesire

Fisier de iesire: pavari.outLinia 1: M - numar natural nenul, reprezentˆ and num arul modalit˘at ilor de apava dreptunghiul.

Restrict ii si precizari

• 1 ≤N ≤100

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 394/518

382 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

Exemplupavari.in pavari.out2 11

Timp maxim de executare: 1 secund a/test

Codul sursa *

import java.io.*; // x[n]=x[n-1]+2*y[n-1]; x[1]=3;class Pavari // y[n]=y[n-1]+x[n]; y[1]=4;

public static void main(String[] args) throws IOException

int k,kk,n;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("pavari9.in")));st.nextToken(); n=(int)st.nval;int[] xv,xn,yv,yn;xv=new int[1];yv=new int[1];

xv[0]=3;yv[0]=4;xn=xv;for(k=2;k<=n;k++)

xn=suma(xv,suma(yv,yv));yn=suma(yv,xn);xv=xn;yv=yn;

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("pavari.out")));

for(kk=xn.length-1;kk>=0;kk--) out.print(xn[kk]);out.close();

// main(...)

static int[] suma(int[] x, int[] y)

int nx=x.length,ny=y.length,i,t;int nz;if(nx>ny) nz=nx+1; else nz=ny+1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 395/518

16.2. PROBLEME REZOLVATE 383

int[] z=new int[nz];

t=0;for(i=0;i<nz;i++)

z[i]=t;if(i<nx) z[i]+=x[i];if(i<ny) z[i]+=y[i];t=z[i]/10;z[i]=z[i]%10;

if(z[nz-1]!=0) return z;else

int[] zz=new int[nz-1];for(i=0;i<nz-1;i++) zz[i]=z[i];return zz;

//suma

16.2.14 Balant ¸a ONI2002 clasa a X-a

Gigel are o ”balant¸ a” mai ciudat˘a pe care vrea s a o echilibreze. De fapt,

aparatul este diferit de orice balant ¸ a pe care at i vazut-o pˆana acum.Balant a lui Gigel dispune de dou˘a brat e de greutate neglijabil˘ a si lungime15 ecare. Din loc ın loc, la aceste brat ¸e sunt atasate cˆ arlige, pe care Gigel poateat arna greut˘at i distincte din colect¸ia sa de G greut ati (numere naturale ıntre 1 si25). Gigel poate atˆarna oric ate greut˘at i de orice c arlig, dar trebuie s˘a foloseascatoate greut˘at ile de care dispune.

Folosindu-se de experient ¸a particip˘arii la Olimpiada Nat ¸ional a de Informatic˘a,Gigel a reusit s˘a echilibreze balant¸a relativ repede, dar acum doreste s˘ a stie ın cˆatemoduri poate ea echilibrat˘ a.

Cerint ¸aCunosc and amplasamentul cˆ arligelor si setul de greut˘ ati pe care Gigel ıl are

la dispozit ie, scriet i un program care calculeaz˘ a ın c ate moduri se poate echilibra

balant a.Se presupune c a este posibil s a se echilibreze balant¸a (va posibil pe toatetestele date la evaluare).

Datele de intrareFisierul de intrare balanta.in are urm atoarea structur˘ a:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 396/518

384 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

• pe prima linie, num˘arul C de carlige si num˘arul G de greut at i, valori sep-arate prin spat ¸iu;

• pe urm atoarea linie, C numere ıntregi, distincte, separate prin spat ¸iu, cuvalori cuprinse ıntre −15 si 15 inclusiv, reprezentˆand amplasamentele cˆ arligelorfat a de centrul balant ¸ei; valoarea absolut˘ a a numerelor reprezint˘ a distant¸a fat a decentrul balant ¸ei, iar semnul precizeaz˘ a brat ul balant¸ei la care este atasat crligul,”-” pentru brat ¸ul st ang si ”+” pentru brat ¸ul drept;

• pe urm atoarea linie, G numere naturale distincte, cuprinse ıntre 1 si 25 in-clusiv, reprezentˆ and valorile greut˘at ilor pe care Gigel le va folosi pentru a echilibrabalant a.

Datele de iesireFisierul de iesire balanta.out contine o singur a linie, pe care se a a un num ar

natural M , num arul de variante de plasare a greut˘ at ilor care duc la echilibrarea

balant ei.Restrict ii si precizari

• 2 ≤C ≤20, 2 ≤G ≤20;

• greut atile folosite au valori naturale ıntre 1 si 25;

• num arul M cerut este ıntre 1 si 100 .000.000;

• celelalte restrict¸ii (lungimea brat ¸elor balant¸ei etc.) au fost prezentate ante-rior.

•balant a se echilibreaz a dac a suma produselor dintre greut˘ ati si coordonateleunde ele sunt plasate este 0 (suma momentelor greut˘ at ilor fat a de centrul balant ¸eieste 0).

Exemplubalanta.in balanta.out2 4 2-2 33 4 5 8

Timp maxim de executare: 1 secund a/test

Indicat ¸ii de rezolvare *

Solut ¸ia comisiei Problema se rezolva prin metoda program˘ arii dinamice .Se calculeaz a ın c ate moduri se poate scrie ecare sum˘ a j , folosind primele i

greut at i. Init ial i = 0 si suma 0 se poate obt¸ineıntr-un singur mod, restul sumelorın 0 moduri.

Urmeaza G pasi. La ecare astfel de pas i se calculeaz a ın c ate moduri putemobt ine ecare sum˘a introducˆand o nou a greutate - a i-a - ın toate congurat ¸iileprecedente. Practic, dac˘ a suma S s-a obtinut cu primele i−1 greut ati ın M moduri,pun and greutatea i pe carligul k se va obtine suma S +( greutate [i]∗coordonata [k])

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 397/518

16.2. PROBLEME REZOLVATE 385

ın M moduri (la care, evident, se pot adauga alte moduri de obt ¸inere plasˆandgreutatea i pe un alt c arlig si folosind suma respectiv˘ a).

In acest mod s-ar construi o matrice cu G linii si 2∗(sumamaxima ) + 1coloane, cu elemente numere ıntregi pe 32 de bit ¸i; de fapt se memoreaza doarultimele dou a linii (ecare linie se obt ine din precedenta). Suma maxim˘ a este15∗25∗20 = 7500, deci o linie se incadreaz˘a ın mai put¸in de 64 K .

Rezultatul nal se obt ¸ine pe ultima linie, ın coloana asociat˘ a sumei 0.

GInfo 12/6 octombrie 2002 Se observa ca suma momentelor greut˘ atilor este cuprins˘a ıntre −6000 si 6000

(dac a avem 20 de greut˘at i cu valoarea 20 si acestea sunt amplasate pe cel maindep artat cˆarlig fat a de centrul balant ¸ei, atunci modulul sumei momentelor fort ¸eloreste 152020 = 6000). Ca urmare, putem p˘ astra un sir a ale carui valori a i vorcontine num˘arul posibilit˘atilor ca suma momentelor greut˘ at ilor s a e i.

Indicii sirului vor varia ıntre −6000 si 6000. Pentru a ımbun˘ at at i viteza deexecut ie a programului, indicii vor varia ıntre −300g si 300 g, unde g este num arulgreut atilor. Pot realizate ımbun˘ at at iri suplimentare dac˘ a se determin˘a distant elemaxime fat a de mijlocul balant¸ei ale celor mai ındep˘ artate cˆarlige de pe cele dou atalere si suma total˘ a a greut atilor. Dac˘a distant ele sunt d1 si d2 , iar suma este s,atunci indicii vor varia ıntre −d1s si d2s.

Init ial, pe balant¸a nu este ag atat˘a nici o greutate, asadar suma momentelorgreut at ilor este 0. Ca urmare, init ¸ial valorile a i vor 0 pentru orice indice nenulsi a0 = 1 (exist˘a o posibilitate ca init¸ial suma momentelor greut˘ ailor sa e 0 si nuexist a nici o posibilitate ca ea s˘a e diferit a de 0).

In continuare, vomıncerca s˘ a amplas am greut˘atile pe carlige. Fiecare greutatepoate amplasat˘ a pe oricare dintre cˆarlige. Sa presupunem c˘a la un moment

dat exist˘a a i posibilit at i de a obt ine suma i. Daca vom amplasa o greutate devaloare g pe un carlig aat la distant ¸a d fat a de centrul balant ¸ei, suma momentelorgreut at ilor va creste sau va sc˘ adea cu gd (ın funct¸ie de brat ul pe care se a acarligul). Ca urmare, dup˘ a amplasarea noii greut at i exist a a i posibilit at i de aobtine suma i + gd. Consider am ca sirul b va cont ine valori care reprezint˘ a num arulposibilit at ilor de a obt ine sume ale momentelor fort ¸elor dup˘a amplasarea greut˘ at iicurente. Inainte de a testa posibilit˘ aile de plasare a greut˘atii, sirul b va cont inedoar zerouri. Pentru ecare pereche ( i, d), valoarea bi+ gd va creste cu a i . Dup aconsiderarea tuturor perechilor, vom putea trece la o nou˘ a greutate.

Valorile din sirul b vor salvate ın sirul a, iar sirul b va reinit ializat cu0. Rezultatul nal va dat de valoarea a0 obtinut˘a dup a considerarea tuturorgreut at ilor disponibile.

Analiza complexit˘ at iiPentru studiul complexit˘ at ii vom nota num˘arul greut˘at ilor cu g, iar cel al

carligelor cu c.Citirea datelor de intrare corespunz˘ atoare c arligelor si greutat ¸ilor se real-

izeaza ın timp liniar, deci ordinul de complexitate al acestor operat ¸ii este O(g),respectiv O(c).

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 398/518

386 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

Singura m arime care nu este considerat˘ a constant˘a si de care depinde num˘ arulde posibilit at i de a obt ine sumele este num˘arul greut˘atilor. Asadar, vom consideraca ordinul de complexitate al travers˘ arii sirului a este O(g).

Num arul de travers˘ari este dat tot de num˘ arul greut˘at ilor disponibile, decivom avea O(g) travers˘ari.

In timpul travers˘ arii vom considera toate cˆ arligele pentru ecare element alsirului. Ca urmare, ordinul de complexitate al operat ¸iilor efectuate asupra unuielement ıntr-o parcurgere este O(c). Rezult a ca ordinul de complexitate al uneiparcurgeri este O(g)O(c) = O(gc), ın timp ce ordinul de complexitate al ıntregiioperat ii care duce la obt inerea rezultatului este O(g)O(gc) = O(g2c).

Asarea num˘arului de posibilit˘at i de a echilibra balant ¸a se realizeaz˘a ın timpconstant.

In concluzie, ordinul de complexitate al algoritmului de rezolvare a acesteiprobleme este O(c) + O(g) + O(g2c) + O(1) = O(g2c).

Codul sursa

import java.io.*;class Balanta

static long[] a=new long[15001]; // a[i] i = -7500, 7500static long[] b=new long[15001]; // sir auxiliar (a+7500)!!!static int[] carlig=new int[20]; // coordonatele carligelorstatic int[] greutate=new int[20]; // valorile greutatilor

static int nrCarlige, nrGreutati;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();citesteDatele();determinaSolutia();scrieSolutia();t2=System.currentTimeMillis();System.out.println("TIMP = "+(t2-t1)+" milisecunde");

// main()

static void citesteDatele() throws IOException

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("balanta9.in")));

st.nextToken(); nrCarlige=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 399/518

16.2. PROBLEME REZOLVATE 387

st.nextToken(); nrGreutati=(int)st.nval;

for(int i=0;i<nrCarlige;i++)

st.nextToken(); carlig[i]=(int)st.nval;for(int i=0;i<nrGreutati;i++)

st.nextToken(); greutate[i]=(int)st.nval;

// citesteDate()

static void scrieSolutia() throws IOException

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("balanta9.out")));

out.print(a[7500+0]);out.close();

// scrieSolutia()

static void determinaSolutia()

int i,j,k;a[7500+0]=1; // initial balanta este echilibratafor(i=0;i<nrGreutati;i++)

for(j=-7500;j<=7500;j++)if(a[7500+j]!=0)for(k=0;k<nrCarlige;k++)

b[7500+j+carlig[k]*greutate[i]]+=a[7500+j];for (j=-7500;j<=7500;j++)

a[7500+j]=b[7500+j];b[7500+j]=0;

// determinaSolutia()// class

16.2.15 Aliniere ONI2002 clasa a X-a

In armat˘a, o companie este alc atuit˘a din n soldat i. La inspect ia de dimineat¸asoldat ii stau aliniat¸i ın linie dreapt˘ a ın fat a c apitanului. Acesta nu e mult ¸umit de

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 400/518

388 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

ceea ce vede; e drept c a soldat ii sunt asezat ¸i ın ordinea numerelor de cod 1 , 2,...,ndin registru, dar nu ın ordinea ın˘ alt imii. C apitanul cere cˆatorva soldat¸i sa iasa dinrand, astfel ca cei r amasi, f ar a a-si schimba locurile, doar apropiindu-se unul dealtul (pentru a nu r˘ amane spat ii mari ıntre ei) s˘ a formeze un sir ın care ecaresoldat vede privind de-a lungul sirului, cel put ¸in una din extremit˘ at i (st anga saudreapta). Un soldat vede o extremitate dac˘ a ıntre el si cap˘ atul respectiv nu exist aun alt soldat cu ın˘ alt imea mai mare sau egal˘ a ca a lui.

Cerint ¸aScrieti un program care determin˘ a, cunosc andın˘alt imea ec arui soldat, num˘ arul

minim de soldat i care trebuie s˘a par aseasc a format ia astfel ca sirul r˘amas s aındeplineasc˘ a condit ia din enunt¸.

Datele de intrarePe prima linie a sierului de intrare aliniere.in este scris num arul n al

soldat ilor din sir, iar pe linia urm˘ atoare un sir de n numere reale, cu maximum 5zecimale ecare si separate prin spat ¸ii. Al k-lea num ar de pe aceast˘a linie reprezint˘aın alt imea soldatului cu codul k (1 ≤k ≤n).

Datele de iesireFisierul aliniere.out va cont ine pe prima linie num˘arul soldat ilor care tre-

buie sa par aseasc a format ia, iar pe linia urm˘atoare codurile acestora ın ordinecrescatoare, separate dou˘ a cate dou a printr-un spat ¸iu. Dac a exist a mai multesolut ii posibile, se va scrie una singur˘ a.

Restrict ii si precizari

• 2 ≤n ≤1000

• ın altimile sunt numere reale ın intervalul [0 .5; 2.5].

Exemplualiniere.in aliniere.out8 41.86 1.86 1.30621 2 1.4 1 1.97 2.2 1 3 7 8

Explicat ieRaman soldat ii cu codurile 2, 4, 5, 6 av and ın˘alt imile 1 .86, 2, 1.4 si 1.Soldatul cu codul 2 vede extremitatea stˆ ang a.Soldatul cu codul 4 vede ambele extremit˘ at i.Soldat ii cu codurile 5 si 6 v ad extremitatea dreapt˘ a.

Timp maxim de executare: 1 secund a/test

Indicat ¸ii de rezolvare

Solut ¸ia comisiei Problema se rezolv˘a prin metoda program˘ arii dinamice .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 401/518

16.2. PROBLEME REZOLVATE 389

Se calculeaz a, pentru ecare element, lungimea celui mai lung subsir strictcrescator care se termin˘ a cu el si lungimea celui mai lung subsir strict descresc˘ atorcare ıncepe cu el.

Solutia const˘aın p˘astrarea a dou˘ a astfel de subsiruri de soldat ¸i (unul cresc˘atorsi unul descresc˘ator) pentru DOI soldat i de aceeasi ın˘ altime (eventual identici) sieliminarea celorlalt¸i. Soldat ii din primul subsir privesc spre stanga, ceilalt ¸i spredreapta. Primul subsir se termin˘ a inainte de a ıncepe al doilea. Se au in vederecazurile particulare.

Deoarece s-a considerat c˘a o parte din concurent ¸i vor rezolva problema pentruun singur soldat central (tot ¸i ceilalti soldat¸i p astrati avˆand ınaltimea mai mic˘ a) sinu vor observa cazul ın care se pot p˘ astra doi soldat¸i de aceeasi ınalt ¸ime, majori-tatea testelor se ıncadreaz˘ a ın acest caz.

GInfo 12/6 octombrie 2002 Pentru ecare soldat vom determina cel mai lung subsir strict cresc˘ ator (din

punct de vedere al ın˘ alt imii) de soldat¸i care se termin˘a cu el, respectiv cel mailung subsir strict descresc˘ ator de soldat¸i care urmeaz˘a dup a el.

Dup a aceast a operat ie, vom determina soldatul pentru care suma lungim-ilor celor dou a siruri este maxim˘ a. Chiar dac˘a s-ar p area c a ın acest mod am g˘ asitsolut ia problemei, mai exist˘ a o posibilitate de a m˘ari num arul soldat ilor care r˘amanın sir. S˘a consider am soldatul cel mai ınalt ın sirul r˘ amas (cel c aruia ıi corespundesuma maxim˘a). Acesta poate privi e spre stˆ anga, e spre dreapta sirului. Dinaceste motive, la stˆanga sau la dreapta sa poate s˘ a se ae un soldat de aceeasiın alt ime; unul dintre cei doi va privi spre dreapta, iar cel˘ alalt spre stˆanga. Totusi,nu putem alege orice soldat cu aceeasi ın˘ alt ime, ci doar unul pentru care lungimeasirului strict cresc˘ ator (dac˘a se aa spre st anga) sau a celui strict descresc˘ ator

(dac a se aa spre dreapta) este aceeasi cu lungimea corespunz˘ atoare sirului strictcrescator, respectiv strict descresc˘ ator, corespunz˘ atoare celui mai ınalt soldat din-tre cei r amasi ın sir.

Dup a identicarea celor doi soldat ¸i deın˘altimi egale (sau demonstrarea faptu-lui ca nu exist a o pereche de acest gen care s˘a respecte condit¸iile date) se marcheaz˘ atot i soldat ii din cele dou a subsiruri. Ceilalt ¸i soldat i vor trebui s˘a par aseasc a format ia.

Analiza complexit˘ at iiCitirea datelor de intrare se realizeaz˘ a ın timp liniar, deci ordinul de com-

plexitate al acestei operat ¸ii este O(n).Chiar dac˘a exist algoritmi ecient¸i (care ruleaz˘a n timp liniar-logaritmic) de

determinare a celui mai lung subsir ordonat, timpul de execut ¸ie admis ne permitefolosirea unui algoritm simplu, cu ordinul de complexitate O(n2). Acesta va aplicat de dou˘a ori, dup a care se va c auta valoarea maxim˘ a a sumei lungimilorsirurilor corespunz˘ atoare unui soldat; asadar identicarea soldatului care poateprivi ın ambele direct ¸ii este o operat ie cu ordinul de complexitate O(n2)+ O(n2)+O(n) = O(n2).

Urmeaz a eventuala identicare a unui alt soldat de aceeasi ın˘ alt ime carerespect a condit iile referitioare la lungimile subsirurilor. Pentru aceasta se parcurge

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 402/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 403/518

16.2. PROBLEME REZOLVATE 391

new BufferedReader(new FileReader(fisi)));st.nextToken(); ns=(int)st.nval;

predCresc=new int[ns];lgCresc=new int[ns];succDesc=new int[ns];lgDesc=new int[ns];ramas=new boolean[ns];inalt=new float[ns];

for(int i=0;i<ns;i++) st.nextToken(); inalt[i]=(float)st.nval;//citescDate()

static void subsirCresc()

int i,j;lgCresc[0]=1;predCresc[0]=-1;for(i=1;i<ns;i++)

lgCresc[i]=1; // subsirul formar doar din ipredCresc[i]=-1; // nu are predecesorfor (int j=0;j<i;j++)if(inalt[j]<inalt[i])

if(lgCresc[i]<lgCresc[j]+1) // sir mai lung

lgCresc[i]=lgCresc[j]+1;predCresc[i] = j;

//subsirCresc()

static void subsirDesc()

int i,j;lgDesc[ns-1]=0; // nu exista nici un soldat mai mic dupa ns-1succDesc[ns-1]=-1; // ns-1 nu are succesorfor(i=ns-2;i>=0;i--)

lgDesc[i]=0; // nu exista nici un soldat mai mic dupa isuccDesc[i]=-1; // i nu are succesorfor(j=ns-1;j>i;j--)

if(inalt[j]<inalt[i]) // soldat mai micif(lgDesc[i]<lgDesc[j]+1) // sir mai lung

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 404/518

392 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

lgDesc[i]=lgDesc[j]+1; // actualizarea lg subsirsuccDesc[i]=j; // actualizare succesor

// subsirDesc()

static void alegeSoldati()

int i;// este posibil ca in mijloc sa fie doi soldati cu inaltimi egaleint im=-1; // indicele soldatului din mijlocint ic, id; // indicii care delimiteaza in interior cele doua subsirurifor(i=0;i<ns;i++)if(lgCresc[i]+lgDesc[i]>nsr)

nsr=lgCresc[i]+lgDesc[i];im=i;

// in "mijlocul" sirului se pot afla doi soldati cu aceeasi inaltimeic=im;id=im;

// caut in stanga un subsir cu aceeasi lungime --> soldat cu aceeasi inaltimefor(i=im-1;i>=0;i--)

if(lgCresc[ic]==lgCresc[i]) ic=i;

// caut in dreapta un subsir cu aceeasi lungime --> soldat cu aceeasi inaltimefor(i=im+1;i<ns;i++)if(lgDesc[id]==lgDesc[i]) id=i;if(ic!=id) // in "mijloc" sunt doi soldati cu aceeasi inaltimensr++;while(id!=-1) // indice descrescator

ramas[id]=true;id=succDesc[id];

while(ic!=-1) // indice crescator

ramas[ic] = true;ic=predCresc[ic];

// alegeSoldati()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 405/518

16.2. PROBLEME REZOLVATE 393

static void scrieRezultate() throws IOException

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("aliniere.out")));

out.println(ns- nsr);for(int i=0;i<ns;i++) if(!ramas[i]) out.print((i+1)+" ");out.close();

// scriuRezultate()// class

16.2.16 Munte - ONI2003 cls 10

Intr-o zon a montan˘a se doreste deschiderea unui lant ¸ de telecabine. Stat ¸iilede telecabine pot ınint ¸ate pe oricare din cele N varfuri ale zonei montane.Varfurile sunt date ın ordine de la stˆ anga la dreapta si numerotate de la 1 la N ,ecare v arf i ind precizat prin coordonata X [i] pe axa OX si prin ın˘altimea H [i].

Se vor ınint¸a exact K stat ii de telecabine. Stat ¸ia de telecabine i (2 ≤ i ≤K )va conectat˘a cu stat iile i −1 si i + 1; stat¸ia 1 va conectat˘a doar cu stat¸ia 2,iar stat ia K , doar cu stat¸ia K −1. Stat ia 1 va obligatoriu amplasat˘ a ın v arful1, iar stat ia K ın v arful N .

Se doreste ca lant¸ul de telecabine s˘a asigure leg atura ıntre vˆ arful 1 si v arfulN . Mai mult, se doreste ca lungimea total˘ a a cablurilor folosite pentru conectaresa e minim a. Lungimea cablului folosit pentru a conecta dou˘ a stat ii este egal a cudistant¸a dintre ele. In plus, un cablu care uneste dou˘ a stat ii consecutive nu poate

avea lungimea mai mare decˆ at o lungime xat˘a L.O restrict ie suplimentar˘ aeste introdus˘a de formele de relief. Astfel, v arfurile isi j (i < j ) nu pot conectate direct dac˘ a exist a un v arf v (i < v < j ) astfel ıncˆatsegmentul de dreapta care ar uni vˆ afurile i si j nu ar trece pe deasupra vˆ arfuluiv. In cazul ın care cele trei vˆarfuri sunt coliniare, se consider˘ a toate trei ca indstat ii, chiar dac˘a distan c dintre vrfurile i si j este mai mic a decat L.

Cerint ¸aDandu-se amplasarea celor N vrfuri ale lant ului muntos, stabilit ¸i o modalitate

de dispunere a celor K stat ii de telecabine astfel ıncˆ at lungimea total˘ a a cablurilorfolosite pentru conectare s˘ a e minim a, cu restrict¸iile de mai sus.

Se garanteaz˘a ca, pe toate testele date la evaluare, conectarea va posibil˘ a.Date de intrarePrima linie a sierului de intrare munte.in contine trei numere ıntregi N , K

si L, separate prin spat ¸ii, cu semnicat iile de mai sus. Urm˘atoarele N linii contincoordonatele vˆarfurilor; linia i + 1 cont ine coordonatele vˆarfului i, X [i] si H [i],separate printr-un spat ¸iu.

Date de iesireIn sierul munte.out veti asa:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 406/518

394 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

- pe prima linie lungimea total˘ a minim a a cablurilor, rotunjit˘ a la cel maiapropiat numar ıntreg (pentru orice ıntreg Q, Q.5 se rotunjeste la Q + 1);

- pe a doua linie K numere distincte ıntre 1 si N , ordonate cresc˘ator, numerelevarfurilor ın care se vor ınin¸ a stat ii de telecabine. Dac˘a exist a mai multe variante,asat i una oarecare.

Restrict ii si precizari2 ≤N ≤1002 ≤K ≤30 si K ≤N 0 ≤L, X [i], H [i] ≤100.000 si X [i] < X [i + 1]Exemplu

munte.in munte.out7 5 11 220 16 1 3 5 6 74 36 87 412 1613 1614 16

Explicat ¸ii- trasarea unui cablu direct ıntre vˆ arfurile 1 si 5 ar contravenit restrict ¸iei

referitoare la lungimea maxim˘ a a unui cablu; ın plus, s-ar obt ¸inut o solut¸ie cu 2stat ii de telecabine ın loc de 3 (deci solut ¸ia ar invalid˘a si pentru valori mari alelui L);

- pentru a ilustra restrict ¸ia introdus˘a de formele de relief, preciz am ca varfurile1 si 4 nu au putut conectate direct datorit˘ a ın alt imii v arfului 3. De asemenea,

varfurile 5 si 7 nu au putut conectate direct datorit˘ a ın alt imii v arfului 6.Timp maxim de executare: 1 secund a/test.

Indicat ¸ii de rezolvare - descriere solut ¸ie *

Mihai Stroe, GInfo nr. 13/6 - octombrie 2003 Problema se rezolv˘a prin metoda program˘ arii dinamice .Practic, problema se poate ımp˘ art i ın dou˘a subprobleme. Primul pas const˘ a

ın determinarea perechilor de vˆ arfuri care pot unite printr-un cablu. Acest passe rezolva folosind cunostint ¸e elementare de geometrie plan˘ a (ecuat ia dreptei, y =a∗x + b). Se va obt ine o matrice OK , unde OK i,j are valoarea 1 dac˘a varfurile i si j pot unite si 0 ın caz contrar. Folosind aceast˘ a matrice, se vor conecta vˆarfurile1 si N cu un lant de K stat ii, astfel ıncˆ at oricare dou˘a stat ii consecutive s a aib aOK -ul corespunz ator egal cu 1.

Aceast a subproblema se rezolv˘a prin metoda program˘ arii dinamice dup a cumurmeaz a: se construieste o matrice A cu K linii si N coloane, unde Ai,j reprezint˘alungimea total˘a minim a a unui lant cu i stat ii care conecteaz˘a varfurile 1 si j .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 407/518

16.2. PROBLEME REZOLVATE 395

Init ial A1,1 = 0, A1,i = + ∞si Ai, 1 = + ∞pentru i > 1.Pentru i cuprins ıntre 2 si N , componentele matricei se calculeaz˘ a astfel:

Ai,j = min Ai−1,v + dist (v, j ), unde v < j si OK v,j = 1

Concomitent cu calculul elementelor Ai,j se construieste o matrice T , undeT i,j reprezint˘a v-ul care minimizeaz˘a expresia de mai sus. Matricea T este folosit apentru reconstituirea solut ¸iei.

Lungimea total˘a minim a este regasit˘a ın AK,N .Subproblemele puteau tratate si simultan, ceea ce complica implementarea.Analiza complexit˘ at iiOperat ia de citire a datelor are ordinul de complexitate O(N ).Calculul matricei OK are ordinul de complexitate O(N 3).Algoritmul bazat pe metoda program˘ arii dinamice are ordinul de complexitate

O(N 2

·K ).Reconstituirea solut ¸iei si asarea au ordinul de complexitate O(N ).Deoarece K ≤ N , ordinul de complexitate al algoritmului de rezolvare a

acestei probleme este O(N 3).

Codul sursa

Prima variant˘ a:

import java.io.*; // cu mesaje pt depanare dar ... fara traseuclass Munte1

static final int oo=Integer.MAX_VALUE;static int n,m,L; // m=nr statii (in loc de K din enunt)

static int[] x,h;static double[][] a;static int[][] t;static boolean[][] ok;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i;BufferedReader br=new BufferedReader(new FileReader("munte.in"));StreamTokenizer st=new StreamTokenizer(br);

st.nextToken(); n=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 408/518

396 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

st.nextToken(); m=(int)st.nval;st.nextToken(); L=(int)st.nval;

x=new int[n+1];h=new int[n+1];ok=new boolean[n+1][n+1]; // implicit este falsea=new double[m+1][n+1];t=new int[m+1][n+1];

for(i=1;i<=n;i++)

st.nextToken(); x[i]=(int)st.nval;st.nextToken(); h[i]=(int)st.nval;

matriceaOK();afism(ok);

matriceaA();

afisSolutia();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()

static void matriceaA()int i,j,k,kmin;double d,dkj,min;a[1][1]=0;for(i=2;i<=m;i++) a[i][1]=oo;for(j=2;j<=n;j++) a[1][j]=oo;afism(a);

for(i=2;i<=m;i++)

for(j=2;j<=n;j++)

min=oo;kmin=-1;for(k=1;k<j;k++)

System.out.println(i+" "+j+" "+k+" "+ok[k][j]);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 409/518

16.2. PROBLEME REZOLVATE 397

if(ok[k][j])

dkj=dist(k,j);d=a[i-1][k]+dkj;System.out.println(i+" "+j+" "+k+" dkj="+dkj+" d="+d+" min="+min);if(d<min) min=d;kmin=k;

// for ka[i][j]=min;

// for jSystem.out.println("Linia: "+i);afism(a);

// for i// matriceaA()

static double dist(int i, int j)

double d;d=(double)(x[i]-x[j])*(x[i]-x[j])+(double)(h[i]-h[j])*(h[i]-h[j]);return Math.sqrt(d);

// dist(...)

static void matriceaOK()

int i,j,ij,x1,y1,x2,y2,sp1,sp2;for(i=1;i<=n-1;i++)

x1=x[i]; y1=h[i];for(j=i+1;j<=n;j++)

x2=x[j]; y2=h[j];ok[i][j]=ok[j][i]=true;for(ij=i+1;ij<=j-1;ij++) // i .. ij .. j

sp1=(0 -y1)*(x2-x1)-(y2-y1)*(x[ij]-x1);sp2=(h[ij]-y1)*(x2-x1)-(y2-y1)*(x[ij]-x1);if(sp1*sp2<=0)

ok[i][j]=ok[j][i]=false;System.out.println(i+" "+j+" ("+ij+")\t"+sp1+"\t"+sp2);break;

if(!ok[i][j]) break;

//for ij

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 410/518

398 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

if(ok[i][j]) if(dist(i,j)>L+0.0000001) ok[i][j]=ok[j][i]=false;//for j

// for i// matriceaOK()

static void afisSolutia() throws IOException

int i,j;PrintWriter out = new PrintWriter(

new BufferedWriter(new FileWriter("munte.out")));out.println(a[m][n]);out.close();

//afisSolutia()

static void afism(int[][] a)

int i,j;for(i=0;i<a.length;i++)

for(j=0;j<a[i].length;j++) System.out.print(a[i][j]+" ");System.out.println();

System.out.println();

// afism(...)

static void afism(boolean[][] a)

int i,j;for(i=1;i<a.length;i++)

for(j=1;j<a[i].length;j++) System.out.print(a[i][j]+" ");System.out.println();

System.out.println();

// afism(...)

static void afism(double[][] a)

int i,j;for(i=1;i<a.length;i++)

for(j=1;j<a[i].length;j++) System.out.print(a[i][j]+" ");System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 411/518

16.2. PROBLEME REZOLVATE 399

System.out.println();// afism(...)

// class

A doua variant˘ a:

import java.io.*; // FINAL: fara mesaje si cu traseu ... darclass Munte2 // test 8 : P1(99,59) P2(171,96) P3(239,81) P4(300,78) // solutia: 1 4 5 ... este gresita (1 4 nu trece de P2 si P3!)

static final int oo=Integer.MAX_VALUE;static int n,m,L; // m=nr statii (in loc de K din enunt)

static int[] x,h;static double[][] a;static int[][] t;static boolean[][] ok;static int[] statia;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i,j;BufferedReader br=new BufferedReader(new FileReader("munte.in"));StreamTokenizer st=new StreamTokenizer(br);

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;st.nextToken(); L=(int)st.nval;

x=new int[n+1];h=new int[n+1];ok=new boolean[n+1][n+1];a=new double[m+1][n+1];t=new int[m+1][n+1];statia=new int[m+1];for(i=1;i<=n;i++)

st.nextToken(); x[i]=(int)st.nval;st.nextToken(); h[i]=(int)st.nval;

matriceaOK();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 412/518

400 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

matriceaA();j=n;for(i=m;i>=1;i--) statia[i]=j; j=t[i][j]; afisSolutia();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()

static void matriceaA()

int i,j,k,kmin;double d,dkj,min;a[1][1]=0;for(i=2;i<=m;i++) a[i][1]=oo;for(j=2;j<=n;j++) a[1][j]=oo;

for(i=2;i<=m;i++)

for(j=2;j<=n;j++)

min=oo;kmin=0;for(k=1;k<j;k++)

if(ok[k][j])

dkj=dist(k,j);d=a[i-1][k]+dkj;if(d<min) min=d;kmin=k;

// for ka[i][j]=min;t[i][j]=kmin;

// for j// for i

// matriceaA()

static double dist(int i, int j)

double d;d=(double)(x[i]-x[j])*(x[i]-x[j])+(double)(h[i]-h[j])*(h[i]-h[j]);return Math.sqrt(d);

// dist(...)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 413/518

16.2. PROBLEME REZOLVATE 401

static void matriceaOK()

int i,j,ij,x1,y1,x2,y2;long sp1,sp2; // 100.000*100.000=10.000.000.000 depaseste int !!!for(i=1;i<=n-1;i++)

x1=x[i]; y1=h[i];for(j=i+1;j<=n;j++)

x2=x[j]; y2=h[j];ok[i][j]=ok[j][i]=true;for(ij=i+1;ij<=j-1;ij++) // i .. ij .. j

sp1=(0 -y1)*(x2-x1)-(y2-y1)*(x[ij]-x1);sp2=(h[ij]-y1)*(x2-x1)-(y2-y1)*(x[ij]-x1);if(sp1*sp2<=0)

ok[i][j]=ok[j][i]=false;break;

if(!ok[i][j]) break;

//for ijif(ok[i][j]) if(dist(i,j)>L) ok[i][j]=ok[j][i]=false;

//for j// for i

// matriceaOK()

static void afisSolutia() throws IOException

int i;PrintWriter out = new PrintWriter(

new BufferedWriter(new FileWriter("munte.out")));out.println((int)(a[m][n]+0.5));for(i=1;i<=m;i++) out.print(statia[i]+" ");out.println();out.close();

//afisSolutia()// class

16.2.17 L˘acusta - OJI2005 clasa a X-aSe consider a o matrice dreptunghiular˘ a cu m linii si n coloane, cu valori

naturale. Travers˘ am matricea pornind de la colt ¸ul st anga-sus la colt ul dreapta-jos.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 414/518

402 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

O traversare const˘ a din mai multe deplas˘ari. La ecare deplasare se execut˘ a unsalt pe orizontal˘a si un pas pe vertical˘a. Un salt ınseamn˘ a ca putem trece de la ocelula la oricare alta aat˘ a pe aceeasi linie, iar un pas ınseamn˘ a ca putem trecede la o celula la celula aat˘a imediat sub ea. Except ¸ie face ultima deplasare (ceaın care ne a˘am pe ultima linie), cˆand vom face doar un salt pentru a ajunge ıncoltul dreapta-jos, dar nu vom mai face si pasul corespunz˘ ator. Astfel traversareava consta din vizitarea a 2 m celule.

Cerint ¸aScriet i un program care s˘a determine suma minim˘ a care se poate obt ine

pentru o astfel de traversare.

Datele de intrareFisierul de intrare lacusta.in contine pe prima linie dou˘a numere naturale

separate printr-un spat ¸iu m n , reprezentˆand num arul de linii si respectiv num˘ arulde coloane ale matricei. Pe urm˘ atoarele m linii este descris a matricea, cˆate nnumere pe ecare linie, separate prin cˆ ate un spat¸iu.

Datele de iesireFisierul de iesire lacusta.out va cont ine o singur a linie pe care va scris a

suma minim a gasit a.

Restrict ii si precizari

• 1 ≤m, n ≤100

• Valorile elementelor matricei sunt numere ıntregi din intervalul [1 , 255].

Exemplelacusta.in lacusta.out Explicatie4 5 28 Drumul este:3 4 5 7 9 (1, 1) →(1, 3) →6 6 3 4 4 (2, 3) →(2, 2) →6 3 3 9 6 (3, 2) →(3, 3) →6 5 3 8 2 (4, 3) →(4, 5)

Timp maxim de executare: 1 secund a/test

Indicat ¸ii de rezolvare *

Ginfo nr. 15/3 martie 2005 Pentru rezolvarea acestei probleme vom utiliza metoda program˘ arii dinamice .Vom nota prin A matricea dat˘ a si vom construi o matrice B ale c˘ arei elemente

bij vor cont ine sumele minime necesare pentru a ajunge ın celula ( i, j ) porninddin celula ( i −1, j ).

Vom completa init ¸ial elementele de pe a doua linie a matricei B. Valoarea b2,1va ∞deoarece ın aceast˘ a celula nu se poate ajunge. Valorile celorlalte elementeb2i vor calculate pe baza formulei: b2,i = a1,1 + a1,i + a2,i .

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 415/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 416/518

404 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

st.nextToken(); a[i][j]=(int)st.nval;

for(i=0;i<m;i++) for(j=0;j<n;j++) b[i][j]=oo;

// prima linie (i=0) din b este oo// a doua linie (i=1) din bfor(j=1;j<n;j++) b[1][j]=a[0][0]+a[0][j]+a[1][j];

// urmatoarele linii din bfor(i=2;i<m;i++)

for(j=0;j<n;j++)b[i][j]=a[i][j]+a[i-1][j]+minLinia(i-1,j);

// "obligatoriu" (!) si ultima linie (i=n-1) dar ... fara coborareb[m-1][n-1]=minLinia(m-1,n-1)+a[m-1][n-1];

out.println(b[m-1][n-1]);out.close();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()

static int minLinia(int ii, int jj) // min pe linia=ii fara pozitia jj==col

int j,min=oo;for(j=0;j<n;j++)

if(j!=jj)if(b[ii][j]<min) min=b[ii][j];return min;

// minLinia(...)// class

A doua variant˘ a:

import java.io.*; // suplimentar ... si traseul !class Lacusta2

static final int oo=100000;static int m,n;static int[][] a,b; // 1 <= i <= m; 1 <= j <= n

public static void main(String[] args) throws IOException

long t1,t2;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 417/518

16.2. PROBLEME REZOLVATE 405

t1=System.currentTimeMillis();

int i,j,min,jmin,j0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("lacusta.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("lacusta.out")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;a=new int[m+1][n+1];b=new int[m+1][n+1];

for(i=1;i<=m;i++)for(j=1;j<=n;j++)

st.nextToken(); a[i][j]=(int)st.nval;for(i=1;i<=m;i++) for(j=1;j<=n;j++) b[i][j]=oo;

// prima linie (i=1) din b este oo// a doua linie (i=2) din bfor(j=2;j<=n;j++) b[2][j]=a[1][1]+a[1][j]+a[2][j];

// urmatoarele linii din bfor(i=3;i<=m;i++)

for(j=1;j<=n;j++) b[i][j]=a[i][j]+a[i-1][j]+minLinia(i-1,j);

// "obligatoriu" (!) si ultima linie (i=n) dar ... fara coborareb[m][n]=minLinia(m,n)+a[m][n];

out.println(b[m][n]);out.close();

jmin=-1; // initializare aiurea !j0=1; // pentru linia 2System.out.print(1+" "+1+" --> ");for(i=2;i<=m-1;i++) // liniile 2 .. m-1

min=oo;for(j=1;j<=n;j++)if(j!=j0)if(b[i][j]<min) min=b[i][j]; jmin=j;System.out.print((i-1)+" "+jmin+" --> ");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 418/518

406 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

System.out.print(i+" "+jmin+" --> ");j0=jmin;

j0=n; min=oo;for(j=1;j<n;j++)if(j!=j0)if(b[i][j]<min) min=b[i][j]; jmin=j;System.out.print((i-1)+" "+jmin+" --> ");System.out.print(i+" "+jmin+" --> ");System.out.println(m+" "+n);

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()

static int minLinia(int ii, int jj) // min pe linia=ii fara pozitia jj==col

int j,min=oo;for(j=1;j<=n;j++)

if(j!=jj)if(b[ii][j]<min) min=b[ii][j];

return min;// minLinia(...)

// class

Varianta 3:

import java.io.*; // fara matricea de costuri (economie de "spatiu")class Lacusta3 // traseul este ... pentru depanare // daca se cere ... se poate inregistra si apoi ...

static final int oo=100000;static int m,n;static int[][] a; // 1 <= i <= m; 1 <= j <= n

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i,j;int minc,minsol,jmin,j0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 419/518

16.2. PROBLEME REZOLVATE 407

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("lacusta.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("lacusta.out")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;a=new int[m+1][n+1];

for(i=1;i<=m;i++)for(j=1;j<=n;j++)

st.nextToken(); a[i][j]=(int)st.nval;

minsol=oo;System.out.print(1+" "+1+" --> ");

// a doua linie (i=2) minc=oo;jmin=-1;for(j=2;j<=n;j++)

if(a[1][1]+a[1][j]+a[2][j]<minc) minc=a[1][1]+a[1][j]+a[2][j]; jmin=j;System.out.print(1+" "+jmin+" --> ");System.out.print(2+" "+jmin+" --> "); minsol=minc;j0=jmin;

jmin=-1; // initializare aiurea !for(i=3;i<=m-1;i++)

minc=oo;for(j=1;j<=n;j++)if(j!=j0)

if(a[i-1][j]+a[i][j]<minc)minc=a[i-1][j]+a[i][j]; jmin=j;

System.out.print((i-1)+" "+jmin+" --> ");System.out.print(i+" "+jmin+" --> "); minsol+=minc;j0=jmin;

j0=n; minc=oo;for(j=1;j<=n;j++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 420/518

408 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

if(j!=j0)if(a[m-1][j]+a[m][j]<minc)

minc=a[m-1][j]+a[m][j]; jmin=j;System.out.print((m-1)+" "+jmin+" --> ");System.out.print(m+" "+jmin+" --> "); minsol+=minc+a[m][n];System.out.println(m+" "+n);

out.println(minsol);out.close();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()// class

Varianta 4:

import java.io.*; // fara matricea de costuri (economie de "spatiu")class Lacusta4 // si ... fara matricea initiala (numai doua linii din ea !) // calculez pe masura ce citesc cate o linie !

static final int oo=100000;static int m,n;static int[][] a; // 1 <= i <= m; 1 <= j <= n

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i,j,ii,jj;int minc,minsol,jmin,j0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("lacusta.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("lacusta.out")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;a=new int[2][n+1];

for(i=1;i<=2;i++) // citesc numai primele doua liniifor(j=1;j<=n;j++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 421/518

16.2. PROBLEME REZOLVATE 409

st.nextToken(); a[i%2][j]=(int)st.nval;

minsol=oo;System.out.print(1+" "+1+" --> ");

// a doua linie (i=2) minc=oo;jmin=-1;for(j=2;j<=n;j++)

if(a[1%2][1]+a[1][j]+a[2%2][j]<minc)minc=a[1%2][1]+a[1%2][j]+a[2%2][j]; jmin=j;

System.out.print(1+" "+jmin+" --> ");System.out.print(2+" "+jmin+" --> "); minsol=minc;j0=jmin;

jmin=-1; // initializare aiurea !for(i=3;i<=m-1;i++) // citesc mai departe cate o linie

for(j=1;j<=n;j++) st.nextToken(); a[i%2][j]=(int)st.nval; minc=oo;for(j=1;j<=n;j++)

if(j!=j0)if(a[(i-1+2)%2][j]+a[i%2][j]<minc)

minc=a[(i-1+2)%2][j]+a[i%2][j]; jmin=j;

System.out.print((i-1)+" "+jmin+" --> ");System.out.print(i+" "+jmin+" --> "); minsol+=minc;j0=jmin;

//citesc linia mfor(j=1;j<=n;j++) st.nextToken(); a[m%2][j]=(int)st.nval;

j0=n; minc=oo;for(j=1;j<=n;j++)

if(j!=j0)if(a[(m-1+2)%2][j]+a[m%2][j]<minc)

minc=a[(i-1+2)%2][j]+a[i%2][j]; jmin=j;System.out.print((i-1)+" "+jmin+" --> ");System.out.print(i+" "+jmin+" --> "); minsol+=minc+a[m%2][n];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 422/518

410 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

System.out.println(m+" "+n);

out.println(minsol);out.close();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()// class

Varianta 5:

import java.io.*; // numai o linie din matricea initiala !class Lacusta5

static final int oo=100000;static int m,n;static int[] a; // 1 <= j <= n

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

int i,j,ii,jj,a11,aa;int minc,minsol,jmin,j0;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("lacusta.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("lacusta.out")));

st.nextToken(); m=(int)st.nval;st.nextToken(); n=(int)st.nval;a=new int[n+1];

// citesc numai prima liniefor(j=1;j<=n;j++) st.nextToken(); a[j]=(int)st.nval; System.out.print(1+" "+1+" --> ");a11=a[1];

// citesc a doua liniest.nextToken(); a[1]=(int)st.nval; minc=oo;jmin=-1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 423/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 424/518

412 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

out.println(minsol);out.close();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main()// class

16.2.18 Avere ONI2005 cls 10

Italag a fost toat˘ a viat a pasionat de speculat ¸ii bursiere reusind s˘ a adune oavere considerabil˘a. Fiind un tip original si pasionat de matematic˘ a a scris un testa-ment inedit. Testamentul cont ¸ine dou a numere naturale: S reprezentˆand averea cetrebuie ımp˘ art it a mostenitorilor si N reprezentˆand alegerea sa pentru ımp˘ art ireaaverii.

Italag decide s a-si ımpart˘ a toat˘a averea, iar sumele pe care le acord˘ a mostenitorilorsa e ın ordine strict descresc˘ atoare.

De exemplu dac a averea ar 7 unit˘ati monetare, ar putea ımp˘ art it a astfel:

• 4 (unit ati primului mostenitor) 3 (unit˘ at i celui de-al doilea), sau

• 6 (unit ati primului mostenitor) 1 (unitate celui de-al doilea), sau

• 7 (unit ati doar primului mostenitor), sau

• 5 (unit ati primului mostenitor) 2 (unit˘ at i celui de-al doilea), sau

• 4 (unit ati primului mostenitor) 2 (unit˘ at i celui de-al doilea) 1 (unitate celuide-al treilea).

Vazand c a ıi este foarte greu s˘a verice dac a nu cumva a omis vreo variant˘ a

de ımp˘art ire, Italag le-a scris ın ordine lexicograc˘ a. Pentru exemplul de mai sus:4 2 1; 4 3; 5 2; 6 1; 7.A hot ar at ca banii s a e distribuit¸i conform celei de-a N -a posibilit at i din

ordinea lexicograc˘a.

Cerint ¸aScriet i un program care pentru numerele S , N date s a calculeze si s a aseze

num arul total de posibilit˘ ati de ımp˘art ire a averii, precum si modul ın care se faceaceast a ımp˘art ire conform cu a N -a posibilitate din ordinea lexicograc˘ a.

Datele de intrareFisierul de intrare avere.in contine o singur a linie pe care se aa dou a numere

naturale separate printr-un singur spat ¸iu:

−primul num˘ar (S ) reprezint˘a suma total˘a

−cel de-al doilea ( N ) reprezint˘a num arul de ordine al pozit¸iei cautate.

Datele de iesireFisierul de iesire avere.out va cont ine dou a linii:

−pe prima linie va asat num˘ arul total de modalit˘ ati de ımp˘art ire a averii;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 425/518

16.2. PROBLEME REZOLVATE 413

−pe cea de-a doua linie va asat˘ a a N -a posibilitate de ımp˘ art ire a lui S conform cerint ei ın ordine lexicograc˘ a. Elementele sale vor separate prin cˆ ateun spat iu.

Restrict ii si precizari

• 1 < S < 701

• 0 < N < num arul total de posibilit˘ at i cu suma S

• Se acord a punctaj part ¸ial pentru ecare test: 5 puncte pentru determinareacorect a a num arului de posibilit˘ati de ımp˘art ire a lui S si 5 puncte pentru deter-minarea corect˘a a posibilit at ii N , din ordinea lexicograc˘a.

• Posibilit atile de ımp˘art ire a averii sunt numerotate ıncepˆ and cu 1.

•Fie x = ( x1 , x2 ..., x m ) si y = ( y1 , y2 ,...,y p) dou a siruri. Spunem c˘ a x preced ape y din punct de vedere lexicograc, dac˘ a exist a k ≥1, astfel ıncˆat x i = yi , pentruorice i = 1 ,...,k

−1 si xk < y k .

Exemple: 4 2 1 preced a secvent a 4 3 deoarece (4 = 4, 2 < 3), iar 6 1 preced a7 deoarece 6 < 7.

Exemple:

avere.in avere.out7 2 5

4 3

avere.in avere.out12 5 15

6 5 1

avere.in avere.out700 912345678912345678 962056220379782044

175 68 63 58 54 45 40 36 34 32 20 18 17 14 11 9 3 2 1

Timp maxim de execut ¸ie/test: 1 secund a pentru Windows si 0.1 secundepentru Linux.

Limita total˘ a de memorie sub Linux este 3Mb din care 1Mb pentrustiv˘a.

Indicat ¸ii de rezolvare - descriere solut ¸ie *

stud. Emilian Miron, Universitatea Bucuresti Problema se rezolv˘a prin programare dinamic˘ a dup a valoarea maxim˘a pe care

poate s a o ia primul num˘ar ın cadrul descompunerii si dup˘ a suma total˘a.Obt inem recurent¸a:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 426/518

414 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

c[v][s] = c[v −1][s] //punˆ and pe prima pozit¸ie 1, 2, ...,v-1+ c[v

−1][s

−v] //punnd pe prima pozit ¸ie v

c[0][0] = 1,c[0][s] = 0 pentru s > 0

Num arul total de posibilit˘ at i va egal cu c[S ][S ].Reconstituirea solut ¸iei se face stabilind primul num˘ ar ca ind cel mai mic i

astfel ıncˆat c[i][S ] ≥N si c[i −1][S ] < N . Procesul continu˘a pentru S = S −i siN = N −c[i −1][S ] pan a cand N = 0.

Observ am ca recurent a depinde doar de linia anterioar˘ a, asa c a ea se poatecalcula folosind un singur vector. Aceasta ne ajut˘ a pentru a respecta limita dememorie. Astfel calcul˘am toate valorile folosind un singur vector si p˘ astr am laecare pas c[i][S ]. Reconstruct¸ia se face recalcul and valorile la ecare pas pentruS -ul curent.

Solutia descris a efectueaz a O(S 2

L) operat ii, unde L este lungimea solut¸iei.

Observ and L = maximO (S 1/ 2) timpul total este O(S 3/ 2).O solut ie backtracking obt ¸ine 20 puncte, iar una cu memorie O(N 2) 50

puncte.

Codul sursa

import java.io.*; // c[0][0]=1; c[0][s]=0; pentru s=1,2,...,Sclass Avere1 // c[v][s]=c[v-1][s]; pentru v>=1 si s<v // c[v][s]=c[v-1][s]+c[v-1][s-v]; pentru v>=1 si s>=v

static int S; // test 4 ??? test 5 = gresit N (>...) in fisier intrarestatic long n; // toate celelalte: OK rezultat si timp !!!

static long c[][]; // dar fara economie de memorie !!!!!!!

public static void main(String[] args) throws IOException

long t1,t2;t1=System.nanoTime();

int s,v;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("10-avere.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("avere.out")));st.nextToken(); S=(int)st.nval;st.nextToken(); n=(int)st.nval;c=new long[S+1][S+1];

for(v=0;v<=S;v++) c[v][0]=(long)1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 427/518

16.2. PROBLEME REZOLVATE 415

for(v=1;v<=S;v++)for(s=0;s<=S;s++)

if(s<v) c[v][s]=c[v-1][s]; else c[v][s]=c[v-1][s]+c[v-1][s-v];//afism();

out.println(c[S][S]);while((n>0)&&(S>0))

v=0;while(c[v][S]<n) v++;out.print(v+" ");n=n-c[v-1][S];S=S-v;

out.close();t2=System.nanoTime();System.out.println("Timp = "+((double)(t2-t1))/1000000000);

// main(...)

static void afism()

int i,j;for(i=0;i<=S;i++)

for(j=0;j<=S;j++) System.out.print(c[i][j]+" ");System.out.println();

// afism()// class/*1 0 0 0 0 0 0 0 0 0 0 0 01 1 0 0 0 0 0 0 0 0 0 0 01 1 1 1 0 0 0 0 0 0 0 0 01 1 1 2 1 1 1 0 0 0 0 0 01 1 1 2 2 2 2 2 1 1 1 0 01 1 1 2 2 3 3 3 3 3 3 2 21 1 1 2 2 3 4 4 4 5 5 5 51 1 1 2 2 3 4 5 5 6 7 7 81 1 1 2 2 3 4 5 6 7 8 9 101 1 1 2 2 3 4 5 6 8 9 10 121 1 1 2 2 3 4 5 6 8 10 11 131 1 1 2 2 3 4 5 6 8 10 12 141 1 1 2 2 3 4 5 6 8 10 12 15Press any key to continue...

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 428/518

416 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

*/

16.2.19 Suma - ONI2005 cls 10Tradit¸ia este ca, la iesirea la pensie, pentru ecare zi de activitate ın slujba

sultanului, marele vizir s˘ a primeasc a o prim a stabilit˘a de marele sfat al t arii. Astfel,vizirul Magir a primit pentru doar 5 zile de activitate prima total˘ a de 411 galbeni,deoarece sfatul t¸arii a hot ar at pentru ziua ıntˆ ai o suma de 53 de galbeni, pentruziua a doua 200 de galbeni, pentru ziua a treia 12 galbeni, pentru ziua a patra 144de galbeni, iar pentru ziua a cincea doar 2 galbeni.

Vizirul Jibal, celebru pentru contribut ¸ia adus˘a la rezolvarea conictului dinzona, primeste dreptul ca, la iesirea la pensie, s˘ a modice sumele stabilite de sfatult arii, dar nu foarte mult. El poate uni cifrele sumelor stabilite si le poate desp˘ art iapoi, dup a dorint a, astfel ıncˆat, suma primit˘ a pe ecare zi sa nu dep aseasc˘a 999 degalbeni si s a primeasc a cel put in un galben pentru ecare dintre zilele de activitate.Astfel, dac a are doar 5 zile de activitate, pl˘ atite cu 23, 417, 205, 5 si respectiv 40 degalbeni, ın total 680 de galbeni, el poate opta pentru o nou˘ a distribut¸ie a cifrelornumerelor stabilite de marele sfat astfel: pentru prima zi cere 2 galbeni, pentru adoua 3, pentru a treia 417, pentru a patra 205 si pentru a cincea 540 de galbeni,primind astfel 1167 de galbeni ın total.

Cerint ¸aPentru num˘ arul de zile n si cele n sume stabilite de sfatul t ¸ arii pentru Jibal,

scriet i un program care s˘a determine cea mai mare prim˘ a total a care se poateobtine prin unirea si desp˘ art irea cifrelor sumelor date.

Datele de intrare

Fisierul de intrare suma.in contine:−pe prima linie un num˘ar natural n reprezentˆand num arul de zile de activ-

itate

− pe linia urm atoare, n numere naturale separate prin spat ¸ii s1 , s2 , ..., snreprezentˆand sumele atribuite de sfatul t ¸arii.

Datele de iesireFisierul de iesire suma.out va cont ine o singur a linie pe care va asat un

singur num˘ar natural reprezentˆ and prima total˘ a maxim a care se poate obt ine.

Restrict ii si precizari

• 1 < n < 501

• 0 < s i < 1000, pentru orice 1 ≤ i ≤n

•ˆIn orice distribut¸ie, ecare sum˘a trebuie s a e o valoare proprie (s˘a nuınceap˘a cu 0).

• Orice sum a dintr-o distribut ¸ie trebuie s˘a e nenul a.

• Pentru 20% din teste, n ≤10, pentru 50% din teste n ≤50.

Exemple

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 429/518

16.2. PROBLEME REZOLVATE 417

suma.in suma.out Explicat ie3 362 Prima maxim˘a (362) se obtine58 300 4 chiar pentru distribut ¸ia 58 300 4

suma.in suma.out Explicat ie5 1608 Prima maxim˘a (1608) se obtine23 417 205 5 40 pentru distribut¸ia 2 341 720 5 540

Timp maxim de execut ¸ie/test: 1 secund a pentru Windows si 0.1 secundepentru Linux.

Indicat ¸ii de rezolvare - descriere solut ¸ie

Solut ¸ia ocial˘ a Solut¸ia ISolutia propus˘a utilizeaz a metoda program˘ arii dinamice . Este implementat

un algoritm de expandare tip Lee realizat cu o coad˘a alocat a dinamic.Astfel, ecare cifr a contribuie la expandarea solut ¸iilor precedente care au

sans a de dezvoltare ulterioar˘ a. Vectorul best memoreaz a la ecare moment sumacea mai mare format˘a dintr-un num˘ ar dat de termeni.

Condit ia nc-nr<=(n-p^.t-1)*3+2 (unde nc este num arul total de cifre carese distribuie, nr este num arul de ordine al cifrei curente, n este num arul totalde termeni si p^.t este num arul de termeni ai solut ¸iei curente) testeaz˘ a ca, princrearea unui nou termen cu ajutorul cifrei curente, s˘ a mai existe sansa construiriicu cifrele ramase a unei solut i cu n termeni.

Condit ia nc-nr>=n-p^.t testeaz˘a ca, prin lipirea cifrei curente la ultimul

termen al solut¸iei curente, s˘a mai existe sansa construirii cu cifrele r˘ amase a uneisolut ii cu n termeni.

type pnod=^nod;nod=record

s:longint; sumat,last:word; nr. de termeni si ultimul termennext:pnod

end;

var n,nc,i,k:longint; f:text;best:array[1..1000]of longint;p,u:pnod;c:char;

procedure citire; determina numarul total de cifrevar i,x:longint;begin

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 430/518

418 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

assign(f,’suma.in’);reset(f);readln(f,n);for i:=1 to n do begin

read(f,x);repeat inc(nc);x:=x div 10 until x=0

end;close(f)

end;

expandarea corespunzatoare cifrei curenteprocedure calc(nr:longint;cif:byte);var c,q:pnod; gata:boolean;begin

c:=u;gata:=false;repeat

if (cif>0) and (nc-nr<=(n-p^.t-1)*3+2) and (best[p^.t]=p .s) thenbegin

new(u^.next);u:=u^.next;u^.s:=p^.s+cif;u^.t:=p^.t+1;u^.last:=cif

end;if (p^.last<100)and(nc-nr>=n-p^.t) then

beginnew(u^.next);u:=u^.next;u^.s:=p^.s+p^.last*9+cif;

u^.t:=p^.t;u^.last:=p^.last*10+cif;end;

if p=c then gata:=true;q:=p;p:=p^.next;dispose(q)

until gata;end;

recalcularea valorilor maxime memorate in vectorul bestprocedure optim;var i:longint;

q:pnod; gata:boolean;begin

for i:=1 to n do best[i]:=0;q:=p;gata:=false;repeat

if q^.s>best[q^.t] then best[q^.t]:=q .s;if q=u then gata:=true;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 431/518

16.2. PROBLEME REZOLVATE 419

q:=q^.nextuntil gata;

end;

BEGINcitire;reluarea citirii cifrelor, ignorand spatiilereset(f); readln(f);repeat read(f,c) until c<>’ ’;new(p);p^.s:=ord(c)-48;p^.t:=1;p^.last:=p^.s;best[1]:=p^.s;u:=p;for i:=2 to nc do begin

repeat read(f,c) until c<>’ ’;calc(i,ord(c)-48);optim

end;close(f);assign(f,’suma.out’);rewrite(f);writeln(f,best[n]);close(f)

END.

Solut¸ia IIProblema se rezolv˘a prin metoda programare dinamic˘ a . Concaten am nu-

merele si obt inem un sir (s˘ a ıl not˘am a) de cifre (de lungime L maxim N ∗3).

Pentru ecare pozit ¸ie p ( p = 1 ..L) calcul am prima maxim˘a pe care o putemobtine desp art ind subsirul de pˆ an a la p inclusiv ın n sume (n = 1 ..N ). Obt inemrelat ia:

smax[p][n] = min(smax[p-1][n-1]+a[p], // punˆ and ultima sum˘a format a doar din cifra a[i]smax[p-2][n-1]+a[p-1]*10+a[p], // punˆ and ultima sum˘a din 2 cifresmax[p-3][n-1]+a[p-2]*100+a[p-1]*10+a[p] // punˆ and ultima sum˘a din 3 cifre)

Trebuie avute ın vedere cazurile limit˘ a cand p = 1, p = 2 sau p = 3 si cazurileın care a[ p], a[ p−1] sau a[ p−2] sunt zero, moment ın care nu putem forma o sum˘ ade lungimea respectiv˘a, asa c a excludem termenii din expresia de minim.

Pentru usurint ¸aın implementare stoc˘ am smax [ p][n] = −infinit pentru cazulın care subsirul de pˆ an a la p nu poate ımp˘ art it ın mod corect ın n sume, iarobserv and c a recurent a depinde doar de ultimele 3 linii, nu p˘ astr am dec at peacestea si linia curent˘ a pentru a nu avea probleme cu memoria.

Obt inem memorie O(N ) si timp de execut¸ie O(L∗N ) = O(N 2);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 432/518

420 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

Codul sursa

Varianta 1:

import java.io.*; // fara economie de spatiuclass Suma1

static int n,nc; // nc=nr cifre din sirstatic int[] c=new int[1501]; // sirul cifrelorstatic int[][] s;

public static void main (String[] args) throws IOException

int i,j,x;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("suma.in")));PrintWriter out=new PrintWriter(new BufferedWriter(

new FileWriter("suma.out")));st.nextToken(); n=(int)st.nval;

nc=0;j=0;for(i=1;i<=n;i++)

st.nextToken(); x=(int)st.nval;if(x<10) c[++j]=x; nc+=1; else

if(x<100) c[++j]=x/10; c[++j]=x%10; nc+=2; elseif(x<1000) c[++j]=x/100; c[++j]=(x/10)%10; c[++j]=x%10; nc+=3;else System.out.println("Eroare date !");

s=new int[nc+1][n+1];calcul();afism();out.print(s[nc][n]);out.close();

// main(...)

static void calcul()

// s[i][j]=max(s[i-1][j-1]+c[i], // xj are 1: cifra c[i]// s[i-2][j-1]+c[i-1]*10+c[i], // xj are 2 cifre: c[i-1]c[i]// s[i-3][j-1]+c[i-2]*100+c[i-1]*10+c[i]); // xj are 3 cifre

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 433/518

16.2. PROBLEME REZOLVATE 421

int i,j,smax;

s[1][1]=c[1];s[2][1]=c[1]*10+c[2];s[3][1]=c[1]*100+c[2]*10+c[3];

if(c[2]!=0) s[2][2]=c[1]+c[2];

if((c[2]!=0)&&(c[3]!=0)) s[3][3]=c[1]+c[2]+c[3];

if(c[3]==0) if(c[2]!=0) s[3][2]=c[1]+c[2]; else // c[3]!=0

if(c[2]==0) s[3][2]=c[1]*10+c[3];else // c[2]!=0 && c[3]!=0s[3][2]=max(c[1]+c[2]*10+c[3],c[1]*10+c[2]+c[3]);

for(i=4;i<=nc;i++) // i = pozitie cifra in sirul cifrelorfor(j=1;j<=n;j++) // j = pozitie numar in sirul final al numerelor

smax=0;

if(j<=i)

if((c[i]!=0)&&(s[i-1][j-1]!=0))

smax=max(smax,s[i-1][j-1]+c[i]);

if((c[i-1]!=0)&&(s[i-2][j-1]!=0))smax=max(smax,s[i-2][j-1]+c[i-1]*10+c[i]);

if((c[i-2]!=0)&&(s[i-3][j-1]!=0))smax=max(smax,s[i-3][j-1]+c[i-2]*100+c[i-1]*10+c[i]);

s[i][j]=smax;// for

// calcul()

static int max(int a, int b)

if(a>b) return a; else return b;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 434/518

422 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

static void afism()

int i,j;

System.out.print(" \t");for(j=1;j<=n;j++) System.out.print(j+"\t");System.out.println();

for(i=1;i<=nc;i++)

System.out.print(i+" "+c[i]+" :\t");for(j=1;j<=n;j++) System.out.print(s[i][j]+"\t");System.out.println();

// afism()

// class

Varianta 2:

import java.io.*; // cu economie de spatiu !!!class Suma2

static int n,nc; // nc=nr cifre din sirstatic int[] c=new int[1501]; // sirul cifrelorstatic int[][] s;

public static void main (String[] args) throws IOExceptionlong t1,t2;t1=System.currentTimeMillis();

int i,j,x;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("suma.in")));PrintWriter out=new PrintWriter(new BufferedWriter(

new FileWriter("suma.out")));st.nextToken(); n=(int)st.nval;

nc=0;j=0;for(i=1;i<=n;i++)

st.nextToken(); x=(int)st.nval;if(x<10) c[++j]=x; nc+=1; else

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 435/518

16.2. PROBLEME REZOLVATE 423

if(x<100) c[++j]=x/10; c[++j]=x%10; nc+=2; elseif(x<1000) c[++j]=x/100; c[++j]=(x/10)%10; c[++j]=x%10; nc+=3;else System.out.println("Eroare date !");

s=new int[4][n+1]; // cu economie de spatiu !!!calcul();

out.print(s[nc%4][n]);out.close();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1));

// main(...)

static void calcul()

// s[i][j]=max(s[i-1][j-1]+c[i],// xj are 1: cifra c[i]// s[i-2][j-1]+c[i-1]*10+c[i], // xj are 2 cifre: c[i-1]c[i]// s[i-3][j-1]+c[i-2]*100+c[i-1]*10+c[i]); // xj are 3 cifre

int i,j,smax;

s[1][1]=c[1];s[2][1]=c[1]*10+c[2];s[3][1]=c[1]*100+c[2]*10+c[3];

if(c[2]!=0) s[2][2]=c[1]+c[2];

if((c[2]!=0)&&(c[3]!=0)) s[3][3]=c[1]+c[2]+c[3];

if(c[3]==0) if(c[2]!=0) s[3][2]=c[1]+c[2]; else // c[3]!=0

if(c[2]==0) s[3][2]=c[1]*10+c[3];else // c[2]!=0 && c[3]!=0s[3][2]=max(c[1]+c[2]*10+c[3],c[1]*10+c[2]+c[3]);

for(i=4;i<=nc;i++) // i = pozitie cifra in sirul cifrelorfor(j=1;j<=n;j++) // j = pozitie numar in sirul final al numerelor

smax=0;

if(j<=i)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 436/518

424 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

if((c[i]!=0)&&(s[(i-1+4)%4][j-1]!=0))smax=max(smax,s[(i-1+4)%4][j-1]+c[i]);

if((c[i-1]!=0)&&(s[(i-2+4)%4][j-1]!=0))smax=max(smax,s[(i-2+4)%4][j-1]+c[i-1]*10+c[i]);

if((c[i-2]!=0)&&(s[(i-3+4)%4][j-1]!=0))smax=max(smax,s[(i-3+4)%4][j-1]+c[i-2]*100+c[i-1]*10+c[i]);

s[i%4][j]=smax;

// calcul()

static int max(int a, int b)

if(a>b) return a; else return b;

// class

Varianta 3:

import java.io.*; // fara economie de spatiu dar cu afisare o solutie !class Suma3

static int n,nc; // nc=nr cifre din sirstatic int[] c=new int[1501]; // sirul cifrelorstatic int[][] s;static int[][] p; // predecesoristatic int[] sol; // o solutie

public static void main (String[] args) throws IOException

int i,j,x;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("suma.in")));PrintWriter out=new PrintWriter(new BufferedWriter(

new FileWriter("suma.out")));st.nextToken(); n=(int)st.nval;

nc=0;j=0;for(i=1;i<=n;i++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 437/518

16.2. PROBLEME REZOLVATE 425

st.nextToken(); x=(int)st.nval;if(x<10) c[++j]=x; nc+=1; elseif(x<100) c[++j]=x/10; c[++j]=x%10; nc+=2; elseif(x<1000) c[++j]=x/100; c[++j]=(x/10)%10; c[++j]=x%10; nc+=3;else System.out.println("Eroare date !");

s=new int[nc+1][n+1];p=new int[nc+1][n+1];calcul();afism(s); System.out.println();afism(p); System.out.println();

sol=new int[n+1];solutia();afisv(sol);

out.print(s[nc][n]);out.close();

// main(...)

static void solutia()

int i,i1,i2,k;i2=nc;

for(k=n;k>=1;k--)i1=p[i2][k];System.out.print(k+" : "+i1+"->"+i2+" ==> ");for(i=i1;i<=i2;i++) sol[k]=sol[k]*10+c[i];System.out.println(sol[k]);i2=i1-1;

// solutia()

static void calcul()

// s[i][j]=max(s[i-1][j-1]+c[i],// xj are 1: cifra c[i]// s[i-2][j-1]+c[i-1]*10+c[i], // xj are 2 cifre: c[i-1]c[i]// s[i-3][j-1]+c[i-2]*100+c[i-1]*10+c[i]); // xj are 3 cifre

int i,j,smax;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 438/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 439/518

16.2. PROBLEME REZOLVATE 427

// if

s[i][j]=smax;// for

// calcul()

static int max(int a, int b)

if(a>b) return a; else return b;

static void afism(int[][] x)

int i,j;

System.out.print(" \t");for(j=1;j<=n;j++) System.out.print(j+"\t");System.out.println();

for(i=1;i<=nc;i++)

System.out.print(i+" "+c[i]+" :\t");for(j=1;j<=n;j++) System.out.print(x[i][j]+"\t");System.out.println();

// afism()

static void afisv(int[] sol)

int i,sum=0;System.out.println();for(i=1;i<=n;i++)

System.out.print(sol[i]+" ");sum+=sol[i];

System.out.println(" ==> "+sum);

// afisv()// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 440/518

428 CAPITOLUL 16. PROGRAMARE DINAMIC ˘ A

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 441/518

Capitolul 17

Potrivirea sirurilor

Consider am un text (un sir de caractere) t = ( t1 , t2 ,...,t n ) si un sablon(tot un sir de caractere, numit pattern ın englez a) p = ( p1 , p2 ,...,p m ). Consider amm ≤n si dorim s a determin˘am dac a textul t contine sablonul p, adica, dac a exist a0 ≤d ≤n −m astfel ıncˆat td+ i = pi pentru orice 1 ≤ i ≤m. Problema potrivirii sirurilor const a ın determinarea tuturor valorilor d (considerate deplasamente ) cuproprietatea ment ¸ionat˘a.

17.1 Un algoritm inecient

Pentru ecare pozit ¸ie i cuprins a ıntre 1 si n−m +1 vom verica dac˘a subsirul(x i , x i+1 ,...,x i + m −1) coincide cu y.

import java.io.*;class PotrivireSir

static char[] t,p;static int n,m;

public static void main(String[] args) throws IOException

int i,j;String s;

BufferedReader br=new BufferedReader(new FileReader("potriviresir.in"));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("potriviresir.out")));

429

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 442/518

430 CAPITOLUL 17. POTRIVIREA SIRURILOR

s=br.readLine();n=s.length();t=new char[n+1];for(i=0;i<n;i++) t[i+1]=s.charAt(i);System.out.print("t : ");afisv(t,1,n);

s=br.readLine(); m=s.length();p=new char[m+1];for(i=0;i<m;i++) p[i+1]=s.charAt(i);System.out.print("p : ");afisv(p,1,m);System.out.println();

for(i=1;i<=n-m+1;i++)

for(j=1;j<=m;j++) if(p[j]!=t[i+j-1]) break;j--; // ultima pozi\c tie potrivita

if(j==m) afisv(t,1,n); afisv(p,i,i+j-1); System.out.println(); out.close();

//main()

static void afisv(char[] x, int i1, int i2)int i;for(i=1;i<i1;i++) System.out.print(" ");for(i=i1;i<=i2;i++) System.out.print(x[i]);System.out.println();

// afisv(...)//class/*x : abababaababaababay : abaabab

abababaababaababaabaabab

abababaababaababaabaabab

*/

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 443/518

17.2. UN ALGORITM EFICIENT - KMP 431

17.2 Un algoritm ecient - KMP

Algoritmul KMP (Knuth-Morris-Pratt) determin˘ a potrivirea sirurilor folosindinformat ii referitoare la potrivirea subsirului cu diferite deplasamente ale sale.

Pentru

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17t: a b a b a b a a b a b a a b a b a

si 1 2 3 4 5 6 7 p: a b a a b a b exist a dou a potriviri:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17t: a b a b a b a a b a b a a b a b a

p: a b a a b a b1 2 3 4 5 6 7

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17t: a b a b a b a a b a b a a b a b a

p: a b a a b a b1 2 3 4 5 6 7

Sirul inecient de ıncerc˘ ari este:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

t: a b a b a b a a b a b a a b a b a p: a b a a b a b p: a b a a b a b p: a b a a b a b p: a b a a b a b p: a b a a b a b * p: a b a a b a b p: a b a a b a b p: a b a a b a b p: a b a a b a b p: a b a a b a b * p: a b a a b a b

1 2 3 4 5 6 7

Prima nepotrivire din ecare ıncercare este evident ¸iat a prin caracter boldatiar solut iile sunt marcate cu *.

Dorim s a avans am cu mai mult de un pas la o nou˘ a ıncercare, f˘ar a sa riscamsa pierdem vreo solut¸ie!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 444/518

432 CAPITOLUL 17. POTRIVIREA SIRURILOR

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17t: a b a b a b a a b a b a a b a b a

p: a b a a b a b p: a b a a b a b p: a b a a b a b * p: a b a a b a b * p: a b a

Not am prin t[i..j ] secventa de elemente consecutive ( t i ,...,t j ) (cuprins˘a ıntrepozitiile i si j ) din sirul t = ( t1 , t2 ,...,t n ).

Sa presupunem c˘a suntem la un pas al veric˘arii potrivirii cu un deplasamentd si prima nepotrivire a ap˘ arut pe pozit¸ia i din text si pozit ¸ia j + 1 din sablon,deci t[i − j..i −1] = p[1..j ] si t[i] = p[ j + 1].

Care este cel mai bun deplasament d′ pe care trebuie s˘a-l ıncercam?

1 . . . . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . .. . .

n

m

m

i

j+1

k+1x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x

1 k

1 jp:

t: i-j i-k

d

d'

i-1

j+1-k

p:

Figura 17.1: Deplasare optim˘ a

Folosind Figura 17.2, dorim s˘ a determin˘am cel mai mare indice k < j astfelınc at p[1..k] = p[ j + 1 −k..j ]. Cu alte cuvinte, dorim s˘a determin˘am cel mailung sux al secvent ei p[1..j ] iar noul deplasament d′ trebuie ales astfel ıncˆ at s arealizeze acest lucru. Este astfel realizat˘ a si potrivirea textului t cu sablonul p,t[i −k..i −1] = p[1..k].

Ramane sa vericam apoi dac a t[i] = p[k + 1].Observ am ca noul deplasament depinde numai de sablonul p si nu are nici o

legatur˘a cu textul t.Algoritmul KMP utilizeaz˘ a pentru determinarea celor mai lungi suxe o

funct ie numit˘a next .Dat ind sirul de caractere p[1..m ], functia

next : 1, 2,...,m → 0, 1,...,m −1este denit˘a astfel:

next ( j ) = max k/k < j si p[1..k] este sux pentru p[1..j ].

Cum determin˘am practic valorile funct ¸iei next ?

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 445/518

17.2. UN ALGORITM EFICIENT - KMP 433

Initializ am next [1] = 0.Presupunem c˘a au fost determinate valorile next [1], next [2], ..., next [ j ].Cum determin˘am next [ j + 1]?

1 . . . . . . . . . . . .

. . .

. . .

. . . . . . . . .

. . . . . .. . .

j+1

k+1

k'+1

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

1 k'

1 k

p:

j+1-k j+1-k' j

k+1-k'. . .

. . .

. . .

. . .

. . .

. . .p:

p:

Figura 17.2: Funct ¸ia next

Ne ajut am de Figura 17.2 pentru a urm˘ ari mai usor rat ¸ionamentul! In aceast agur a next [ j ] = k si next [k] = k′.

Daca p[ j +1] = p[k+1] (folosind notat¸iile din gur a) atunci next [ j +1] = k+1.Obt inem:

daca p[ j + 1] = p[next ( j ) + 1] atunci next [ j + 1] = next ( j ) + 1 .

Ce se ıntˆampl a dac a p[ j + 1] = p[k + 1]?Caut am un sux mai mic pentru p[1..j ]! Fie acesta p[1..k ′]. Dar acest sux

mai mic este cel mai lung sux pentru p[1..k], cu alte cuvinte

k′ = next (k) = next (next ( j )) .Astfel, dac a p[ j + 1] = p[k′ + 1] atunci next ( j + 1) = k′ + 1.Obt inem:

dac a p[ j + 1] = p[next (next ( j )) + 1] atunci next [ j + 1] = next (next ( j )) + 1 .

Daca nici acum nu avem egalitate de caractere, vom continua acelasi rat ¸iona-ment p an a cand g asim o egalitate de caractere sau lungimea prexului c˘ autateste 0. Evident, acest algoritm se termin˘ a ıntr-un num˘ ar nit de pasi pentru c˘ a j > k > k ′ > ... ≥0. Daca ajungem la 0, atunci vom avea next ( j + 1) = 0.

Ordinul de complexitate al algoritmului KMP este O(n + m).

import java.io.*;class KMP

static int na=0; // nr aparitiistatic char[] t,p; // t[1..n]=text, p[1..m]=patternstatic int[] next;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 446/518

434 CAPITOLUL 17. POTRIVIREA SIRURILOR

static void readData() throws IOException

String s;char[] sc;int i,n,m;BufferedReader br=new BufferedReader(new FileReader("kmp.in"));s=br.readLine();sc=s.toCharArray();n=sc.length;t=new char[n+1];for(i=1;i<=n;i++) t[i]=sc[i-1];

s=br.readLine();sc=s.toCharArray(); m=sc.length;p=new char[m+1];for(i=1;i<=m;i++) p[i]=sc[i-1];

//readData()

static int[] calcNext(char[] p)

int m=p.length-1;int[] next=new int[m+1]; // next[1..m] pentru p[1..m]next[1]=0; // initializareint k=0; // nr caractere potrivite

int j=2;while(j<=m)

while(k>0&&p[k+1]!=p[j]) k=next[k];if(p[k+1]==p[j]) k++;next[j]=k; j++;

return next;

// calcNext()

static void kmp(char[] t, char[] p) // t[1...n], p[1..m]

int n=t.length-1, m=p.length-1;next=calcNext(p);int j=0; // nr caractere potrivite dejaint i=1; // ultima pozitie a sufixuluiwhile(i<=n) // t[1..n]

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 447/518

17.2. UN ALGORITM EFICIENT - KMP 435

while(j>0&&p[j+1]!=t[i]) j=next[j];if(p[j+1]==t[i]) j++;if(j==m)

na++;System.out.println("pattern cu deplasarea "+(i-m)+" : ");afissol(t,p,i-m);j=next[j];

i++;

// while// kmp

static void afissol(char[] t, char[] p, int d)

int i, n=t.length-1, m=p.length-1;for(i=1;i<=n;i++) System.out.print(t[i]);System.out.println();for(i=1;i<=d;i++) System.out.print(" ");for(i=1;i<=m;i++) System.out.print(p[i]);System.out.println();

// afissol(...)

public static void main(String[] args) throws IOException

readData();

kmp(t,p);PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("kmp.out")));

out.println(na);out.close();

//main()//class/*pattern apare cu deplasarea 5 :12312123412123412

1234pattern apare cu deplasarea 11 :12312123412123412

1234*/

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 448/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 449/518

17.3. PROBLEME REZOLVATE 437

static char[] x,y; // x[1..n]=text, y[1..m]=patternstatic int[] next;

static void readData() throws IOException

String s;char[] sc;int i;BufferedReader br=new BufferedReader(new FileReader("circular.in"));

n=Integer.parseInt(br.readLine()); // System.out.println("n="+n);

x=new char[n+1];y=new char[n+1];

s=br.readLine(); sc=s.toCharArray(); // System.out.println("x="+s);for(i=1;i<=n;i++) x[i]=sc[i-1];

s=br.readLine(); sc=s.toCharArray(); // System.out.println("y="+s);for(i=1;i<=n;i++) y[i]=sc[i-1];

//readData()

static int[] calcNext(char[] p)

int m=n;int[] next=new int[m+1]; // next[1..m] pentru p[1..m]

next[1]=0; // initializareint k=0; // nr caractere potriviteint j=2;while(j<=m)

while(k>0&&p[k+1]!=p[j]) k=next[k];if(p[k+1]==p[j]) k++;next[j]=k; j++;

return next;

// calcNext()

static void kmp(char[] t, char[] p) // t[1...n], p[1..m]

int m=p.length-1;next=calcNext(p);int j=0; // nr caractere potrivite dejaint i=1; // ultima pozitie a sufixului

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 450/518

438 CAPITOLUL 17. POTRIVIREA SIRURILOR

while((i<=2*n)&&(d==-1)) // t[1..n]

while(j>0&&p[j+1]!=t[(i>n)?(i-n):i]) j=next[j];if(p[j+1]==t[(i>n)?(i-n):i]) j++;if(j==m) d=i-n; break; i++;

// while// kmp

public static void main(String[] args) throws IOException

readData();kmp(x,y);PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("circular.out")));out.println(d);out.close();

//main()//class/*circular.in circular.out----------- ------------20 51231212341212341234112341212341234112312*/

17.3.2 Cifru - ONI2006 baraj

Copiii solarieni se joac a adesea trimit¸andu-si mesaje codicate. Pentru codi-care ei folosesc un cifru bazat pe o permutare p a literelor alfabetului solarian siun num ar natural d.

Alfabetul solarian cont¸ine m litere foarte complicate, asa c˘ a noi le vomreprezenta prin numere de la 1 la m.

Dat ind un mesaj ın limbaj solarian, reprezentat de noi ca o succesiunede n numere cuprinse ıntre 1 si m, c1c2 ...cn , codicarea mesajului se realizeaz˘ aastfel: se ınlocuieste ecare liter˘ a ci cu p(ci ), apoi sirul obt¸inut p(c1) p(c2)...p(cn )se roteste spre dreapta, f˘ acand o permutare circular˘ a cu d pozitii rezultˆand sirul p(cn −d+1 )...p(cn −1) p(cn ) p(c1) p(c2)...p(cn −d ).

De exemplu, pentru mesajul 213321, permutarea p = (312) (adic˘a p(1) = 3, p(2) = 1, p(3) = 2) si d = 2. Aplic and permutarea p vom obt ine sirul 132213, apoirotind spre dreapta sirul cu dou˘ a pozit ii obt inem codicarea 131322.

Cerint ¸a:

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 451/518

17.3. PROBLEME REZOLVATE 439

Date ind un mesaj necodicat si codicarea sa, determinat ¸i cifrul folosit(permutarea p si num˘arul d).

Date de intrare:Fisierul de intrare cifru.in contine pe prima linie numele naturale n si m,

separate prin spat ¸iu, reprezentˆ and lungimea mesajului si respectiv num˘ arul delitere din alfabetul solarian. Pe cea de a doua linie este scris mesajul necodicatca o succesiune de n numere cuprinse ıntre 1 si m separate prin cˆate un spat¸iu.Pe cea de a treia linie este scris mesajul codicat ca o succesiune de n numerecuprinse ıntre 1 si m separate prin cˆate un spat¸iu.

Date de iesire:Fisierul de iesire cifru.out va cont ine pe prima linie num˘arul natural d,

reprezentˆand num arul de pozit ii cu care s-a realizat permutarea circular˘ a spredreapta. Dac˘ a pentru d exist a mai multe posibilit˘at ii se va alege valoarea minim˘a.Pe urm atoarea linie este descris˘ a permutarea p. Mai exact se vor scrie valorile p(1) , p(2) ,...,p (m) separate prin cˆate un spat¸iu.

Restrict ¸ii:n ≤100000m ≤9999Mesajul cont ine ecare num˘ar natural din intervalul [1 , m] cel putin o dat˘a.Pentru teste cu m ≤5 se acorda 40 de puncte din care 20 pentru teste si cu

n ≤2000.Exemplu:

cifru.in cifru.out6 3 22 1 3 3 2 1 3 1 21 3 1 3 2 2

Timp maxim de execut ¸ie/test: 0.2 secundeIndicatii de rezolvare:Solut ¸ia comisiei

Fiecare aparit ¸ie a unui simbol din alfabet ıntr-un sir se ınlocuieste cu distant ¸afat a de precedenta aparit ¸ie a aceluiasi simbol (considerˆ and sirul circular, deci pen-tru prima aparit ¸ie a simbolului se ia distant ¸a fat a de ultima aparit ¸ie a aceluiasisimbol).

Facand aceast˘a recodicare pentru cele dou˘ a siruri reducem problema la de-terminarea permut˘ arii circulare care duce primul sir ın al doilea, care poate rezolvat˘a cu un algoritm de pattern matching, dac˘ a concaten˘am primul sir cu elınsusi rezultˆ and o complexitate O(n).

Pentru m mic se pot genera toate permut˘ arile mult imii

1, 2,...,m

facand

pentru ecare permutare o c˘ autare (cu KMP de exemplu), iar pentru n mic sepoate c auta permutarea pentru ecare d = 0 , 1,...,n .

Codul sursa

import java.io.*;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 452/518

440 CAPITOLUL 17. POTRIVIREA SIRURILOR

class kmp

static int[] t0; // text mesaj necodificat --> spatiu ... de eliberat !static int[] t1; // text mesaj codificat --> spatiu ... de eliberat !

static int[] d0; // distante ... mesaj necodificatstatic int[] d1; // distante ... mesaj codificat

static int[] t; // text in KMP ... (d0,d0) ... d0 dublat ... spatiu !!!static int[] s; // sablon in KMP ... (d1)static int[] p; // prefix in KMP ... 1,2,...n

static int[] ua; // pozitia ultimei aparitii ... 1,2,...,m ... ==> d[] mai rapid ...static int[] perm;// permutarea

static int n,m; // ... n=100.000, m=9.999 ... maxim !!! ==> 200K

public static void main(String[] args) throws IOException

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("9-cifru.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("cifru.out")));

int i,j,j0,j1,k,deplasarea=-1;

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

ua=new int[m+1];

t0=new int[n+1];t1=new int[n+1];d0=new int[n+1];d1=new int[n+1];p=new int[n+1];

for(i=1;i<=n;i++) st.nextToken(); t0[i]=(int)st.nval; for(i=1;i<=n;i++) st.nextToken(); t1[i]=(int)st.nval; distanta(t0,d0);distanta(t1,d1);//afisv(t0,1,n); afisv(d0,1,n); System.out.println();//afisv(t1,1,n); afisv(d1,1,n); System.out.println();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 453/518

17.3. PROBLEME REZOLVATE 441

s=d0;prefix(s,p,n);//afisv(s,1,n); afisv(p,1,n); System.out.println();

t=new int[2*n+1]; // ocupa spatiu prea mult; aici standard dar ...for(i=1;i<=n;i++) t[i]=t[n+i]=d1[i];//afisv(t,1,2*n);

deplasarea=kmp(t,2*n,s,n)-1; // d1 dublat si caut d0 ...out.println(deplasarea);System.out.println(deplasarea);

// permutarea ...perm=ua; // economie de spatiu ...for(i=1;i<=m;i++) perm[i]=0;k=0; // nr elemente plasate deja in permutare ...j1=0;for(i=1;i<=n;i++)

j1++;j0=n-deplasarea+i;if(j0>n) j0=j0-n;//System.out.println(i+" : "+j0+" "+j1);if(perm[t0[j0]]==0)

perm[t0[j0]]=t1[j1];

k++;if(k==m) break;

//afisv(perm,1,m);

for(i=1;i<=m;i++) out.print(perm[i]+" ");out.close();

// main

static int kmp(int[] t, int n, int[] s, int m)// t1,...,tn si s1,...,sm

int k,i,pozi=-1;k=0;for (i=1;i<=n;i++)

while(k>0&&s[k+1]!=t[i]) k=p[k];if (s[k+1]==t[i]) k++;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 454/518

442 CAPITOLUL 17. POTRIVIREA SIRURILOR

if(k==m)

pozi=i-m+1;//System.out.println("incepe pe pozitia "+pozi);break; // numai prima aparitie ... !!!

// forreturn pozi;

// kmp(...)

static void distanta(int[] t,int[] d) // t=text, d=distante ...

int i,j,k;for(i=1;i<=m;i++) ua[i]=0;

for(i=1;i<=n;i++)

if(ua[t[i]]!=0) // stiu pozitia spre stanga a lui t[i] ...

if(ua[t[i]]<i)d[i]=i-ua[t[i]]; // e mai la stanga ...

elsed[i]=i-ua[t[i]]+n; // e mai la dreapta ...

ua[t[i]]=i; // noua pozitie a lui t[i] ...continue;

// nu a aparut inca in 1..i-1 ==> de la n spre stangak=i; // distanta spre stanga ... pana la n inclusiv ...j=n; // caut in zona n,n-1,n-2,...while(t[i]!=t[j])

k++;j--;

d[i]=k;ua[t[i]]=i;

// for i// distanta(...)

static void prefix(int[] s,int[] p,int m) // s=sablon, p=prefix, m=dimensiune

int i,k;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 455/518

17.3. PROBLEME REZOLVATE 443

p[1]=0;for(i=2;i<=m;i++)

k=p[i-1];while(k>0&&s[k+1]!=s[i]) k=p[k];if(s[k+1]==s[i]) p[i]=k+1; else p[i]=0;

// prefix()

static void afisv(int[] x, int i1, int i2)

int i;for(i=i1;i<=i2;i++) System.out.print(x[i]+" ");System.out.println();

// afisv(...)// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 456/518

444 CAPITOLUL 17. POTRIVIREA SIRURILOR

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 457/518

Capitolul 18

Geometrie computat ¸ionala

18.1 Determinarea orientarii

Consider am trei puncte ın plan P 1(x1 , y1), P 2(x2 , y2) si P 3(x3 , y3).Panta segmentului P 1P 2 : m12 = ( y2 −y1)/ (x2 −x1)Panta segmentului P 2P 3 : m23 = ( y3 −y2)/ (x3 −x2)

P1P1 P1

P2P2

P2

P3

P3P3

a) b) c)

Orientarea parcurgerii laturilor P 1P 2 si P 2P 3 (ın aceast˘a ordine):

• ın sens trigonometric (spre stˆ anga): m12 < m 23 , cazul a) ın gur˘a

•ın sensul acelor de ceas (spre dreapta): m12 > m 23 , cazul c) ın gur˘a

• varfuri coliniare: m12 = m23 , cazul b) ın gur˘a

Orientarea depinde de valoarea expresiei

o(P 1(x1 , y1), P 2(x2 , y2), P 3(x3 , y3)) = ( y2 −y1) ·(x3 −x2) −(y3 −y2) ·(x2 −x1)

445

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 458/518

446 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

astfel

o(P 1(x1 , y1), P 2(x2 , y2), P 3(x3 , y3))< 0 ⇒ sens trigonometric= 0 ⇒ coliniare> 0 ⇒ sensul acelor de ceas

18.2 Testarea convexitat ¸ii poligoanelor

Consider am un poligon cu n varfuri P 1(x1 , y1)P 2(x2 , y2)...P n (xn yn ), n ≥3.Poligonul este convex dac˘a si numai dac˘a perechile de segmente

(P 1P 2 , P 2P 3), (P 2P 3 , P 3P 4), ..., (P n −2P n −1 , P n −1P n ) si (P n −1P n , P n P 1)

au aceeasi orientare sau sunt colineare.

P1

P7 P6

P5

P4P3P2

P1

P7 P6 P5

P4

P3P2

a) b)

18.3 Aria poligoanelor convexe

Aria poligonului convex cu n varfuri P 1(x1 , y1)P 2(x2 , y2)...P n (xn yn ), n ≥ 3se poate determina cu ajutorul urm˘ atoarei formule:

12 |x1y2 + x2y3 + ... + xn −1yn + xn y1 −y1x2 + y2x3 + ... + yn −1xn + yn x1|

Expresia de sub modul este pozitiv˘ a dac a orientarea P 1 →P 2 →...P n →P 1este ın sens trigonometric, este negativ˘ a dac a orientarea P 1 →P 2 →...P n →P 1este ın sensul acelor de ceasornic si este nul˘ a dac a punctele P 1(x1 , y1), P 2(x2 , y2),..., P n (xn yn ) sunt colineare. Reciproca acestei armat ¸ii este deasemenea adev˘ arat˘a

ın cazul poligoanelor convexe.

18.4 Pozit ¸ia unui punct fat ¸a de un poligon convex

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 459/518

18.5. POZITIA UNUI PUNCT FAT ˘ A DE UN POLIGON CONCAV 447

Consider am un poligon convex cu n varfuri P 1(x1 , y1)P 2(x2 , y2)...P n (xn yn ),n

≥3 si un punct P

0(x

0, y

0). Dorim s a determin˘am dac a punctul P

0(x

0, y

0) este

ın interiorul poligonului.Pentru comoditatea prezent˘ arii consider am si punctul P n +1 (xn +1 , yn +1 ) unde

x1 = xn +1 si y1 = yn +1 , adic a punctul P n +1 este de fapt tot punctul P 1 .Consider am o latur˘a oarecare [ P i P i+1 ] (1 ≤ i ≤n) a poligonului.Ecuat ia dreptei ( P i P i+1 ) este

(P i P i +1 ) : y −yi =yi +1 −yi

x i +1 −x i(x −x i )

Aducem la acelasi numitor si consider˘ am funct ia

f i (x, y ) = ( y −yi ) ·(x i+1 −x i ) −(x −x i ) ·(yi+1 −yi )

Dreapta ( P i P i+1 )ımparte planulın dou˘ a semiplane. Funct ¸ia f i (x, y) are valoride acelasi semn pentru toate punctele din acelasi semiplan, valori cu semn contrarpentru toate punctele din cel˘ alalt semiplan si valoarea 0 pentru doate punctelesituate pe dreapt˘ a.

Pentru a siguri c˘a punctul P 0(x0 , y0) se aa ın interiorul poligonului (acestaind convex) trebuie s˘a veric am dac a toate v arfurile poligonului ımpreun˘ a cupunctul P 0(x0 , y0) sunt de aceeasi parte a dreptei ( P i P i +1 ), adic a toate valorilef i (x j , yj ) (1 ≤ j ≤ n, j = i si j = i + 1) au acelasi semn cu f i (x0 , y0) (sausunt nule dac˘a accept am prezent a punctului P 0(x0 , y0) pe frontiera poligonului).Aceasta este o condit¸ie necesar a dar nu si sucient˘a. Vom verica dac˘a pentruorice latur˘a [P i P i+1 ] (1 ≤ i ≤ n) a poligonului toate celelalte vˆ arfuri sunt ınacelasi semiplan cu P 0(x0 , y0) (din cele dou a determinate de dreapta suport a

laturii respective) iar dac˘ a se ıntˆampl a acest lucru atunci putem trage concluziaca punctul P 0(x0 , y0) se aa ın interiorul poligonului convex.O alt a modalitate de vericare dac˘ a punctul P 0(x0 , y0) este ın interiorul

sau pe frontiera poligonului convex P 1(x1 , y1)P 2(x2 , y2)...P n (xn yn ) este vericareaurm atoarei relat¸ii:

arie poligon (P 1P 2 ...P n ) =n

k =1

arie triunghi (P 0P k P k+1 )

unde punctul P (xn +1 , yn +1 ) este de fapt tot punctul P 1(x1 , y1).

18.5 Pozit ¸ia unui punct fat ¸ a de un poligon concav

Consider am un poligon concav cu n varfuri P 1(x1 , y1)P 2(x2 , y2)...P n (xn yn ),n ≥3 si un punct P 0(x0 , y0). Dorim s a determin˘am dac a punctul P 0(x0 , y0) esteın interiorul poligonului.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 460/518

448 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

Poligonul concav se descompune ın poligoane convexe cu ajutorul diago-nalelor interne si se foloseste un algoritm pentru poligoane convexe pentru ecarepoligon convex astfel obt inut. Dac˘a punctul este ın interiorul unui poligon convexobtinut prin partit ¸ionarea poligonului concav atunci el se a˘ aın interiorul acestuia.Daca nu se a a ın nici un poligon convex obt¸inut prin partit ¸ionarea poligonuluiconcav atunci el nu se a˘a ın interiorul acestuia.

P1

P7 P6

P5

P4

P3

P2

P1

P7 P6

P5

P4

P3

P2

a) b)

18.6 Infasuratoarea convexa

18.6.1 Impachetarea Jarvis

1

1

2

2

3

3

4

4

5

5

6 7 1

1

2

2

3

3

4

4

5

5

6 7

a) b)

Toate punctele de pe ınf˘ asur˘atoarea convex˘a (cazul a) ın gur˘a):

import java.io.*; // infasuratoare convexaclass Jarvis1 // pe frontiera coliniare ==> le iau pe toate ... !!!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 461/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 449

static int n,npic=0; // npic=nr puncte pe infasuratoarea convexastatic int [] x;static int [] y;static int [] p; // precedentstatic int [] u; // urmator

static void afisv(int[] a, int k1, int k2)

int k;for(k=k1;k<=k2;k++) System.out.print(a[k]+" ");System.out.println();

static int orient(int i1, int i2, int i3)

long s=(y[i1]-y[i2])*(x[i3]-x[i2])-(y[i3]-y[i2])*(x[i1]-x[i2]);if(s<0) return -1; elseif(s>0) return 1; else return 0;

static void infasurareJarvis() throws IOException

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

int i0,i,i1,i2;i0=1;

for(i=2;i<=n;i++) if((x[i]<x[i0])||((x[i]==x[i0])&&(y[i]<y[i0]))) i0=i;System.out.println("Stanga_Jos ==> P"+i0+" : "+x[i0]+" "+y[i0]);

i1=i0;npic++;System.out.println(npic+" --> "+i1); //br.readLine();do

i2=i1+1; if(i2>n) i2-=n;for(i=1;i<=n;i++)

//System.out.println("orient("+i1+","+i+","+i2+")="+orient(i1,i,i2));//br.readLine();if(orient(i1,i,i2)>0) i2=i; else

if(orient(i1,i,i2)==0) // coliniareif( // i intre i1 i2 ==> cel mai apropiat((x[i]-x[i1])*(x[i]-x[i2])<0)||((y[i]-y[i1])*(y[i]-y[i2])<0)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 462/518

450 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

)i2=i;

u[i1]=i2;p[i2]=i1;i1=i2;npic++;System.out.println(npic+" --> "+i1); //br.readLine();

while(i2!=i0);npic--; // apare de doua ori primul punct !System.out.print("u : "); afisv(u,1,n);System.out.print("p : "); afisv(p,1,n);

// infasurareJarvis()

public static void main(String[] args) throws IOException

int k;StreamTokenizer st= new StreamTokenizer(

new BufferedReader(new FileReader("jarvis.in")));st.nextToken(); n=(int)st.nval;x=new int[n+1];y=new int[n+1];p=new int[n+1];u=new int[n+1];

for(k=1;k<=n;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;

infasurareJarvis();

//main//class

Far a punctele coliniare de pe ınf˘ asur˘atoarea convex˘a (cazul b) ın gur˘a):

import java.io.*; // infasuratoare convexaclass Jarvis2 // pe frontiera coliniare ==> iau numai capetele ... !!!

static int n,npic=0; // npic=nr puncte pe infasuratoarea convexastatic int [] x;static int [] y;static int [] p; // precedentstatic int [] u; // urmator

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 463/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 451

static void afisv(int[] a, int k1, int k2)

int k;for(k=k1;k<=k2;k++) System.out.print(a[k]+" ");System.out.println();

static int orient(int i1, int i2, int i3)

long s=(y[i1]-y[i2])*(x[i3]-x[i2])-(y[i3]-y[i2])*(x[i1]-x[i2]);if(s<0) return -1; elseif(s>0) return 1; else return 0;

static void infasurareJarvis() throws IOException

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

int i0,i,i1,i2;i0=1;for(i=2;i<=n;i++) if((x[i]<x[i0])||((x[i]==x[i0])&&(y[i]<y[i0]))) i0=i;System.out.println("Stanga_Jos ==> P"+i0+" : "+x[i0]+" "+y[i0]);

i1=i0;npic++;System.out.println(npic+" --> "+i1); //br.readLine();

doi2=i1+1; if(i2>n) i2-=n;for(i=1;i<=n;i++)

//System.out.println("orient("+i1+","+i+","+i2+")="+orient(i1,i,i2));//br.readLine();if(orient(i1,i,i2)>0) i2=i; elseif(orient(i1,i,i2)==0) // coliniareif( // i2 intre i1 i ==> cel mai departat

((x[i2]-x[i1])*(x[i2]-x[i])<0)||((y[i2]-y[i1])*(y[i2]-y[i])<0))

i2=i;u[i1]=i2;p[i2]=i1;i1=i2;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 464/518

452 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

npic++;System.out.println(npic+" --> "+i1); //br.readLine();

while(i2!=i0);npic--; // apare de doua ori primul punct !System.out.print("u : "); afisv(u,1,n);System.out.print("p : "); afisv(p,1,n);

// infasurareJarvis()

public static void main(String[] args) throws IOException

int k;StreamTokenizer st= new StreamTokenizer(

new BufferedReader(new FileReader("jarvis.in")));st.nextToken(); n=(int)st.nval;x=new int[n+1];y=new int[n+1];p=new int[n+1];u=new int[n+1];for(k=1;k<=n;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;

infasurareJarvis();

//main//class

18.6.2 Scanarea Craham

Versiune cu mesaje pentru sortarea punctelor:

import java.io.*; // numai pentru sortare si mesaje ...class Graham0

static int n,npic=0; // npic=nr puncte pe infasuratoarea convexastatic int[] x;static int[] y;static int[] o; // o[k] = pozitia lui k inainte de sortarestatic int[] of; // of[k] = pozitia lui k dupa sortare

// pentru depanare ... stop ! ...static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 465/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 453

1

1

2

2

3

3

4

4

5

5

6 7

a) b)

1

1

2

2

3

3

4

4

5

5

6 7

a) b)

1

1

2

2

3

3

4

4

5

5

6 7 1

1

2

2

3

3

4

4

5

5

6 7

static void afisv(int[] a, int k1, int k2)

int k;for(k=k1;k<=k2;k++) System.out.print(a[k]+" ");System.out.print(" ");

static int orient(int i0,int i1, int i2)

long s=(y[i1]-y[i0])*(x[i2]-x[i0])-(y[i2]-y[i0])*(x[i1]-x[i0]);if(s<0) return -1; elseif(s>0) return 1; else return 0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 466/518

454 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

static void qsort(int p, int u) throws IOException

// aleg un punct fix kint k=(p+u)/2;

System.out.println("qsort: p="+p+" u="+u+" k="+k+" xk="+x[k]+" yk="+y[k]);System.out.print("x : "); afisv(x,p,u); System.out.println();System.out.print("y : "); afisv(y,p,u); System.out.println();

int i,j,aux;i=p;j=u;while(i<j)

while( (i<j)&&( (orient(1,i,k)<0)||

((orient(1,i,k)==0)&&(((x[i]-x[1])*(x[i]-x[k])<0)||((y[i]-y[1])*(y[i]-y[k])<0)))

))

i++;

while( (i<j)&&

( (orient(1,j,k)>0)||((orient(1,j,k)==0)&&

(((x[j]-x[1])*(x[j]-x[k])>0)||((y[j]-y[1])*(y[j]-y[k])>0)))))

j--;

if(i<j)

if(k==i) k=j; else if(k==j) k=i;// k=fix dar se poate schimba pozitiaaux=x[i]; x[i]=x[j]; x[j]=aux;aux=y[i]; y[i]=y[j]; y[j]=aux;aux=o[i]; o[i]=o[j]; o[j]=aux;

// while

System.out.println("Final while ... i="+i+" j="+j);// i=j si P[i] este pe locul lui !!!

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 467/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 455

System.out.print("x : "); afisv(x,p,i-1); afisv(x,i,i); afisv(x,i+1,u);System.out.println();System.out.print("y : "); afisv(y,p,i-1); afisv(y,i,i); afisv(y,i+1,u);System.out.println();br.readLine();

if(p<i-1) qsort(p,i-1);if(j+1<u) qsort(j+1,u);

// qSort(...)

static void scanareGraham() throws IOException

int i0,i,i1,i2,aux;

System.out.print("x : "); afisv(x,1,n); System.out.println();System.out.print("y : "); afisv(y,1,n); System.out.println();System.out.println();

i0=1;for(i=2;i<=n;i++) if((x[i]<x[i0])||((x[i]==x[i0])&&(y[i]<y[i0]))) i0=i;System.out.println("Stanga_Jos ==> P"+i0+" : "+x[i0]+" "+y[i0]+"\n");

aux=x[1]; x[1]=x[i0]; x[i0]=aux;aux=y[1]; y[1]=y[i0]; y[i0]=aux;aux=o[1]; o[1]=o[i0]; o[i0]=aux;

System.out.print("x : "); afisv(x,1,n); System.out.println();System.out.print("y : "); afisv(y,1,n); System.out.println();System.out.print("o : "); afisv(o,1,n); System.out.println();System.out.println();

qsort(2,n);

System.out.println();System.out.print("x : "); afisv(x,1,n); System.out.println();System.out.print("y : "); afisv(y,1,n); System.out.println();System.out.print("o : "); afisv(o,1,n); System.out.println();System.out.println();

// scanareGraham()

public static void main(String[] args) throws IOException

int k;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 468/518

456 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

StreamTokenizer st= new StreamTokenizer(new BufferedReader(new FileReader("graham.in")));

st.nextToken(); n=(int)st.nval;x=new int[n+1];y=new int[n+1];o=new int[n+1];of=new int[n+1];

for(k=1;k<=n;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;o[k]=k;

scanareGraham();

// ordinea finala (dupa sortare) a punctelorfor(k=1;k<=n;k++) of[o[k]]=k;System.out.println();System.out.print("of : "); afisv(of,1,n); System.out.println();System.out.println();

//main//class

Versiune cu toate punctele de pe ınf˘ asur˘atoare:

import java.io.*; // NU prinde punctele coliniarele pe ultima latura !class Graham1 // daca schimb ordinea pe "razele" din sortare, atunci ... // NU prinde punctele coliniarele pe prima latura, asa ca ...

static int n;static int np; // np=nr puncte pe infasuratoarea convexastatic int[] x;static int[] y;static int[] o; // pozitia inainte de sortarestatic int[] p; // poligonul infasuratoare convexa

static int orient(int i0,int i1, int i2)

long s=(y[i1]-y[i0])*(x[i2]-x[i0])-(y[i2]-y[i0])*(x[i1]-x[i0]);if(s<0) return -1; elseif(s>0) return 1; else return 0;

static void qsort(int p, int u)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 469/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 457

int i,j,k,aux;// aleg un punct fix kk=(p+u)/2;i=p;j=u;while(i<j)

while( (i<j)&&( (orient(1,i,k)<0)||

((orient(1,i,k)==0)&&(((x[i]-x[1])*(x[i]-x[k])<0)||((y[i]-y[1])*(y[i]-y[k])<0)))

)) i++;

while( (i<j)&&( (orient(1,j,k)>0)||

((orient(1,j,k)==0)&&(((x[j]-x[1])*(x[j]-x[k])>0)||((y[j]-y[1])*(y[j]-y[k])>0)))

)) j--;

if(i<j)

if(k==i) k=j; else if(k==j) k=i;// k=fix dar se poate schimba pozitiaaux=x[i]; x[i]=x[j]; x[j]=aux;aux=y[i]; y[i]=y[j]; y[j]=aux;aux=o[i]; o[i]=o[j]; o[j]=aux;

if(p<i-1) qsort(p,i-1);if(j+1<u) qsort(j+1,u);

// qSort(...)

static void scanareGraham() throws IOException

int i0,i,i1,i2,i3,aux;

i0=1;for(i=2;i<=n;i++) if((x[i]<x[i0])||((x[i]==x[i0])&&(y[i]<y[i0]))) i0=i;

aux=x[1]; x[1]=x[i0]; x[i0]=aux;aux=y[1]; y[1]=y[i0]; y[i0]=aux;aux=o[1]; o[1]=o[i0]; o[i0]=aux;

qsort(2,n);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 470/518

458 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

i1=1; p[1]=i1;i2=2; p[2]=i2;np=2;

i3=3;while(i3<=n)

while(orient(i1,i2,i3)>0)

i2=p[np-1];i1=p[np-2];np--;

np++;p[np]=i3;i2=p[np];i1=p[np-1];i3++;

// while

// plasez si punctele coliniare de pe ultima latura a infasuratoriii=n-1;while(orient(1,p[np],i)==0) p[++np]=i--;

// afisez rezultatele

System.out.print("punctele initiale: ");for(i=1;i<=np;i++) System.out.print(o[p[i]]+" ");System.out.println();System.out.print("infasuratoare x: ");for(i=1;i<=np;i++) System.out.print(x[p[i]]+" ");System.out.println();System.out.print("infasuratoare y: ");for(i=1;i<=np;i++) System.out.print(y[p[i]]+" ");System.out.println();

// scanareGraham()

public static void main(String[] args) throws IOException

int k;

StreamTokenizer st= new StreamTokenizer(new BufferedReader(new FileReader("graham1.in")));

st.nextToken(); n=(int)st.nval;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 471/518

18.6. INF ˘ ASUR ˘ ATOAREA CONVEX ˘ A 459

x=new int[n+1];y=new int[n+1];o=new int[n+1];p=new int[n+1];

for(k=1;k<=n;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;o[k]=k;

scanareGraham();

//main//class

Versiune f ar a puncte coliniare pe ınf˘ asur˘atoare:

import java.io.*; // aici ... infasuratoarea nu contine puncte coliniare ...class Graham2 // este o eliminare din rezultatul final dar ... // se pot elimina puncte la sortare si/sau scanare ...

static int n;static int np; // np=nr puncte pe infasuratoarea convexastatic int[] x;static int[] y;static int[] o; // pozitia inainte de sortare

static int[] p; // poligonul infasuratoare convexa

static int orient(int i0,int i1, int i2)

long s=(y[i1]-y[i0])*(x[i2]-x[i0])-(y[i2]-y[i0])*(x[i1]-x[i0]);if(s<0) return -1; elseif(s>0) return 1; else return 0;

static void qsort(int p, int u)// elimin si punctele coliniare (din interior)

int i,j,k,aux;// aleg un punct fix kk=(p+u)/2;i=p;j=u;while(i<j)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 472/518

460 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

while( (i<j)&&( (orient(1,i,k)<0)||

((orient(1,i,k)==0)&&(((x[i]-x[1])*(x[i]-x[k])<0)||((y[i]-y[1])*(y[i]-y[k])<0)))

)) i++;

while( (i<j)&&( (orient(1,j,k)>0)||

((orient(1,j,k)==0)&&(((x[j]-x[1])*(x[j]-x[k])>0)||((y[j]-y[1])*(y[j]-y[k])>0)))

)) j--;

if(i<j)

if(k==i) k=j; else if(k==j) k=i;// k=fix dar se poate schimba pozitiaaux=x[i]; x[i]=x[j]; x[j]=aux;aux=y[i]; y[i]=y[j]; y[j]=aux;aux=o[i]; o[i]=o[j]; o[j]=aux;

if(p<i-1) qsort(p,i-1);if(j+1<u) qsort(j+1,u);

// qSort(...)

static void scanareGraham() throws IOException

int i0,i,i1,i2,i3,aux;

i0=1;for(i=2;i<=n;i++) if((x[i]<x[i0])||((x[i]==x[i0])&&(y[i]<y[i0]))) i0=i;

aux=x[1]; x[1]=x[i0]; x[i0]=aux;aux=y[1]; y[1]=y[i0]; y[i0]=aux;aux=o[1]; o[1]=o[i0]; o[i0]=aux;

qsort(2,n);

i1=1; p[1]=i1;i2=2; p[2]=i2;np=2;

i3=3;while(i3<=n)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 473/518

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 474/518

462 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;o[k]=k;

scanareGraham();

//main//class

18.7 Dreptunghi minim de acoperire a punctelor

Se poate determina dreptunghiul minim de acoperire pentru ınf˘ asur˘atoareaconvex a (gura 18.1) pentru a prelucra mai put ¸ine puncte dar nu este obligatorieaceast a strategie.

xmin xmax

ymin

ymax

A

B

C

DM

N

R

Q

P1P2

P6

P4P3

P5

P7

P8P12

P11P10

P9

Figura 18.1: Dreptunghi minim de acoperire

Putem s˘a presupunem c˘a punctele formeaz˘a un poligon convex. Determinareadreptunghiului de arie minim˘ a care cont ine ın interiorul s˘ au (inclusiv frontiera)toate punctele date se poate face observˆ and c a o latur a a sa cont ine o latur˘a apoligonului convex. Pentru ecare latur˘ a a poligonului convex se determin˘ a drep-tunghiul minim de acoperire care cont ¸ine acea latur˘ a. Dintre aceste dreptunghiurise alege cel cu aria minim a.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 475/518

18.8. CERC MINIM DE ACOPERIRE A PUNCTELOR 463

18.8 Cerc minim de acoperire a punctelorSe poate determina cercul minim de acoperire pentru ınf˘ asur˘atoarea convex˘a

pentru a prelucra mai put ¸ine puncte dar nu este obligatorie aceast˘ a strategie.

Pk

C = C k-1k

C k+1k

CCk

a)

Pk+1

b)

x

Ordon am punctele astfel ıncˆ at pe primele pozit¸ii sa e plasate punctele deextrem (cel mai din stˆanga, urmat de cel mai din dreapta, urmat de cel mai de jos, urmat de cel mai de sus; dup˘a acestea urmeaz˘a celelalte puncte ıntr-o ordineoarecare). Presupunem c˘ a punctele, dup˘a ordonare, sunt: P 1(x1 , y1), P 2(x2 , y2),P 3(x3 , y3), ..., P n (xn , yn ).

Not am cu C i (a i , bi ; r i ) cercul de centru ( a i , bi ) si raz a minim a r i care acoper apunctele P 1 , P 2 ,...,P n .

Consider am cercul C 2(a2 , b2 ; r 2) unde a2 = ( x1 + x2)/ 2, b2 = ( y1 + y2)/ 2 sir 2 = 1

2 (x2 −x1)2 + ( y2 −y1)2 , adic a cercul de diametru [ P 1P 2].Sa presupunem c˘a am determinat, pas cu pas, cercurile C 2 , C 3 , ..., C i si

trebuie s a determin˘am cercul C i+1 .Daca punctul P i+1 se aa ın interiorul cercului C i atunci cercul C i +1 este

identic cu C i .Daca punctul P i+1 nu se aaın interiorul cercului C i atunci cercul C i+1 se de-

termin˘a reluınd algoritmul pentru sirul de puncte P 1 , P 2 , ...,P i , P i +1 dar impunˆandcondit ia ca acest cerc s˘a treac a ın mod obligatoriu prin punctul P i+1 (x i+1 , yi+1 ).Putem plasa acest punct pe prima pozit ¸ie ın sirul punctelor si astfel vom impunela ecare pas ca punctul P 1 sa e pe cercul care trebuie determinat!

18.9 Probleme rezolvate18.9.1 Seceta - ONI2005 clasa a IX-a

lect. Ovidiu Domsa

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 476/518

464 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

Gr adinile roditoare ale B˘ar aganului sufer a anual pierderi imense dincauza secetei. C˘aut atorii de ap˘a au gasit n fant ani din care doresc s˘a alimenteze ngradini. Fie G i , F i , i = 1 ,...,n puncte ın plan reprezentˆ and puncte de alimentareale gradinilor si respectiv punctele ın care se a˘ a fant anile. Pentru ecare punctse dau coordonatele ıntregi ( x, y) ın plan.

Pentru a economisi materiale, leg˘ atura dintre o gr˘ adin a si o fant an a se rea-lizeaza printr-o conduct˘ a ın linie dreapt˘ a. Fiecare f ant an a alimenteaz˘a o singur agradin a. Consiliul Judet¸ean Galat¸i pl ateste investit ¸ia cu condit ia ca lungimea to-tal a a conductelor s˘a e minim a.

Fiecare unitate de conduct˘ a cost a 100 lei noi (RON).

Cerint ¸aSa se determine m, costul minim total al conductelor ce leag˘ a ecare gr adin a

cu exact o f ant an a.

Date de intrareFisierul de intrare seceta.in va cont ine:

• Pe prima linie se a˘a num arul natural n, reprezentˆand num arul gr adinilorsi al fant anilor.

• Pe urm atoarele n linii se aa perechi de numere ıntregi Gx Gy , separateprintr-un spat ¸iu, reprezentˆ and coordonatele punctelor de alimentare ale gr˘ adinilor.

• Pe urm atoarele n linii se aa perechi de numere ıntregi F x F y , separateprintr-un spat ¸iu, reprezentˆ and coordonatele punctelor fˆ ant anilor.

Date de iesireFisierul de iesire seceta.out va cont ine:m −un num ar natural reprezentˆ and partea ıntreag˘ a a costului minim total

al conductelor.

Restrict ii si precizari

• 1 < n < 13

• 0 ≤Gx,Gy,Fx,Fy ≤200

• Nu exist a trei puncte coliniare, indiferent dac˘ a sunt gr adini sau f ant ani

•Orice linie din sierele de intrare si iesire se termin˘ a prin marcajul de sfˆarsitde linie.

Exempluseceta.in seceta.out Explicat ie3 624 Costul minim este [6.24264 * 100]=6241 4 prin legarea perechilor:3 3 Gradini Fantani

4 7 1 4 2 32 3 3 3 3 12 5 4 7 2 53 1

Timp maxim de execut ¸ie/test: 1 sec sub Windows si 0.5 sec sub Linux.

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 477/518

18.9. PROBLEME REZOLVATE 465

Indicat ¸ii de rezolvare *

Solut ¸ia ocial˘ a, lect. Ovidiu Domsa Num arul mic al punctelor permite generarea tuturor posibilit˘ atilor de a conecta

o gradin a cu o fant an a neconectat˘a la un moment dat.Pentru ecare astfel de combinat ¸ie gasit a se calculeaza suma distant¸elor

(Gi,Fj ), ın linie dreapta, folosind formula distant ¸ei dintre dou˘a puncte ın plan,studiat˘a la geometrie. ( d(A(x, y ), B (z, t ) = (x −z)2 + ( y −t)2).

Acest a solut ie implementat˘ a corect asigur˘a 60 −70 de puncte.Pentru a obt¸ine punctajul maxim se tine cont de urm˘ atoarele aspecte:1. Se construieste ın prealabil matricea distant ¸elor d(i, j ) cu semnicat ia

distant¸ei dintre gr˘adina i si fant ana j . Aceasta va reduce timpul de calcul lavariantele cu peste 9 perechi.

2. Pentru a elimina cazuri care nu pot constitui solut ¸ii optime se folosesteproprietatea patrulaterului c˘ a suma a doua laturi opuse (condit ¸ie care asigur˘aunicitatea conect˘ arii unei singure f ant ani la o singura gradin a) este mai mic a decatsuma diagonalelor. De aceea nu se vor lua ın considerare acele segmente care seintersecteaz˘a. Condit ia de intersect¸ie a dou a segmente care au capetele ın punctelede coordonate A(a1, a2), B (b1, b2), C (c1, c2), D(d1, d2) este ca lu and segmentulAB , punctele C si D sa se ae de aceeasi parte a segmentului AB si respectivpentru segmentul CD , punctele A si B s a se ae de aceeasi parte (se ınlocuiesteın ecuat¸ia dreptei ce trece prin dou˘ a puncte, studiat˘ a ın clasa a 9-a).

Observat¸ie: Pentru cei interesat ¸i, problema are solut ¸ie si la un nivel superior,folosind algoritmul de determinare a unui ux maxim de cost minim.

Variant˘a cu determinarea intesect ¸iei segmentelor.

import java.io.*; // cu determinarea intesectiei segmentelorclass Seceta1 // Java este "mai incet" decat Pascal si C/C++ // test 9 ==> 2.23 sec

static int nv=0;static int n;static int[] xg, yg, xf, yf, t, c;static int[] a; // permutare: a[i]=fantana asociata gradinii istatic double costMin=200*1.42*12*100;static double[][] d;static PrintWriter out;static StreamTokenizer st;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();citire();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 478/518

466 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

rezolvare();afisare();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

static void citire() throws IOException

int k;st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));st.nextToken(); n=(int)st.nval;

xg=new int[n+1];yg=new int[n+1];xf=new int[n+1];yf=new int[n+1];a=new int[n+1];d=new double[n+1][n+1];

for(k=1;k<=n;k++)

st.nextToken(); xg[k]=(int)st.nval;st.nextToken(); yg[k]=(int)st.nval;

for(k=1;k<=n;k++)

st.nextToken(); xf[k]=(int)st.nval;st.nextToken(); yf[k]=(int)st.nval;

static void rezolvare() throws IOException

int i,j;int s;for(i=1;i<=n;i++) // gradina i

for(j=1;j<=n;j++) // fantana j

s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);d[i][j]=Math.sqrt(s);

f(1); // generez permutari

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 479/518

18.9. PROBLEME REZOLVATE 467

static void f(int k)

boolean ok;int i,j;for(i=1;i<=n;i++)

ok=true; // k=1 ==> nu am in stanga ... for nu se executa !for(j=1;j<k;j++) if(i==a[j]) ok=false; break;if(!ok) continue;for(j=1;j<k;j++)

if(seIntersecteaza(xg[k],yg[k],xf[i], yf[i],xg[j],yg[j],xf[a[j]],yf[a[j]]))

ok=false;break;

if(!ok) continue;a[k]=i;if(k<n) f(k+1); else verificCostul();

static void verificCostul()

int i;double s=0;

for(i=1;i<=n;i++) s=s+d[i][a[i]];if(s<costMin) costMin=s;

// de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)static int s(int xp,int yp,int xa,int ya,int xb,int yb)

double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;if(s<-0.001) return -1; // in zona "negativa"

else if(s>0.001) return 1; // in zona "pozitiva"else return 0; // pe dreapta suport

// testeaza daca segmentul[P1,P1] se intersecteaza cu [P3,P4]static boolean seIntersecteaza(int x1, int y1, int x2, int y2,

int x3, int y3, int x4, int y4)

double x,y;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 480/518

468 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

if((x1==x2)&&(x3==x4)) // ambele segmente verticaleif(x1!=x3) return false;else if(intre(y1,y3,y4)||intre(y2,y3,y4)) return true;

else return false;

if((y1==y2)&&(y3==y4)) // ambele segmente orizontaleif(y1!=y3) return false;else if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;

else return false;

if((y2-y1)*(x4-x3)==(y4-y3)*(x2-x1)) // au aceeasi panta (oblica)if((x2-x1)*(y3-y1)==(y2-y1)*(x3-x1)) // au aceeasi dreapta suport

if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;else return false;

else return false;// nu au aceeasi dreapta suportelse // nu au aceeasi panta (macar unul este oblic)

x=(double)((x4-x3)*(x2-x1)*(y3-y1)-x3*(y4-y3)*(x2-x1)+x1*(y2-y1)*(x4-x3))/

((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));if(x2!=x1) y=y1+(y2-y1)*(x-x1)/(x2-x1); else y=y3+(y4-y3)*(x-x3)/(x4-x3);if(intre(x,x1,x2)&&intre(y,y1,y2)&&intre(x,x3,x4)&&intre(y,y3,y4))

return true; else return false;

static boolean intre(int c, int a, int b) // c este in [a,b] ?

int aux;if(a>b) aux=a; a=b; b=aux;if((a<=c)&&(c<=b)) return true; else return false;

static boolean intre(double c, int a, int b) // c este in [a,b] ?

int aux;if(a>b) aux=a; a=b; b=aux;if((a<=c)&&(c<=b)) return true; else return false;

static void afisare() throws IOException

int k;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 481/518

18.9. PROBLEME REZOLVATE 469

out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));out.println((int)(costMin*100));out.close();

Variant˘a cu cu determinarea pozitiei punctelor in semiplane si mesaje pentrudepanare.

import java.io.*; // cu determinarea pozitiei punctelor in semiplaneclass Seceta2 // cu mesaje pentru depanare !

static int nv=0;static int n;static int[] xg, yg, xf, yf, t, c;static int[] a; // permutare: a[i]=fantana asociata gradinii istatic double costMin=200*1.42*12*100;static double[][] d;static PrintWriter out;static StreamTokenizer st;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();citire();rezolvare();

afisare();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

static void citire() throws IOException

int k;st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));st.nextToken(); n=(int)st.nval;xg=new int[n+1];yg=new int[n+1];xf=new int[n+1];yf=new int[n+1];a=new int[n+1];d=new double[n+1][n+1];

for(k=1;k<=n;k++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 482/518

470 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

st.nextToken(); xg[k]=(int)st.nval;st.nextToken(); yg[k]=(int)st.nval;

for(k=1;k<=n;k++)

st.nextToken(); xf[k]=(int)st.nval;st.nextToken(); yf[k]=(int)st.nval;

static void rezolvare() throws IOException

int i,j;int s;for(i=1;i<=n;i++) // gradina ifor(j=1;j<=n;j++) // fantana j

s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);d[i][j]=Math.sqrt(s);

f(1); // generez permutari

static void f(int k)

boolean ok;int i,j;for(i=1;i<=n;i++)

ok=true; // k=1 ==> nu am in stanga ... for nu se executa !for(j=1;j<k;j++) if(i==a[j]) ok=false; break;if(!ok) continue;

for(j=1;j<k;j++)if((s(xg[k],yg[k],xg[j],yg[j],xf[a[j]],yf[a[j]])*

s(xf[i],yf[i],xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&(s(xg[j], yg[j], xg[k],yg[k],xf[i],yf[i])*

s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i],yf[i])<0))

afisv(k-1);// pe pozitia k(gradina) vreau sa pun i(fantana)System.out.print(i+" ");// pe pozitia j(gradina) e pus a[j](fantana)System.out.print(k+""+i+" "+j+""+a[j]);System.out.print(" ("+xg[k]+","+yg[k]+") "+" ("+xf[i]+","+yf[i]+") ");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 483/518

18.9. PROBLEME REZOLVATE 471

System.out.println(" ("+xg[j]+","+yg[j]+") "+" ("+xf[a[j]]+","+yf[a[j]]+") ");

ok=false;break;

if(!ok) continue;

a[k]=i;if(k<n) f(k+1); else verificCostul();

static void verificCostul()

int i;double s=0;for(i=1;i<=n;i++) s=s+d[i][a[i]];if(s<costMin) costMin=s;afisv(n); System.out.println(" "+s+" "+costMin+" "+(++nv));

static void afisv(int nn)

int i;for(i=1;i<=nn;i++) System.out.print(a[i]);

// de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)static int s(int xp,int yp,int xa,int ya,int xb,int yb)

double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;if(s<-0.001) return -1; // in zona "negativa"else if(s>0.001) return 1; // in zona "pozitiva"

else return 0; // pe dreapta suport

static void afisare() throws IOException

int k;out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));out.println((int)(costMin*100));out.close();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 484/518

472 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

Variant˘a cu cu determinarea pozitiei punctelor in semiplane, f˘ ar a mesajepentru depanare.

import java.io.*; // cu determinarea pozitiei punctelor in semiplaneclass Seceta3 // Java este "mai incet" decat Pascal si C/C++ // test 9 ==> 2.18 sec

static int n;static int[] xg, yg, xf, yf, t, c;static int[] a; // permutare: a[i]=fantana asociata gradinii istatic double costMin=200*1.42*12*100;static double[][] d;static PrintWriter out;static StreamTokenizer st;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();citire();rezolvare();afisare();t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

static void citire() throws IOException

int k;st=new StreamTokenizer(new BufferedReader(

new FileReader("seceta.in")));st.nextToken(); n=(int)st.nval;xg=new int[n+1];yg=new int[n+1];xf=new int[n+1];yf=new int[n+1];a=new int[n+1];d=new double[n+1][n+1];

for(k=1;k<=n;k++)

st.nextToken(); xg[k]=(int)st.nval;st.nextToken(); yg[k]=(int)st.nval;

for(k=1;k<=n;k++)

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 485/518

18.9. PROBLEME REZOLVATE 473

st.nextToken(); xf[k]=(int)st.nval;st.nextToken(); yf[k]=(int)st.nval;

static void rezolvare() throws IOException

int i,j;int s;for(i=1;i<=n;i++) // gradina ifor(j=1;j<=n;j++) // fantana j

s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);d[i][j]=Math.sqrt(s);

f(1); // generez permutari

static void f(int k)

boolean ok;int i,j;for(i=1;i<=n;i++)

ok=true; // k=1 ==> nu am in stanga ... for nu se executa !

for(j=1;j<k;j++) if(i==a[j]) ok=false; break;if(!ok) continue;for(j=1;j<k;j++)if((s(xg[k], yg[k], xg[j],yg[j],xf[a[j]],yf[a[j]])*

s(xf[i], yf[i], xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&(s(xg[j], yg[j], xg[k],yg[k],xf[i], yf[i])*

s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i], yf[i])<0))

ok=false;break;

if(!ok) continue;a[k]=i;if(k<n) f(k+1); else verificCostul();

static void verificCostul()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 486/518

474 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

int i;double s=0;for(i=1;i<=n;i++) s=s+d[i][a[i]];if(s<costMin) costMin=s;

//de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)static int s(int xp,int yp,int xa,int ya,int xb,int yb)

double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;if(s<-0.001) return -1; // in zona "negativa"else if(s>0.001) return 1; // in zona "pozitiva"

else return 0; // pe dreapta suport

static void afisare() throws IOException

int k;out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));out.println((int)(costMin*100));out.close();

Varianta 4:

import java.io.*; // gresit (!) dar ... obtine 100p ... !!!class Seceta4 // test 9 : 2.18 sec --> 0.04 sec

static int n;static int[] xg, yg, xf, yf, t, c;static int[] a; // permutare: a[i]=fantana asociata gradinii istatic double costMin=200*1.42*12*100;static double[][] d;static boolean[] epus=new boolean[13];

static PrintWriter out;static StreamTokenizer st;

public static void main(String[] args) throws IOException

long t1,t2;t1=System.currentTimeMillis();

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 487/518

18.9. PROBLEME REZOLVATE 475

citire();rezolvare();afisare();

t2=System.currentTimeMillis();System.out.println("Timp = "+(t2-t1)+" ms");

// main(...)

static void citire() throws IOException

int k;st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));st.nextToken(); n=(int)st.nval;xg=new int[n+1];yg=new int[n+1];xf=new int[n+1];yf=new int[n+1];a=new int[n+1];

d=new double[n+1][n+1];

for(k=1;k<=n;k++)

st.nextToken(); xg[k]=(int)st.nval;st.nextToken(); yg[k]=(int)st.nval;

for(k=1;k<=n;k++)st.nextToken(); xf[k]=(int)st.nval;st.nextToken(); yf[k]=(int)st.nval;

// citire(...)

static void rezolvare() throws IOException

int i,j;int s;for(i=1;i<=n;i++) // gradina i

for(j=1;j<=n;j++) // fantana j

s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);d[i][j]=Math.sqrt(s);

f(1); // generez permutari

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 488/518

476 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

// rezolvare(...)

static void f(int k)

int i,j;boolean seIntersecteaza;for(i=1;i<=n;i++)

if(epus[i]) continue;seIntersecteaza=false;for(j=1;j<=k-1;j++)

if(d[k][i]+d[j][a[j]]>d[j][i]+d[k][a[j]])

seIntersecteaza=true;break;

if(seIntersecteaza) continue;

a[k]=i;

epus[i]=true;if(k<n) f(k+1); else verificCostul();epus[i]=false;

// for i// f(...)

static void verificCostul()

int i;double s=0;for(i=1;i<=n;i++) s=s+d[i][a[i]];if(s<costMin) costMin=s;

// verificCostul(...)

static void afisare() throws IOException

int k;out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));out.println((int)(costMin*100));out.close();

// afisare(...)// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 489/518

18.9. PROBLEME REZOLVATE 477

18.9.2 Antena - ONI2005 clasa a X-a

prof. Osman Ay, Liceul International de Informatic˘ a Bucuresti

In Delta Dun˘arii exist a o zona salbatic a, rupt˘a de bucuriile si necazurilecivilizat iei moderne.

In aceast a zona exist a doar n case, pozit iile acestora ind specicate princoordonatele carteziene de pe hart˘ a.

Postul de radio al ONI 2005 doreste s˘ a emit a pentru tot¸i locuitorii din zon˘asi, prin urmare, va trebui s˘ a instaleze o anten˘a de emisie special a pentru aceasta.

O anten˘a emite unde radio ıntr-o zon˘ a circular a. Centrul zonei coincide cupunctul ın care este pozit ¸ionat˘a antena. Raza zonei este denumit˘ a puterea antenei.Cu cat puterea antenei este mai mare, cu atˆ at antena este mai scump˘ a.

Prin urmare trebuie selectat˘ a o pozitie optim˘a de amplasare a antenei, astfelınc at ecare cas a sa se ae ın interiorul sau pe frontiera zonei circulare ın careemite antena, iar puterea antenei s˘ a e minim a.

Cerint ¸aScrieti un program care s˘ a determine o pozit¸ie optim˘a de amplasare a antenei,

precum si puterea minim˘ a a acesteia.

Datele de intrareFisierul de intrare antena.in cont ine pe prima linie un num˘ ar natural n,

reprezentˆand num arul de case din zon a. Pe urm˘atoarele n linii se aa pozitiilecaselor. Mai exact, pe linia i + 1 se a a dou a numere ıntregi separate printr-unspat iu x y, ce reprezint˘a abscisa si respectiv ordonata casei i. Nu exist a dou a caseın aceeasi locat ¸ie.

Datele de iesireFisierul de iesire antena.out contine pe prima linie dou˘a numere reale sep-

arate printr-un spat ¸iu x y reprezentnd abscisa si ordonata pozit ¸iei optime de am-plasare a antenei.

Pe cea de a doua linie se va scrie un num˘ ar real reprezentˆ and puterea antenei.

Restrict ii si precizari

• 2 < N < 15001

• −15000 < x, y < 15001

•Numerele reale din sierul de iesire trebuie scrise cu trei zecimale cu rotun-

jire.

• La evaluare, se veric˘a dac a diferent a dintre solut ¸ia asat˘a si cea corect˘a(ın valoare absolut˘ a) este < 0.01.

Exemplu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 490/518

478 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

antena.in antena.out Explicat ie7 3.250 2.875 Antena va plasat˘a ın punctul5 0 3.366 de coordonate (3 .250, 2.825) iar2 6 puterea antenei este 3 .3664 52 20 23 65 2

Timp maxim de execut ¸ie/test: 0.3 secunde pentru Windows si 0.1 se-cunde pentru Linux.

import java.io.*; // practic, trebuie sa determinam cele trei puncteclass Antena // prin care trece cercul care le acopera pe toate!!!

static int n;static int[] x,y;static double x0, y0, r0;

public static void main(String[] args) throws IOException

int k;long t1,t2;t1=System.nanoTime();StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("antena.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("antena.out")));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 491/518

18.9. PROBLEME REZOLVATE 479

st.nextToken(); n=(int)st.nval;x=new int[n+1];y=new int[n+1];

for(k=1;k<=n;k++)

st.nextToken(); x[k]=(int)st.nval;st.nextToken(); y[k]=(int)st.nval;

if(n>3)

puncteExtreme();cercDeDiametru(x[1],y[1],x[2],y[2]);for(k=3;k<=n;k++)if(!esteInCerc(k))

cercPrin(x[k],y[k],k-1); // trece prin Pk si acopera 1,2,...,k-1else cercCircumscris(x[1],y[1],x[2],y[2],x[3],y[3]);

// scriere cu 3 zecimale rotunjiteout.print( (double)((int)((x0+0.0005)*1000))/1000+" ");out.println((double)((int)((y0+0.0005)*1000))/1000);out.println((double)((int)((r0+0.0005)*1000))/1000);out.close();t2=System.nanoTime();

System.out.println("Timp = "+((double)(t2-t1))/1000000000);// main(...)

// trece prin (xx,yy) si acopera punctele 1,2,...,kstatic void cercPrin(int xx, int yy, int k)

int j;cercDeDiametru(x[1],y[1],xx,yy); // trece prin P1 si (xx,yy)

for(j=2;j<=k;j++)if(!esteInCerc(j))

cercPrin(xx,yy,x[j],y[j],j-1); // ... acopera 1,2,...,j-1// cercPrin(...)

// trece prin (xx,yy) si (xxx,yyy) si acopera 1,2,3,...,jstatic void cercPrin(int xx,int yy,int xxx,int yyy,int j)

int i;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 492/518

480 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

cercDeDiametru(xx,yy,xxx,yyy);for(i=1;i<=j;i++) // acopera 1,2,...,j

if(!esteInCerc(i))cercCircumscris(xx,yy,xxx,yyy,x[i],y[i]);

// cercPrin(...)

static boolean esteInCerc(int k)

if(d(x[k],y[k],x0,y0)<r0+0.0001) return true; else return false;

static void puncteExtreme()

int k,aux,min,max,kmin,kmax;

// caut cel mai din stanga punct (si mai jos) si-l pun pe pozitia 1// (caut incepand cu pozitia 1)kmin=1; min=x[1];for(k=2;k<=n;k++)

if((x[k]<min)||(x[k]==min)&&(y[k]<y[kmin])) min=x[k]; kmin=k;if(kmin!=1) swap(1,kmin);

// caut cel mai din dreapta (si mai sus) punct si-l pun pe pozitia 2// (caut incepand cu pozitia 2)kmax=2; max=x[2];for(k=3;k<=n;k++)

if((x[k]>max)||(x[k]==max)&&(y[k]>y[kmax])) max=x[k]; kmax=k;if(kmax!=2) swap(2,kmax);

// caut cel mai de jos (si mai la dreapta) punct si-l pun pe pozitia 3// (caut incepand cu pozitia 3)kmin=3; min=y[3];for(k=4;k<=n;k++)

if((y[k]<min)||(y[k]==min)&&(x[k]>x[kmin])) min=y[k]; kmin=k;if(kmin!=3) swap(3,kmin);

// caut cel mai de sus (si mai la stanga) punct si-l pun pe pozitia 4// (caut incepand cu pozitia 4)kmax=4; max=y[4];for(k=5;k<=n;k++)

if((y[k]>max)||(y[k]==max)&&(x[k]<x[kmax])) max=y[k]; kmax=k;if(kmax!=4) swap(4,kmax);

if(d(x[1],y[1],x[2],y[2])<d(x[3],y[3],x[4],y[4])) // puncte mai departate

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 493/518

18.9. PROBLEME REZOLVATE 481

swap(1,3);swap(2,4);

// puncteExtreme()

static void cercCircumscris(int x1,int y1,int x2,int y2,int x3,int y3) // consider ca punctele nu sunt coliniare !

// (x-x0)^2+(y-y0)^2=r^2 ecuatia cercului verificata de punctele P1,P2,P3// 3 ecuatii si 3 necunoscute: x0, y0, r

double a12, a13, b12, b13, c12, c13; // int ==> eroare !!!

a12=2*(x1-x2); b12=2*(y1-y2); c12=x1*x1+y1*y1-x2*x2-y2*y2;a13=2*(x1-x3); b13=2*(y1-y3); c13=x1*x1+y1*y1-x3*x3-y3*y3;

// sistemul devine: a12*x0+b12*y0=c12;// a13*x0+b13*y0=c13;if(a12*b13-a13*b12!=0)

x0=(c12*b13-c13*b12)/(a12*b13-a13*b12);y0=(a12*c13-a13*c12)/(a12*b13-a13*b12);r0=Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));

else // consider cercul de diametru [(minx,maxx),(miny,maxy)] // punctele sunt coliniare !

x0=(max(x1,x2,x3)+min(x1,x2,x3))/2;y0=(max(y1,y2,y3)+min(y1,y2,y3))/2;r0=d(x0,y0,x1,y1)/2;

// cercCircumscris(...)

static void cercDeDiametru(int x1,int y1,int x2,int y2)

x0=((double)x1+x2)/2;y0=((double)y1+y2)/2;r0=d(x1,y1,x2,y2)/2;

// cercDeDiametru(...)

static int min(int a,int b) if(a<b) return a; else return b; static int max(int a,int b) if(a>b) return a; else return b;

static int min(int a,int b,int c) return min(min(a,b),min(a,c)); static int max(int a,int b,int c) return max(min(a,b),max(a,c));

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 494/518

482 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

static double d(int x1, int y1, int x2, int y2)

double dx,dy;dx=x2-x1;dy=y2-y1;return Math.sqrt(dx*dx+dy*dy);

static double d(double x1, double y1, double x2, double y2)

double dx,dy;dx=x2-x1;dy=y2-y1;return Math.sqrt(dx*dx+dy*dy);

//interschimb punctele i si jstatic void swap(int i, int j)

int aux;aux=x[i]; x[i]=x[j]; x[j]=aux;aux=y[i]; y[i]=y[j]; y[j]=aux;

// swap(...)// class

18.9.3 Mosia lui Pacala - OJI2004 clasa a XI-a

P acal a a primit, asa cum eraınvoiala, un petec de teren de pe mosia boierului.Terenul este ımprejmuit complet cu segmente drepte de gard ce se sprijin˘ a laambele capete de cˆate un par zdrav˘ an. La o nou a prinsoare, P˘acal a iese iar ıncastig si primeste dreptul s˘ a str amute niste pari, unul cˆ ate unul, cum i-o voia,astfel ıncˆat s a-si extind˘a suprafat a de teren. Dar ınvoiala prevede c˘ a ecare parpoate mutat ın orice direct ¸ie, dar nu pe o distant ¸ a mai mare dec at o valoaredat a (scris a pe ecare par) si ecare segment de gard, ind cam suubred, poate rotit si prelungit de la un singur cap˘ at, cel alalt r amanand nemiscat.

Cunoscnd pozit¸iile init iale ale parilor si valoarea ınscris˘ a pe ecare par, secere suprafat¸a maxim˘a cu care poate s a-si extind˘a P acal a proprietatea. Se stie c˘ aparii sunt dat¸i ıntr-o ordine oarecare, pozit ¸iile lor init iale sunt date prin numereıntregi de cel mult 3 cifre, distant ¸ele pe care ecare par poate deplasat suntnumere naturale strict pozitive si gura format˘ a de terenul init¸ial este un poligonneconcav.

Date de intrare

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 495/518

18.9. PROBLEME REZOLVATE 483

Fisierul MOSIA.IN cont ¸ine n + 1 linii cu urm˘atoarele valori:n - numarul de parix1 y1 d1 - coordonatele init¸iale si distant ¸a pe care poate mutat parul 1x2 y2 d2 - coordonatele init¸iale si distant ¸a pe care poate mutat parul 2. . .xn yn dn - coordonatele init¸iale si distant ¸a pe care poate mutat parul nDate de iesireIn sierul MOSIA.OUT se scrie un num˘ ar real cu 4 zecimale ce reprezint˘ a

suprafat a maxim˘a cu care se poate m˘ari mosia.Restrict ¸ii si observat ¸ii:3 < N ≤200 numar natural

−1000 < x i , yi < 1000 numere ıntregi0 < d i ≤20 numere ıntregipoligonul neconcav se deneste ca un poligon convex cu unele vˆ arfuri coliniarepozit iile parilor sunt date ıntr-o ordine oarecarepoligonul obt inut dup˘a mutarea parilor poate concavpozit iile nale ale parilor nu sunt ın mod obligatoriu numere naturaleExempluPentru sierul de intrare

4-3 0 23 0 30 6 20 -6 6

se va scrie ın sierul de iesire valoarea 30 .0000Explicat ¸ie: prin mutarea parilor 1 si 2 cu cˆ ate 2 si respectiv 3 unit˘ at i, se

obt ine un teren avˆand suprafat¸a cu 30 de unit˘at i mai mare decˆat terenul init¸ial.Timp limita de executare: 1 sec./test

18.9.4 Partit ¸ie - ONI2006 baraj

Ionica a primit de ziua lui de la tat˘ al sau un joc format din piese de form˘atriunghiular˘ a de dimensiuni diferite si o suprafat ¸u a magnetic˘a pe care acestea pot asezate.

Pe suprafat¸a magnetic˘a este desenat un triunghi dreptunghic cu lungimilecatetelor a, respectiv b si un sistem de coordonate xOy cu originea ın unghiuldrept al triunghiului, semiaxa [ Ox pe cateta de lungime a, respectiv semiaxa [ Oype cateta de lungime b.

La un moment dat Ionic˘ a aseaz a pe tabla magnetic˘ a n piese, pentru care secunosc coordonatele vˆarfurilor lor. Tat˘ al lui Ionica vrea s a verice dac a pe tabl apiesele realizeaz a o partit ie a triunghiului dreptunghic desenat, adic˘ a dac a suntındeplinite condit ¸iile:

• nu exist a piese suprapuse;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 496/518

484 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

•piesele acoper a toat˘a port iunea desenat˘ a (ın form˘a de triunghi dreptunghic);

•nu exist a port iuni din piese ın afara triunghiului desenat.

Cerint ¸aSe cere sa se verice dac a piesele plasate pe tabla magnetic˘ a formeaz a o

partit¸ie a triunghiului desenat pe tabla magnetic˘ a.

Date de intrareFisierul de intrare part.in contine pe prima linie un num˘ ar natural k, reprezen-

t and num arul de seturi de date din sier. Urmeaz˘ a k grupe de linii, c ate o grup apentru ecare set de date. Grupa de linii corespunz˘ atoare unui set este format˘ adintr-o linie cu numerele a, b, n separate ıntre ele prin cˆ ate un spat iu si n linii cucate sase numere ıntregi separate prin spat ¸ii reprezentˆand coordonatele vˆarfurilor(abscis a ordonat˘a) celor n piese, cate o pies a pe o linie.

Date de iesireIn sierul part.out se vor scrie k linii, cate o linie pentru ecare set de date.Pe linia i (i = 1 , 2,...,k ) se va scrie 1 daca triunghiurile din setul de date i formeaz ao partit ie a triunghiului desenat pe tabla magnetic˘ a sau 0 ın caz contrar.

Restrict ii si precizari

• 1 ≤n ≤150

• 1 ≤k ≤10

• a, b sunt numere ıntregi din intervalul [0 , 31000]

• Coordonatele vrfurilor pieselor sunt numere ntregi din intervalul [0, 31000].

Exemplupart.in part.out2 120 10 4 00 5 0 10 10 50 0 10 5 0 50 0 10 0 10 510 0 20 0 10 520 10 20 0 0 10 10 50 0 20 0 20 10

Timp maxim de execut ¸ie: 0.3 secunde/test

Prelucrare ın Java dup˘ a rezolvarea ın C a autorului problemei

import java.io.*;class part

static final int ON_EDGE=0;static final int INSIDE=1;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 497/518

18.9. PROBLEME REZOLVATE 485

20 20

10 10

T4T3T2

T1

T2T1

1010

55

x x

yy

a) b)

Figura 18.2: a) pentru setul 1 de date si b) pentru setul 2 de date

static final int OUTSIDE=2;static final int N_MAX=512;

static int N, A, B;static int[][] X=new int[N_MAX][3];static int[][] Y=new int[N_MAX][3];

static int sgn(int x)

return x>0 ? 1 : (x<0 ? -1 : 0);

static int point_sign (int x1, int y1, int x2, int y2, int _x, int _y)

int a, b, c;a=y2-y1;b=x1-x2;c=y1*x2-x1*y2;return sgn(a*_x+b*_y+c);

static int point_inside (int n, int x, int y)

int i;int[] sgn=new int[3];for(i=0;i<3;i++)

sgn[i]=point_sign(X[n][i],Y[n][i],X[n][(i+1)%3],Y[n][(i+1)%3],x,y);if(sgn[0]*sgn[1]<0 || sgn[0]*sgn[2]<0 || sgn[1]*sgn[2]<0) return OUTSIDE;if(sgn[0]==0 || sgn[1]==0 || sgn[2]==0) return ON_EDGE;return INSIDE;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 498/518

486 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

static boolean segment_intersect(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)

int a1,b1,c1,a2,b2,c2;a1=y2-y1; b1=x1-x2; c1=y1*x2-x1*y2;a2=y4-y3; b2=x3-x4; c2=y3*x4-x3*y4;return sgn(a1*x3+b1*y3+c1)*sgn(a1*x4+b1*y4+c1)<0 &&

sgn(a2*x1+b2*y1+c2)*sgn(a2*x2+b2*y2+c2)<0;

static boolean triangle_intersect (int n1, int n2)

int i,j,x,t1=0,t2=0;for(i=0;i<3;i++)

if((x=point_inside(n2,X[n1][i],Y[n1][i]))==ON_EDGE) t1++;if(x==INSIDE) return true;if((x=point_inside(n1,X[n2][i],Y[n2][i]))==ON_EDGE) t2++;if(x==INSIDE) return true;

if(t1==3 || t2==3) return true;for(i=0;i<3;i++)

for(j=0;j<3;j++)if(segment_intersect(

X[n1][i],Y[n1][i],X[n1][(i+1)%3],Y[n1][(i+1)%3],X[n2][j],Y[n2][j],X[n2][(j+1)%3],Y[n2][(j+1)%3]

)) return true; return false;

static int solve()

int i,j,area=0;for(i=0;i<N;i++)

for(j=0;j<3;j++)if(point_inside(N,X[i][j],Y[i][j])==OUTSIDE) return 0;

area+=Math.abs((X[i][1]*Y[i][2]-X[i][2]*Y[i][1])-(X[i][0]*Y[i][2]-X[i][2]*Y[i][0])+(X[i][0]*Y[i][1]-X[i][1]*Y[i][0]));

if(area!=A*B) return 0;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 499/518

18.9. PROBLEME REZOLVATE 487

for(i=0;i<N;i++)for(j=i+1;j<N;j++)

if(triangle_intersect(i,j)) return 0;

return 1;

public static void main(String[] args) throws IOException

int tests, i, j;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("part.in")));PrintWriter out=new PrintWriter(

new BufferedWriter(new FileWriter("part.out")));

st.nextToken(); tests=(int)st.nval;

for(; tests-->0;)

st.nextToken(); A=(int)st.nval;st.nextToken(); B=(int)st.nval;st.nextToken(); N=(int)st.nval;

for(i=0;i<N;i++)for(j=0;j<3;j++)

st.nextToken(); X[i][j]=(int)st.nval;st.nextToken(); Y[i][j]=(int)st.nval;

X[N][0]=0; Y[N][0]=0;X[N][1]=A; Y[N][1]=0;X[N][2]=0; Y[N][2]=B;out.println(solve());

out.close();

// main(...)// class

18.9.5 Triunghi - ONI2007 cls 9

In comuna Triunghi din Rom ania sunt n t arani codicat¸i prin numerele

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 500/518

488 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

1, 2,...,n . Dup a anul 1990 a ınceput retrocedarea suprafet ¸elor de p amant det inuteınainte de colectivizare. Fiecare t ¸aran are un document prin care dovedeste c˘ a esteproprietar pe o singur˘ a suprafat a de teren de form˘a triunghiular˘ a. Din p acate, doc-umentele dau b˘ataie de cap primarului (care se ocup˘ a de retrocedarea suprafet ¸elorde pamant), pentru c˘ a sunt port¸iuni din suprafet ¸ele de p amant care se reg˘asesc pemai multe documente.

In aceast a comun a exist a o fant an a cu ap a, ind posibil ca ea s a e revendi-cat a de mai mult i t arani. O suprafat ¸ a de p amant este dat˘a prin coordonatele celortrei colt uri, iar f ant ana este considerat˘ a punctiform˘a si dat˘a prin coordonatelepunctului.

Cerint ¸aSa se scrie un program care s˘a determine:a) Codurile t aranilor care au documente cu suprafet ¸e de p amant ce cont in ın

interior sau pe frontier˘ a fant ana.b) Codul t aranului ce det¸ine un document cu suprafat ¸a de teren, care include

toate celelalte suprafet ¸e.

Date de intrareFisierul de intrare triunghi.in are pe prima linie num˘arul n de t arani, pe

urm atoarele n linii cate 6 valori numere ıntregi separate prin cˆ ate un spat¸iu, ın for-matul: x1 y1 x2 y2 x3 y3, ce reprezint˘a coordonatele celor trei colt ¸uri ale suprafet¸eitriunghiulare det ¸inute de un t¸ aran ( x1, x2, x3 abscise, iar y1, y2, y3 ordonate). Pelinia i +1 se a a coordonatele colt¸urilor suprafet ¸ei de teren triunghiulare det ¸inutede t aranul i, i = 1 , 2,...,n . Ultima linie a sierului (linia n + 2) va cont ine coordo-natele f ant anii ın formatul x y, cu un spat iu ıntre ele ( x abscis a, iar y ordonat˘a).

Date de iesireFisierul de iesire triunghi.out va cont ine pe prima linie r˘aspunsul de la

punctul a), adic a: num arul de t arani care ındeplinesc condit ¸ia din cerint¸ a si apoicodurile lor (ın ordine cresc˘ atoare), cu un spat ¸iu ıntre ele. Dac˘ a nu exist a t aranicu condit ia din cerint¸ a, pe prima linie se va scrie cifra 0. Pe linia a doua se va scrieraspunsul de la punctul b), adic a: codul t aranului cu proprietatea cerut˘ a, sau cifra0, dac a nu exist a un astfel de t aran.

Restrict ii si precizari

• 2 ≤n ≤65

• coordonatele colt¸urilor suprafet ¸elor de p amant si ale f ant anii sunt numereıntregi din intervalul [

−3000, 3000]

• cele trei colt uri ale ec arei suprafet¸e de p amant sunt distincte si necoliniare

• nu exist a doi t arani care s a detin a aceeasi suprafat ¸a de p amant

• nu se acord a punctaje part ¸iale.

Exemplu

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 501/518

18.9. PROBLEME REZOLVATE 489

secv.in secv.out3 2 1 210 0 0 10 10 10 20 100 100 0 -100 00 0 10 0 0 1010 5

Explicat ¸ie:La punctul a), sunt doi t arani care det¸in suprafet¸e de p amant ce au ın interior

sau pe frontier˘a fant ana, cu codurile 1 si 2.La punctul b), t aranul cu codul 2 det¸ine o suprafat¸ a de teren care include,

suprafet ele de p amant det inute de ceilalt¸i t arani (cu codurile 1 si 3).

Timp maxim de execut ¸ie/test: 0.1 secunde

Indicat ¸ii de rezolvare - descriere solut ¸ie

Descrierea solut ¸iei (Prof. Doru Popescu Anastasiu)Not am cu T 1 , T 2 ,...,T n triunghiurile corespunz˘ atoare suprafet¸elor si cu I

punctul unde se g˘aseste f ant ana.

T i = Ai B i C i , i = 1 , 2,...,n.

a)nr = 0Pentru i = 1 ,...,n vericam dac a I este interior sau pe frontiera lui T i , ın caz

armativ nr = nr + 1 si sol[nr ] = i. As am nr si vectorul sol .Pentru a verica dac˘ a I este interior sau pe frontiera unui triunghi T i este

sucient s a vericam dac a:

aria (Ai B i C i ) = aria (IA i B i ) + aria (IA i C i ) + aria (IB i C i )

O alt a variant˘a ar sa folosim pozitia unui punct fat ¸ a de o dreapt˘a.b)Daca exist a un asemenea triunghi atunci el este de arie maxim˘ a. Astfel de-

termin˘am triunghiul p de arie maxim˘a. Pentru acest triunghi veric˘ am dac a toatecelelalte n −1 triunghiuri sunt interioare sau pe frontiera lui T p (adic a dac a autoate v arfurile ın interiorul sau pe frontiera lui T p). In caz armativ se aseaz˘ a p,altfel 0.

Codul sursa

import java.io.*;class Pereti

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 502/518

490 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

static int n,x0,y0;static int smax=-1,imax=-1,nr=0;static int[] x1=new int[66];static int[] y1=new int[66];static int[] x2=new int[66];static int[] y2=new int[66];static int[] x3=new int[66];static int[] y3=new int[66];static int[] sol=new int[66];

public static void main(String[] args) throws IOException

int i,j,s,s1,s2,s3;boolean ok;

StreamTokenizer st=new StreamTokenizer(new BufferedReader(new FileReader("14-triunghi.in")));

PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("triunghi.out")));

st.nextToken(); n=(int)st.nval;for(i=1;i<=n;i++)

st.nextToken(); x1[i]=(int)st.nval;st.nextToken(); y1[i]=(int)st.nval;st.nextToken(); x2[i]=(int)st.nval;st.nextToken(); y2[i]=(int)st.nval;

st.nextToken(); x3[i]=(int)st.nval;st.nextToken(); y3[i]=(int)st.nval;st.nextToken(); x0=(int)st.nval;st.nextToken(); y0=(int)st.nval;for(i=1;i<=n;i++)

s=aria(x1[i],y1[i],x2[i],y2[i],x3[i],y3[i]);if(s>smax) smax=s; imax=i;s1=aria(x1[i],y1[i],x2[i],y2[i],x0,y0);s2=aria(x2[i],y2[i],x3[i],y3[i],x0,y0);s3=aria(x1[i],y1[i],x3[i],y3[i],x0,y0);if(s==s1+s2+s3) nr++; sol[nr]=i;//System.out.println("i = "+i+" --> "+s+" "+s1+" "+s2+" "+s3);

if(nr>0)

out.print(nr+" ");

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 503/518

18.9. PROBLEME REZOLVATE 491

for(i=1;i<=nr;i++)if(i!=nr) out.print(sol[i]+" "); else out.println(sol[i]);

else out.println(0);

//System.out.println("imax = "+imax);ok=true;for(i=1;i<=n;i++)

if(i==imax) continue;

s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x1[i],y1[i]);s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x1[i],y1[i]);s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x1[i],y1[i]);if(smax!=s1+s2+s3) ok=false; break;

s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x2[i],y2[i]);s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x2[i],y2[i]);s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x2[i],y2[i]);if(smax!=s1+s2+s3) ok=false; break;

s1=aria(x1[imax],y1[imax],x2[imax],y2[imax],x3[i],y3[i]);s2=aria(x2[imax],y2[imax],x3[imax],y3[imax],x3[i],y3[i]);s3=aria(x1[imax],y1[imax],x3[imax],y3[imax],x3[i],y3[i]);if(smax!=s1+s2+s3) ok=false; break;

if(ok) out.println(imax); else out.println(0);out.close();// main(...)

static int aria(int x1, int y1, int x2, int y2, int x3, int y3) // dubla ...

int s=x1*y2+x2*y3+x3*y1-y1*x2-y2*x3-y3*x1;if(s<0) s=-s;return s;

// class

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 504/518

492 CAPITOLUL 18. GEOMETRIE COMPUTATIONAL ˘ A

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 505/518

Capitolul 19

Teoria jocurilor

19.1 Jocul NIM

19.1.1 Prezentare generala

19.1.2 Exemple

493

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 506/518

494 CAPITOLUL 19. TEORIA JOCURILOR

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 507/518

Capitolul 20

Alt i algoritmi

20.1 Secvent ¸a de suma maxima

20.1.1 Prezentare generala

20.1.2 Exemple

20.2 Algoritmul Belmann-Ford

Pentru grafuri cu costuri negative (dar fara cicluri negative!) se poate folosialgoritmul Bellman-Ford.

20.2.1 Algoritmul Belmann-Ford pentru grafuri neorientate// drum scurt in graf neorientat cu costuri negative (dar fara ciclu negativ!)// Algoritm: 1. init// 2. repeta de n-1 ori// pentru fiecare arc (u,v)// relax(u,v)// 3. OK=true

495

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 508/518

496 CAPITOLUL 20. ALTI ALGORITMI

// 4. pentru fiecare muchie (u,v)// daca d[v]>d[u]+w[u][v]// OK=false// 5. return OK

import java.io.*;class BellmanFordstatic final int oo=0x7fffffff; // infinitstatic int n,m; // varfuri, muchii

static int[][] w; // matricea costurilorstatic int[] d; // d[u]=dist(nods,u)static int[] p; // p[u]=predecesorul nodului u

public static void main(String[] args) throws IOException

int i,j,k;int nods=1, cost; // nod sursa, costul arculuiint u,v;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("BellmanFordNeorientat.in")));

st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

w=new int[n+1][n+1];d=new int[n+1];p=new int[n+1];

for(i=1;i<=n;i++)for(j=1;j<=n;j++)

w[i][j]=oo;// initializare !

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[i][j]=cost;w[j][i]=cost; // numai pentru graf neorientat

init(nods);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 509/518

20.2. ALGORITMUL BELMANN-FORD 497

for(k=1;k<=n-1;k++) // de n-1 ori !!!for(u=1;u<n;u++) // vectorii muchiilor erau mai buni !

for(v=u+1;v<=n;v++) // lista de adiacenta era mai buna !if(w[u][v]<oo) // (u,v)=muchie si u<v

relax(u,v);

boolean cicluNegativ=false;for(u=1;u<n;u++)

for(v=u+1;v<=n;v++)if(w[u][v]<oo) // (u,v)=muchie

if(d[u]<oo) // atentie !!! oo+ceva=???if(d[v]>d[u]+w[u][v])

cicluNegativ=true;break;

if(!cicluNegativ)for(k=1;k<=n;k++)

System.out.print(nods+"-->"+k+" dist="+d[k]+" drum: ");drum(k);System.out.println();

//main

static void init(int s)

int u;for(u=1;u<=n;u++) d[u]=oo; p[u]=-1; d[s]=0;

// init(...)

static void relax(int u,int v) // (u,v)=arc(u-->v)

if(d[u]<oo) // oo+ceva ==> ???if(d[u]+w[u][v]<d[v])

d[v]=d[u]+w[u][v];p[v]=u;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 510/518

498 CAPITOLUL 20. ALTI ALGORITMI

static void drum(int k) // s --> ... --> k

if(p[k]!=-1) drum(p[k]);System.out.print(k+" ");

static void afisv(int[] x)

int i;for(i=1;i<=n;i++) System.out.print(x[i]+" ");System.out.println();

//class

/*6 71 2 -3 1-->1 dist=0 drum: 11 3 1 1-->2 dist=-3 drum: 1 22 3 2 1-->3 dist=-1 drum: 1 2 33 4 1 1-->4 dist=0 drum: 1 2 3 44 5 1 1-->5 dist=1 drum: 1 2 3 4 55 6 -3 1-->6 dist=-2 drum: 1 2 3 4 5 64 6 2*/

20.2.2 Alg Belmann-Ford pentru grafuri orientate// drumuri scurte in graf orientat cu costuri negative (dar fara ciclu negativ!)// Dijkstra nu functioneaza daca apar costuri negative !// Algoritm: 1. init// 2. repeta de n-1 ori// pentru fiecare arc (u,v)// relax(u,v)// 3. OK=true// 4. pentru fiecare arc (u,v)// daca d[v]>d[u]+w[u][v]// OK=false// 5. return OK

import java.io.*;class BellmanFord

static final int oo=0x7fffffff;static int n,m; // varfuri, muchii

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 511/518

20.2. ALGORITMUL BELMANN-FORD 499

static int[][] w; // matricea costurilorstatic int[] d; // d[u]=dist(nods,u)static int[] p; // p[u]=predecesorul nodului u

public static void main(String[] args) throws IOException

int i,j,k;int nods=1, cost; // nod sursa, costul arculuiint u,v;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("BellmanFordNeorientat.in")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

w=new int[n+1][n+1];d=new int[n+1];p=new int[n+1];for(i=1;i<=n;i++) for(j=1;j<=n;j++) w[i][j]=oo; // initializare !for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[i][j]=cost;

init(nods);for(k=1;k<=n-1;k++) // de n-1 ori !!!for(u=1;u<=n;u++) // vectorii arcelor erau mai buni !

for(v=1;v<=n;v++) // lista de adiacenta era mai buna !if(w[u][v]<oo) // (u,v)=arc

relax(u,v);

boolean cicluNegativ=false;for(u=1;u<=n;u++)

for(v=1;v<=n;v++)if(w[u][v]<oo) // (u,v)=arc

if(d[u]<oo) // atentie !!! oo+ceva=???if(d[v]>d[u]+w[u][v])

cicluNegativ=true;break;

System.out.println(cicluNegativ);

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 512/518

500 CAPITOLUL 20. ALTI ALGORITMI

if(!cicluNegativ)for(k=1;k<=n;k++)

System.out.print(nods+"-->"+k+" dist="+d[k]+" drum: ");if(d[k]<oo) drum(k); else System.out.print("Nu exista drum!");System.out.println();

//main

static void init(int s)

int u;for(u=1;u<=n;u++) d[u]=oo; p[u]=-1; d[s]=0;

// init()

static void relax(int u,int v) // (u,v)=arc(u-->v)

if(d[u]<oo) // oo+ceva ==> ???if(d[u]+w[u][v]<d[v])

d[v]=d[u]+w[u][v];p[v]=u;

// relax(...)

static void drum(int k) // s --> ... --> kif(p[k]!=-1) drum(p[k]);System.out.print(k+" ");

// drum(...)

static void afisv(int[] x)

int i;for(i=1;i<=n;i++) System.out.print(x[i]+" ");System.out.println();

//class

/*6 8 false1 2 -3 1-->1 dist=0 drum: 11 3 1 1-->2 dist=-4 drum: 1 3 2

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 513/518

20.2. ALGORITMUL BELMANN-FORD 501

2 3 6 1-->3 dist=1 drum: 1 33 4 1 1-->4 dist=2 drum: 1 3 45 4 1 1-->5 dist=2147483647 drum: Nu exista drum!5 6 -3 1-->6 dist=4 drum: 1 3 4 64 6 23 2 -5*/

20.2.3 Alg Belmann-Ford pentru grafuri orientate aciclice// Cele mai scurte drumuri in digraf (graf orientat ACICLIC)// Dijkstra nu functioneaza daca apar costuri negative !// Algoritm: 1. sortare topologica O(n+m)// 2. init(G,w,s)// 3. pentru toate nodurile u in ordine topologica// pentru toate nodurile v adiacente lui u// relax(u,v)// OBS: O(n+m)

import java.io.*;class BellmanFordDAG

static final int oo=0x7fffffff;static final int WHITE=0, BLACK=1; // color[u]=BLACK ==> u in listastatic int n,m,t,pozl; // varfuri, muchii, time, pozitie in listastatic int[] color; // culoare

static int[] lista; // listastatic int[] gi; // grad interiorstatic int[][] w; // matricea costurilorstatic int[] d; // d[u]=dist(nods,u)static int[] p; // p[u]=predecesorul nodului u

public static void main(String[] args) throws IOException

int i,j,k;int nods=1, cost; // nod sursa, costul arculuiint u,v;StreamTokenizer st=new StreamTokenizer(

new BufferedReader(new FileReader("BellmanFordDAG.in")));st.nextToken(); n=(int)st.nval;st.nextToken(); m=(int)st.nval;

w=new int[n+1][n+1];color=new int[n+1];

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 514/518

502 CAPITOLUL 20. ALTI ALGORITMI

lista=new int[n+1];gi=new int[n+1];d=new int[n+1];p=new int[n+1];

for(i=1;i<=n;i++)for(j=1;j<=n;j++) w[i][j]=oo; // initializare !

for(k=1;k<=m;k++)

st.nextToken(); i=(int)st.nval;st.nextToken(); j=(int)st.nval;st.nextToken(); cost=(int)st.nval;w[i][j]=cost;gi[j]++;

topoSort();System.out.print("Lista : "); afisv(lista);

init(nods);for(i=1;i<=n;i++)

u=lista[i];for(v=1;v<=n;v++)

if(w[u][v]<oo) // lista de adiacenta era mai buna !

relax(u,v);

System.out.print("Distante : ");afisv(d);

for(k=1;k<=n;k++)

if(d[k]<oo) System.out.print(k+" : "+d[k]+" ... ");else System.out.print(k+": oo ... ");drum(k);System.out.println();

//main

static void init(int s)

int u;

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 515/518

20.2. ALGORITMUL BELMANN-FORD 503

for(u=1;u<=n;u++)

d[u]=oo;p[u]=-1;

d[s]=0;

// init(...)

static void relax(int u,int v) // (u,v)=arc(u-->v)

if(d[u]<oo) // oo+ceva ==> ???if(d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v]; p[v]=u;

// relax(...)

static void drum(int k) // s --> ... --> k

if(p[k]!=-1) drum(p[k]);if(d[k]<oo) System.out.print(k+" ");

static void topoSort()

int u,i,k,pozl;for(i=1;i<=n;i++) // oricum era initializat implicit, dar ... !!!

color[i]=WHITE;pozl=1;

for(k=1;k<=n;k++) // pun cate un nod in listau=nodgi0();color[u]=BLACK; micsorezGrade(u);lista[pozl++]=u;

// topoSort()

static int nodgi0() // nod cu gradul interior zero

int v,nod=-1;for(v=1;v<=n;v++) // coada cu prioritati (heap) este mai buna !!!

if(color[v]==WHITE)if(gi[v]==0) nod=v; break;

return nod;// nodgi0()

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 516/518

504 CAPITOLUL 20. ALTI ALGORITMI

static void micsorezGrade(int u)

int v;for(v=1;v<=n;v++) // lista de adiacenta este mai buna !!!if(color[v]==WHITE)

if(w[u][v]<oo) gi[v]--;// micsorezGrade(...)

static void afisv(int[] x)

int i;for(i=1;i<=n;i++)if(x[i]<oo) System.out.print(x[i]+" "); else System.out.print("oo ");System.out.println();

// afisv(...)//class

/*6 7 Lista : 1 3 2 5 4 61 2 -3 Distante : 0 -4 1 2 oo 41 3 1 1 : 0 ... 13 4 1 2 : -4 ... 1 3 25 4 1 3 : 1 ... 1 35 6 -3 4 : 2 ... 1 3 44 6 2 5: oo ...3 2 -5 6 : 4 ... 1 3 4 6

*/

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 517/518

Bibliograe

[1] Aho, A.; Hopcroft, J.; Ullman, J.D.; Data strutures and algorithms, AddisonWesley, 1983

[2] Aho, A.; Hopcroft, J.; Ullman, J.D.; The Random Access Machine, 1974[3] Andonie R., G arbacea I.; Algoritmi fundamentali, o perspectiv˘ a C++, Ed.

Libris, 1995

[4] Apostol C., Rosca I. Gh., Rosca V., Ghilic-Micu B., Introducere ın progra-mare. Teorie si aplicatii, Editura ... Bucuresti, 1993

[5] Atanasiu, A.; Concursuri de informatic˘ a. Editura Petrion, 1995

[6] Atanasiu, A.; Ordinul de complexitate al unui algoritm. Gazeta de Informatic˘ anr.1/1993

[7] - Bell D., Perr M.: Java for Students, Second Edition, Prentice Hall, 1999

[8] Calude C.; Teoria algoritmilor, Ed. Universit˘ atii Bucuresti, 1987

[9] Cerchez, E.; Informatic˘a - Culegere de probleme pentru liceu, Ed. Polirom,Iasi, 2002

[10] Cerchez, E., Serban, M.; Informatic˘ a - manual pentru clasa a X-a., Ed.Polirom, Iasi, 2000

[11] Cori, R.; Levy, J.J.; Algorithmes et Programmation, Polycopie, version 1.6;http://w3.edu.polytechnique.fr/informatique/

[12] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Introducere ın Algoritmi, EdAgora, 2000

[13] Cormen, T.H., Leiserson C.E., Rivest, R.L.; Pseudo-Code Language, 1994[14] Cristea, V.; Giumale, C.; Kalisz, E.; Paunoiu, Al.; Limbajul C standard, Ed.

Teora, Bucuresti, 1992

[15] Erickson J.; Combinatorial Algorithms; http://www.uiuc.edu/~jeffe/

505

8/6/2019 48967575 Cursuri Carte Algoritmi Si Exemple Programe

http://slidepdf.com/reader/full/48967575-cursuri-carte-algoritmi-si-exemple-programe 518/518

506 BIBLIOGRAFIE

[16] Flanagan, D.; Java in a Nutshell, O’Reilly, 1997.

[17] Flanagan, D.; Java examples in a Nutshell, O’Reilly, 1997.

[18] Giumale, C.; Introducere ın Analiza Algoritmilor, Ed.Polirom, 2004

[19] Giumale C., Negreanu L., C˘alinoiu S.; Proiectarea si analiza algoritmilor.Algoritmi de sortare, Ed. All, 1997

[20] Gosling, J.; Joy, B.; Steele, G.; The Java Language Specication, AddisonWesley, 1996.

[21] Knuth, D.E.; Arta program˘ arii calculatoarelor, vol. 1: Algoritmi fundamentali,Ed. Teora, 1999.

[22] Knuth, D.E.; Arta programarii calculatoarelor, vol. 2: Algoritmi seminumerici,Ed. Teora, 2000.

[23] Knuth, D.E.; Arta programarii calculatoarelor, vol. 3: Sortare si c˘ autare, Ed.