skripta iz dizajna i analize algoritama (radna...

99
Skripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi´ c Prirodno-matematiˇ cki fakultet, Univerzitet u Niˇ su Departman za raˇ cunarske nauke e-mail: [email protected] Niˇ s, Februar 2019.

Upload: others

Post on 25-Jan-2020

82 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Skripta iz Dizajna i analizealgoritama (radna verzija)

Nikola MilosavljevicPrirodno-matematicki fakultet, Univerzitet u Nisu

Departman za racunarske naukee-mail: [email protected]

Nis, Februar 2019.

Page 2: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Sadrzaj

0 Uvod 20.1 Asimtotske notacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2 Model racunanja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30.3 Poznati identiteti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1 Osnovne tehnike 51.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Algoritmi teorije brojeva 222.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3 Podeli pa vladaj 323.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

4 Grafovski algoritmi I (Obilazak grafova) 454.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

5 Grafovski algoritmi II (Tezinski grafovi) 565.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

6 Greedy algoritmi 696.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

7 Dinamicko programiranje 787.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 797.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

8 Backtracking 898.1 Teorija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 898.2 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 928.3 Resenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

1

Page 3: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 0

Uvod

0.1 Asimtotske notacije

Za domen svake od funkcija iz definicija se podrazumeva skup N0 = 0, 1, 2, . . ..

Definicija 0.1 Za datu funkciju g(n), O(g(n)) (veliko ”O” od g(n)) predstavlja skup funkcija f(n)za koje postoje pozitivne konstante c i n0 tako da vazi 0 ≤ f(n) ≤ cg(n), za sve n ≥ n0.

O-notaciju koristimo kada zelimo da odredimo asimptotsku gornju granicu neke funkcije f .Npr. f(n) = 100n+ 42 ∈ O(n2) jer funkcija 100n+ 42 ”sporije raste” od od funkcije n2.

Definicija 0.2 Za datu funkciju g(n), Ω(g(n)) (veliko Omega od g(n)) predstavlja skup funkcijaf(n) za koje postoje pozitivne konstante c i n0 tako da vazi 0 ≤ cg(n) ≤ f(n), za sve n ≥ n0.

Ω-notaciju koristimo kada zelimo da odredimo asimptotsku donju granicu neke funkcije f .Npr. f(n) = 100n+ 42 ∈ Ω(

√n) jer funkcija 100n+ 42 ”brze raste” od funkcije

√n.

Definicija 0.3 Za datu funkciju g(n), Θ(g(n)) (Teta od g(n)) predstavlja skup funkcija f(n) zakoje postoje pozitivne konstante c1, c2 i n0 tako da vazi 0 ≤ c1g(n) ≤ f(n) ≤ c2g(n), za sve n ≥ n0.

Θ-notacija najbolje odreduje funkciju, jer vazi

f(n) ∈ Θ(g(n))⇔ f(n) ∈ O(g(n)) ∧ f(n) ∈ Ω(g(n)).

Granice za funkciju kod O i Ω oznaka mogu biti neprecizne1 dok Θ oznaka daje tacan red velicinefunkcije - npr. 100n+ 42 ∈ Θ(n).2

U literaturi se cesto umesto izraza oblika ”f(n) ∈ Θ(g(n))” (analogno za O i Ω) koristi nebas korektan izraz f(n) = Θ(g(n)) koji ima svoje prednosti, pre svega jer je prakticnije (i krace)reci/zapisati npr. ”n log n+5n je O(n

√n)” umesto ”n log n+5n pripada skupu funkcija O(n

√n)”.

Zbog toga ce se takva notacija koristiti i ovde (smatrati da smo ”definisali” novu relaciju i oznacilije sa ”=”).

1Npr. funkcija 100n+ 42 pripada svakom od skupova O(n), O(n logn), O(n2), O(n10) i mnogim drugim; nama jeinformativnija procena 100n+ 42 ∈ O(n) od procene 100n+ 42 ∈ O(n10).

2Istina, funkcija moze pripadati mnogim Θ-skupovima, npr. 100n+ 42 pripada svakom od skupova Θ(n),Θ(5n−2),Θ(2n+ 3

√n− logn) itd., ali sve njih karakterise isti red velicine (u asimptotskom smislu).

2

Page 4: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 3

0.2 Model racunanja

Na nivou ovog kursa podrazumeva se varijanta RAM (Random Access Machine) modelaracunanja - ovaj model je (od svih osnovnih modela racunanje) najslicniji modernim racunarimai najmanje apstraktan. Pretpostavljamo da se masina koja izvrsava nase algoritme sastoji odbeskonacno 3 memorijskih lokacija (registara) pri cemu svaka od njih ima jedinstvenu adresu isvakoj od njih se moze pristupiti u slozenosti O(1).

Za potrebe ovog kursa smatramo da je velicina svake memorijske lokacije konacna (za razliku odstandardne pretpostavke RAM modela) ali dovoljno velika da svaka vrednost ulaznih parametaraalgoritama moze stati u jednu memorijsku lokaciju4. Npr. ukoliko je velicina memorijske lokacije2MaxSize bitova i ulazni podaci su niz A i duzina niza n, tada se smatra da se broj n i svaka odvrednosti A[i] moze predstaviti sa najvise 2MaxSize bitova. Ova dodatna pretpostavka nam olaksavaanalizu memorijske slozenosti algoritama a uz to nas priblizava analizi realnih racunskih masina.

Za analizu algoritama koristicemo takozvani uniform cost model gde se svakoj osnovnoj(masinskoj) instrukciji dodeljuje jedinicna cena.5 Na osnovu ovog modela, slozenost algoritmaracunamo ”brojanjem” osnovnih instrukcija koje se izvrse prilikom izvrsavanja algoritma.

Za nase potrebe, osnovnim instrukcijama/naredbama/operacijama smatracemo sledece instruk-cije/naredbe/operacije koje rade iskljucivo sa promenlijvima/vrednostima od kojih svakastaje u jednu memorijsku lokaciju:

• Naredbu dodele vrednosti promenljive (npr. x← y)

• Osnovne aritmeticke operacije: +, −, ·, / na celim i realnim brojevima

• Operacije celobrojnog deljenja i ostatka pri deljenju (div i mod) na celim brojevima

• Bit/logicke operacije (and, or, not, xor, left/right shift, pristup konkretnom bitu)

• Operacije poredenja (=, 6=, <,>,≤,≥)

• Ceste matematicke funkcije poput√x, sinx, log x osim ako se ne naglasi drugacije

Radi jednostavnosti i ukoliko nije drugacije naglaseno, smatracemo da konstantan broj osnovnihoperacija nad promenljivama koje staju u jednu memorijsku lokaciju daje rezultat koji staje u jednumemorijsku lokaciju. Specijalno, to znaci da ako x staje u registar, tada i vrednost P (x), gde jeP polinom stepena O(1), takode staje u registar (npr. x · y, x2017 + 5 staju u registar, dok to netreba pretpostavljati u opstem slucaju za npr. xy.)

3Ili ”konacno, ali dovoljno mnogo”4Mozemo i parafrazirati: smatramo da su svi ulazni parametri algoritma ”dovoljno mali” da je za cuvanje svakog

od njih u memoriji dovoljna po jedna memorijska lokacija.5Precizniji model je logarithmic cost model koji svakoj osnovnoj (masinskoj) instrukciji dodeljuje cenu pro-

porcionalnu broju bitova koji ucestvuju u njenom izvrsavanju. Medutim, ovaj model je komplikovan za prakticnuupotrebu i koristi se samo kada je neophodan - npr. prilikom specificnih algoritma sa brojevima gde ne mozemopretpostaviti da su svi (medu)rezultati dovoljno mali da staju u jedinicnu memorijsku lokaciju; tada nema smislasmatrati da npr. mnozenje takvih brojeva radi u konstantnoj slozenosti.

Page 5: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 4

0.3 Poznati identiteti

Teorema 0.4 Neka su a i b proizvoljni pozitivni realni brojevi razliciti od 1. Tada vazi loga n =Θ(logb n), gde oba izraza posmatramo kao funkciju po n.

Dokaz. Koristeci poznati identitet loga n = 1logb a

· logb n, dobijamo da se funkcije (po n) loga n i

logb n dobijaju jedna od druge mnozenjem konstantom (koja ne zavisi od n) odakle sledi tvrdenjeteoreme.

Dakle, kada uzimamo logaritam datog broja n, asimptotski je ”svejedno” koju osnovu uzimamo(log2 n, log10 n, lnn, . . .) jer su sve takve vrednosti istog reda velicine (pod pretpostavkom da jeosnova neka konstanta). Zbog toga cemo uvek smatrati da uzimamo logaritam za osnovu 2 ipisacemo skraceno log n.

Teorema 0.5 Neka je n prirodan broj. Tada vazi

a) 1 + 2 + 3 + . . .+ n = Θ(n2)

b) 1 + 12 + 1

3 + . . .+ 1n = Θ(log n)

c) log 1 + log 2 + log 3 + . . .+ log n = Θ(n log n)

gde se svi prethodni izrazi posmatraju kao funkcija promenljive n.

Teorema 0.6 Neka su n i k > 1 prirodni brojevi. Tada vazi

a) 1k + 2k + 3k + . . .+ nk = Θ(nk+1)

b) 1 + 12k

+ 13k

+ . . .+ 1nk

= Θ(1)

c) logk 1 + logk 2 + logk 3 + . . .+ logk n = Θ(n logk n)

gde se svi prethodni izrazi posmatraju kao funkcija promenljive n.

Page 6: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 1

Osnovne tehnike

1.1 Teorija

TODO

5

Page 7: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 6

1.2 Zadaci

Zadatak 1. Ispred blagajne je poredano n ljudi cije su visine h1, h2, . . . hn, redom. Odrediti brojljudi koje vidi blagajnik. Blagajnik vidi neku osobu x ukoliko su sve osobe u redu ispred osobe xnize od osobe x. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 8

5 5 8 7 11 12 5 11

4

Zadatak 2. Rotacija niza za jedno mesto ulevo predstavlja modifikaciju niza u kome se svakielement niza pomeri za jednu poziciju ulevo, pri cemu prvi element ode na poslednje mesto (npr.5 8 1 0 → 8 1 0 5). Dat je celobrojni niz a duzine n i prirodan broj m. Rotirati niz a za m mestaulevo. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 6 m = 4

3 8 -2 10 -7 5

-7 5 3 8 -2 10

Zadatak 3. Sedlo u matrici je element matrice koji je istovremeno najmanji (ili jedan od najman-jih) u svojoj vrsti a najveci (ili jedan od najvecih) u svojoj koloni. Za datu matricu celih brojevaA dimenzija n×m odrediti poziciju sedla, ukoliko postoji. Ukoliko ima vise resenja stampati bilokoje. Trazi se resenje vremenske slozenosti O(nm).

Ulaz Izlazn = 3 m = 4

1 5 1 0

3 4 3 5

7 1 2 2

Broj 3 na poziciji (2, 3)

Zadatak 4. Dat je niz realnih brojeva a duzine n i m upita tipa: kolika je suma brojeva napozicijama od Li do Ri u nizu a. Za svaki upit stampati odgovarajucu sumu. Trazi se resenjevremenske slozenosti O(n+m).

Ulaz Izlazn = 5 m = 3

5 11 22 10 50

2 3

3 5

1 5

33

82

98

Zadatak 5. Dat je celobrojni niz a duzine n. Odrediti uzastopni podniz niza a sa najvecom sumomsvojih elemenata (stampati sumu). Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 7

1 5 -10 5 -2 6 -4

9

(od 4. do 6. pozicije)

Zadatak 6. Grupa od n ucenika numerisanih brojevima od 1 do n je ucestvovala na 2 takmicenja.Za svako takmicenje je poznat poredak ovih ucenika, tj. date su dve permutacije brojeva od 1 don koje predstavljaju plasmane ovih ucenika na takmicenjima. Ucenik x je odrao ucenika y ako je

Page 8: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 7

bio bolji od njega na oba takmicenja. Odrediti koliko ima parova ucenika (x, y) za koje vazi da jeucenik x odrao ucenika y. Trazi se resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 5

3 5 1 4 2

1 3 5 2 4

6

(npr. 5 je odrao 4, 1 je odrao 2,

itd.)

Zadatak 7. Dat je niz a prirodnih brojeva duzine n i prirodan broj k. Potrebno je odrediti da liu ovom nizu postoji uzastopni podniz cija je suma elemenata jednaka k.

Programer Pera je smislio sledeci algoritam: na pocetku postavi promenljive i (levi kraj) i j(desni kraj) na 1 i trenutnu sumu s na a1. Zatim u svakom koraku uporedi s sa k: ako su jednaki,kraj; ako je s > k poveca i za 1 i oduzme ai od s; ako je s < k poveca j za 1 i doda aj sumi s.Algoritam se prekida kada i ili j postane vece od n.

1) Dokazati da je Perin algoritam tacan, implementirati ga i analizirati mu slozenost.

2) Da li je Perin algoritam dobar ako niz a moze sadrzati negativne brojeve?

Zadatak 8. Data je binarna matrica (matrica sastavljena od nula i jedinica) A dimenzija n×m.Odrediti da li skup svih polja u kojima je upisana jedinica obrazuje tacno jedan pravougaonik(pravougaonu podmatricu). Trazi se resenje vremenske slozenosti O(nm).

Ulaz Izlazn = 4 m = 4

0110

0110

0111

0000

NE

Zadatak 9. Dat je niz a celih brojeva duzine n. Za svaki element niza ispisati indeks prvog ele-menta sa njegove leve strane koji je strogo veci od njega (ispisati -1 ako takav element ne postoji).Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 10

4 1 8 4 3 3 6 2 7 20

-1 1 -1 3 4 4 3 7 3 -1

Zadatak 10. Na casu fizickog se n ucenika nasumicno poredalo u vrstu. Visina i-tog ucenika u vrstije ai, pri cemu su sve visine razlicite. Zatim im je nastavnik naredio da se poredaju rastuce premavisini. Odrediti koji ucenik je morao da prede najduzi put pri premestanju (stampati samo ap-solutnu razliku izmedu pocetne i krajnje pozicije). Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 7

90 100 80 95 81 101 99

4

(ucenik sa 2. na 6. poziciju)

Zadatak 11. Dato je n segmenata [ai, bi] na x–osi. Odrediti duzinu dela x–ose koji je prekrivenovim segmentima (tacka na x–osi je prekrivena ako pripada bar jednom segmentu). Trazi se resenjevremenske slozenosti O(n log n).

Page 9: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 8

Ulaz Izlazn = 3

5 10

3 8

20 30

17

Zadatak 12. Dato je n duzi cije su duzine prirodni brojevi. Ispitati da li medu njima postoje 3od kojih se moze sastaviti trougao. Ukoliko postoje, vratiti bilo koje resenje. Trazi se resenje vre-menske slozenosti O(n log n). [Ukoliko smatramo da su duzine duzi ogranicene odozgo konstantom,dizajnirati algoritam slozenosti O(1) koji resava ovaj problem!]

Ulaz Izlazn = 6

10 8 30 18 200 40

DA

30, 18 i 40

Zadatak 13. Dat je niz a duzine n ciji su svi elementi prirodni brojevi iz segmenta [1, k]. Sortirati(urediti) ovaj niz u neopadajuci poredak. Trazi se resenje vremenske slozenosti O(n+ k).

Ulaz Izlazn = 9 k = 53 5 1 4 4 2 3 1 4

1 1 2 3 3 4 4 4 5

Zadatak 14. Dva druga imaju neke evre i odlucili su da ih podele na jednake delove. Oni imajux novcanica u vrednosti od a evra i y novcanica u vrednosti od b evra. Odrediti da li mogu dapodele novac na dva jednaka dela i u slucaju da mogu stampati koliko od svake vrste novcanicadobija prvi drug. Trazi se resenje vremenske slozenosti O(minx, y).

Ulaz Izlazx = 2 a = 3

y = 3 b = 6

2 1

Zadatak 15. Programer Pera je resavao Zadatak 5 (uzastopni podniz sa maksimalnom sumom) idosao do nekih zakljucaka:

1) Optimalni podniz ce uvek sadrzati (bar jedan) maksimalan element niza.

2) Optimalni podniz nikada nece sadrzati (nijedan) minimalan element niza.

3) Ako niz a ima bar jedan nenegativan element onda optimalni podniz uvek pocinje i zavrsavase nenegativnim elementom.

Za svaki od njegovih zakljucaka odrediti da li je tacan (obrazloziti) ili ne (navesti kontra-primer).

Zadatak 16. Za dati polinom P stepena n sa celobrojnim koeficijentima a0, a1, . . . , an i dati ceobroj x izracuanti P (x) mod m. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 3 m = 100 x = 8

3 20 2 2

55

Zadatak 17. Dat je broj koji se sastoji od n cifara. Koji se najveci broj moze dobiti od ovogbroja brisanjem tacno k cifara (1 ≤ k < n)? Trazi se resenje vremenske slozenosti O(n+ k).

Page 10: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 9

Ulaz Izlazn = 7 k = 4

8299341

994

Zadatak 18. Dato je n pravougaonika u ravni sa stranicama paralelnim osama - svaki pravougaonikje zadat cetvorkom (x1, y1, x2, y2) gde su (x1, y1) i (x2, y2) koordinate gornjeg-levog i donjeg desnogtemena, redom. Odrediti povrsinu njihovog preseka. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 3

0 10 10 0

-2 3 5 0

2 20 4 -20

6

Zadatak 19. Dat je niz a celih brojeva duzine n. Odrediti koliko u ovom nizu ima uzastopnihpodnizova (podnizovi sastavljeni od uzastopnih elemenata niza a) cija je suma paran broj. Trazise resenje vremenske slozenosti O(n).

Ulaz Izlazn = 4

5 2 3 -4

4

Zadatak 20. Za proizvoljnu permutaciju p brojeva od 1 do n definisemo niz d kao:

d[i] =

1, ako prvih i elemenata niza p predstavljaju permutaciju brojeva od 1 do i0, inace

Za dati niz d, ispisati odgovarajucu permutaciju p. Ukoliko ima vise resenja, ispisati bilo koje;ukoliko ne postoji resenje, ispisati -1. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 5

0 0 1 0 1

2 3 1 5 4

Zadatak 21. Data je matrica celih brojeva A dimenzija n ×m kao i k upta tipa: kolika je sumabrojeva u pravougaonoj podmatrici cije je gornje-levo polje (Xi, Yi) a donje-desno polje (Zi, Ti). Zasvaki upiti stampati odgovarajucu sumu. Trazi se resenje vremenske slozenosti O(nm+ k).

Ulaz Izlazn = 3 m = 4

1 5 1 0

2 3 4 5

7 1 8 2

k = 3

(2, 1) (3, 3)

(1, 1) (3, 4)

(1, 4) (2, 4)

25

39

5

Zadatak 22. Data je matrica dimenzija n×m koja se sastoji samo od nula i jedinica. Ukoliko zaneki broj k postoji polje u matrici koje ima vrednost 1 i cijih k uzastpnih suseda gore, desno, dolei levo takode imaju vrednost 1 (i svi ti susedi su unutar matrice), taj skup od 4k + 1 polja nazi-vamo k-plus. Odrediti najvece k za koje u datoj matrici postoji k-plus. Trazi se resenje vremenske

Page 11: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 10

slozenosti O(nm).

Ulaz Izlazn = 8 m = 81 1 1 0 1 1 0 0

0 1 1 0 1 0 0 0

1 0 1 0 1 0 1 1

1 1 1 0 1 1 0 0

0 1 1 1 1 1 1 1

1 0 1 0 1 0 0 0

1 1 1 0 1 1 0 0

1 1 1 0 1 1 0 1

3

(centar 3-plusa je podvucen)

Page 12: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 11

1.3 Resenja

1. Trivijalno resenje je za svaku osobu i ispitati redom osobe i− 1, i− 2, . . . , 1 sve dok ne naidemona osobu koja je visa ili iste visine kao i-ta osoba (tada blagajnik ne vidi i-tu osobu) ili dok nenaidemo na pocetak reda (tada blagajnik vidi i-tu osobu). Vremenska slozenost ovog pristupa jeO(n2) i npr. u slucaju da je niz h rastuci izvrsicemo bas Θ(n2) poredenja. Memorijska slozenostje O(1).

Bolje resenje: oznacimo sa maxi = maxh1, h2, . . . , hi, tj. maxi = visina najvise osobe meduprvih i u redu (neka je, specijalno, max0 = −∞). Sada imamo da vazi: blagajnik vidi i-u osobu uredu ako i samo ako je hi > maxi−1. Vrednosti maxi moze izracunati linearno (s leva udesno) jerje maxi = maxmaxi−1, hi pa je ukupna vremenska slozenost ovog pristupa O(n) a memorijskaO(1) jer ne moramo koristiti niz max vec samo jednu promenljivu.

Solve(n, h[])

sol ← 0

M ← −∞

for i ← 1 to n do

if (h[i] > M)

sol ← sol + 1

M ← max(M, h[i])

return sol

2. Najjednostavnije (ali veoma neefikasno) resenje je direktno simulirati rotaciju za po jedno mestoulevo m puta: svaki put zapamtimo trenutni prvi element u pomocnu promenljivu, pomerimo sveelemente za jedno mesto ulevo i na kraju vrednost pomocne promenljive prebacimo na kraj. Kakom puta radimo O(n) instrukcija (pomeranje), ukupna vremenska slozenost algoritma je O(mn)(zapravo, bas Θ(mn)) a memorijska slozenost je O(1).

SolveSlow(n, m, a[])

for i ← 1 to m do

t ← a[1]

for j ← 1 to n - 1 do

a[j] ← a[j + 1]

a[n] ← t

return a[]

Mozemo i mnogo bolje: za pocetak, primetimo da je, zbog ponavljanja, rotacija niza za m mestaista kao i rotacija niza za m mod n mesta (npr. ako niz duzine 10 rotiramo 23 puta, dobijamo istiniz kao da smo ga rotirali svega 3 puta). Zato mozemo odraditi dodelu m← m mod n i obezbeditise da je m < n.

Dodatnom analizom uocavamo da je rotacija niza za m mesta ulevo (kada je m < n) zapravozamena mesta prvih m elemenata i poslednjih n − m elemenata niza (ili premesanje prvih melemenata, u tom redosledu, na kraj niza). Ovaj postupak je vrlo jednostavno uraditi koriscenjempomocnog niza kao sto je prikazano u pseudo-kodu. Vremenska slozenost algoritma je ociglednoO(n) (zapravo bas Θ(n)) dok je memorijska slozenost O(n) zbog pomocnog niza.1

SolveFast(n, m, a[])

m ← m mod n

for i ← 1 to n - m do

b[i] ← a[n - m + i];

1Razmisliti kako da se ovaj zadatak uradi u O(n) uz svega O(1) dodatne memorije!

Page 13: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 12

for i ← n - m + 1 to n do

b[i] ← a[i - (n - m)];

for i ← 1 to n do

a[i] ← b[i];

return a[]

3. Trivijlani algoritam: za svaki element matrice (nm mogucnosti) proverimo da li je on najmanjiu svojoj vrsti i da li je najveci u svojoj koloni (klasicnim poredenjem sa svim elementima iz njegovevrste i kolone). To zahteva Θ(n+m) poredenja po elementu (jer toliko ima elemenata u njegovojvrsti i koloni) pa je vremenska slozenost algoritma O(nm(n+m)) a memorijska O(1).

Mozemo i bolje. Oznacimo sa r[i] - vrednost najmanjeg elementa u i-toj vrsti a sa c[j] - vrednostnajveceg elementa u j-toj koloni. Nizove r i c mozemo izracunati u slozenosti O(nm) - za svakoi, odnosno j, prodemo kroz sve elemente odgovarajuce vrste, odnosno kolone. Sada prodjemokroz svaki element matrice i proveru da li je A[i][j] sedlo radimo u O(1) - A[i][j] je sedlo akko jer[i] = A[i][j] i c[j] = A[i][j]. Vremenska slozenost ovog pristupa je O(nm) a memorijska O(n+m).

Solve(n, m, A[][])

r[] ←∞c[] ← −∞for i ← 1 to n do

for j ← 1 to m do

r[i] ← min(r[i], A[i][j])

c[j] ← max(c[j], A[i][j])

for i ← 1 to n do

for j ← 1 to m do

if (r[i] = A[i][j] and c[j] = A[i][j])

return (i, j)

return -1

4. Trivijalno resenje je za svaki upit eksplicitno sabirati sve brojeve od Li-te do Ri-te pozicije.Vremenska slozenost ovog pristupa je O(m · n) jer u svakom upitu sabiramo Ri − Li + 1 brojeva avazi Ri−Li + 1 = O(n) tj. u ”najgorem slucaju” mozemo u svakom upitu da prolazimo skoro krozceo niz. Memorijska slozenost je O(1).

Pametniji nacin je koriscenje niza prefiksnih suma tj. niza s definisanog sa s0 = 0 i si =a1 + a2 + . . . + ai za svako 1 ≤ i ≤ n. Ovaj niz mozemo konstruisati u slozenosti O(n) na osnovurekurentne formule si = si−1 + ai. Kako za proizvoljne indekse l < r vazi

al + al+1 + . . .+ ar = (a1 + a2 + . . . ar)− (a1 + a2 + . . . al−1) = sr − sl−1

sledi da na svaki upit mozemo odgovarati u O(1) tako sto za i-ti upit vratimo vrednost sRi − sLi−1 .Ukupna vremenska slozenost (konstrukcija niza s i odgovaranje na upite) je sada O(n+m) dok jememorijska slozenost O(n) zbog niza s.

Solve(n, m, a[], l[], r[])

s[0] ← 0

for i ← 1 to n do

s[i] ← s[i - 1] + a[i]

for i ← 1 to m do

print(s[r[i]] - s[l[i] - 1])

Page 14: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 13

5. Trivijalno resenje je da ispitamo sve uzastopne podnizove niza a (njih ima Θ(n2) jer fiksiramopocetni i kranji indeks) i za svaki od njih izracunamo sumu elemenata. Naivna implementacijaovoga (racunanje svake od ovih suma u O(n)) daje slozenost od O(n3) dok nesto pametnija im-plementacija (npr. fiksiramo pocetak podniza a zatim, kako pomeramo kraj podniza, paralelnoracunamo i trenutnu sumu pa nam ne treba i treca ugnjezdena petlja) dovodi do slozenosti O(n2).Za detalje, videti pseudo-kodove.

Definisimo niz prefiksnih suma s kao u prethodnom zadatku. Zadatak se svodi na pronalazenjeindeksa 0 ≤ i < j ≤ n u nizu s za koje je sj − si najvece moguce (to odgovara podnizuai+1, ai+2, . . . , aj u nizu a). Provericemo sve mogucnosti za j (desni kraj) i uzeti najbolje resenje; zafiksirano j nam treba indeks i tako da je si najmanji od svih brojeva s0, s1, . . . , sj−1 (da bi razlikasj−si bila najveca). Kako se krecemo s leva na desno, u svakom trenutku pamtimo promenljivu M- najmanji medu svm elementima niza s od prvog do trenutnog. Za j-ti element je resenje sj −Mdok kada prelazimo na (j + 1)-vi, treba postaviti M = min(M, sj). Dakle, uz ovo ”pametno”racunanje minimuma, dobili smo algoritam vremenske i memorijske slozenosti O(n).

VeryBadSolution(n, a[]) (* slozenost O(n3) *)

sol ← −∞for i ← 1 to n do

for j ← i to n do

sum ← 0

for k ← i to ← j do

sum ← sum + a[k]

sol ← max(sol, sum)

return sol

BetterSolution(n, a[]) (* slozenost O(n2) *)

sol ← −∞for i ← 1 to n do

sum ← 0

for j ← i to n do

sum ← sum + a[j] (* u ovom trenutku sum = a[i] + a[i+1] + ... + a[j] *)

sol ← max(sol, sum)

return sol

BestSolution(n, a[]) (* slozenost O(n) *)

s[0] ← 0

for i ← 1 to n do

s[i] ← s[i - 1] + a[i]

sol ← −∞M ← 0

for j ← 1 to n do

sol ← max(sol, s[j] - M) (* s[j] - M je max suma koja se zavrsava u a[j] *)

M ← min(M, s[j]) (* u ovom trenutku M = mins[0], s[1], ..., s[j] *)

return sol

6. Trivijalno resenje: za svaki par ucenika (x, y) proverimo da li je x odrao y tako sto prodemokroz obe permutacije i proverimo da li se i u prvoj i u drugoj x javlja pre y. Dakle, prolazimo krozcelu permutaciju (n elemenata) za svaki od O(n2) parova pa je vremenska slozenost ovog algoritmaO(n3); memorijska je O(1).

Mnogo bolje resenje je da napravimo nizove p1[i] = pozicija ucenika i na prvom takmicenju

Page 15: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 14

(prvoj permutaciji) i p2[i] = pozicija ucenika i na drugom takmicenju (drugoj permutaciji). Nekanizovi a i b predstavljaju date permutacije. Nizove p1 i p2 lako konstruisemo u O(n) tako sto zasvako i od 1 do n postavimo p1[a[i]] = i i p2[b[i]] = i. Sada za svaki par ucenika (x, y) mozemoproveriti u O(1) da li je x odrao y: to je ekvivalentno sa p1[x] < p1[y] i p2[x] < p2[y]. Dakle,vremenska slozenost je sada O(n2) a memorijska O(n).

Solve(n, a[], b[])

for i ← 1 to n do

p1[ a[i] ] ← i

p2[ b[i] ] ← i

sol ← 0

for x ← 1 to n do

for y ← 1 to n do

if ((p1[x] < p1[y]) and (p2[x] < p2[y]))

sol ← sol + 1

return sol

7. Ponudeni algoritam u svakom trenutku posmatra uzastopni podniz [i, j] tj. podniz od i-tog do j-tog elementa niza a i pamti njegovu trenutnu sumu s. Ukoliko je s = k, resenje je nadeno i algoritamse zavrsava. Inace, ukoliko je s < k, nema smisla proveravati podnizove [i+ 1, j], [i+ 2, j], . . . , [j, j]jer ce njihove sume takode biti manje od k (skidamo pozitivne brojeve iz podniza [i, j]) pa sledecipodniz koji ima smisla proveravati je bas [i, j + 1]. Slicno, ukoliko je s > k, tada nema smislaproveravati podnizove [i, j + 1], [i, j + 2], . . . , [i, n] jer su njihove sume takode vece od k (elementiniza a su pozitivni) pa sledeci podniz koji ima smisla proveravati je [i+ 1, j].

Na ovaj nacin ”propustamo” samo podnizove koji nisu kandidati za resenje pa ukoliko nizsa sumom k postoji, ovaj algoritam ce ga pronaci – dakle, algoritam je tacan. Jedna mogucaimplementacija je sledeca.

Solve(n, a[], k)

i ← 1

j ← 1

s ← a[1]

while ((i ≤ n) and (j ≤ n)) do

if (s = k)

return true

if (s < k)

s ← s - a[i]

i ← i + 1

else

j ← j + 1

s ← s + a[j]

return false

Uocimo da se u svakom ciklusu while petlje izvrsi konstantan broj naredbi; prema tome slozenostalgoritma jednaka je redu velicine broja izvrsavanja while petlje. Kako se petlja zavrsava kada i ilij postane vece od n, a u svakom koraku petlje se ili i ili j poveca za 1, petlja se izvrsava najvise2n puta pa je vremenska slozenost algoritma O(n) a memorijska O(1).

Inace prethodni algoritam je moguce implementirati na sledeci nacin:

Solve2(n, a[], k)

j ← 0

Page 16: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 15

s ← 0

for i ← 1 to n do

while ((j < n) and s < k)

j ← j + 1

s ← s + a[j]

if (s = k)

return true

s ← s - a[i]

return false

Citaocu se ostavlja da pokaze da je ovaj algoritam radi istu stvar kao prethodni. Sto se slozenostitice, ”najugnjezdenije” naredbe su ”j ← j + 1” i ”s ← s + a[j]” ali se one izvrsavaju najvise nputa jer se prilikom svakog izvrsavanja j povecava za 1 a u petlju se ne ulazi vise kada j postane n.Zakljucak: iako imamo dve ugnjezdene petlje, slozenost u ovom slucaju nije kvadratna vec linearnatj. O(n).

Za deo 2), odgovor je: Perin algoritam nije tacan ako se u nizu a javljaju i negativni brojevi.Npr. za n = 3, a = (3, 3,−1) i k = 5, algoritam prvo ispituje podniz [1, 1], zatim [1, 2] (jer je3 < 5), zatim [2, 2] (jer je 3 + 3 > 5), zatim [2, 3] pa se zavrsava i prijavljuje da podniz sa sumom5 ne postoji sto nije tacno (takav je podniz [1, 3] tj. ceo niz).

8. Postoji puno nacina da se ovaj problem resi u slozenosti Ω((nm)2) tj. u slozenosti O((nm)2) ilijos ”slabijoj”. Npr. jedno od resenja je da za svaku pravougaonu podmatricu proverimo (prolaskomkroz celu matricu) da li se u njoj nalaze samo jedinice i da li se van nje nalaze samo nule. Matrica

dimenzija n × m sadrzi Θ((nm)2) pravougaonih podmatrica (n(n+1)2 nacina da izaberemo gornju

i donju vrstu i m(m+1)2 nacina da izaberemo levu i desnu kolonu) i za svaku od njih prolazimo

kroz celu matricu (nm operacija) pa je ukupna vremenska slozenost algoritma O((nm)3) (tj. basΘ((nm)3)) dok je memorijska O(1) (videti pseudo-kod).

SolveSlow(n, m, A[][])

for u ← 1 to n do

for d ← u to n do

for l ← 1 to m do

for r ← l to m do

(* fiksirana podmatrica: gornje levo polje (u,l) a donje desno (d,r) *)

ok ← true

for i ← 1 to n do

for j ← 1 to m do

if (A[i][j] = 0 and u ≤ i ≤ d and l ≤ j ≤ r)

ok → false (* nula u pravougaoniku *)

if (A[i][j] = 1 and not(u ≤ i ≤ d and l ≤ j ≤ r))

ok → false (* jedinica van pravougaonika *)

if (ok)

return DA

return NE

Bolje resenje je sledece: jednim prolaskom kroz matricu cemo izracunati s = broj svih jedinica ivrednosti l, r, u, d koje, redom, predstavljaju najlevlju kolonu, najdesnju kolonu, najgornju vrstu inajdonju vrstu u kojoj se nalazi neka jedinica. To znaci da sve jedinice obrazuju pravougaonik akoi samo ako je ceo pravougaonik [u, d]× [r, l] popunjen jedinicama za sta je dovoljno proveriti da li je(d− u+ 1)(r− l+ 1) = s (ili jos jednom proci kroz matricu). Zaista, ako pomenuta jednakost vazi,onda je ceo pravougaonik [u, d]× [r, l] popunjen jedinicama jer zbog definicije brojeva u, d, l, r van

Page 17: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 16

pomenutog pravougaonika nema jedinica. Vremenska slozenost ovog algoritma je ocigledno O(nm)a memorijska O(1).

SolveFast(n, m, A[][])

s ← 0

u ← n + 1, d ← 0

l ← m + 1, r ← 0

for i ← 1 to n do

for j ← 1 to m do

if (A[i][j] = 1)

s ← s + 1

u ← min(u, i)

d ← max(d, i)

l ← min(u, j)

r ← max(u, j)

if ((d - u + 1)*(r - l + 1) = s)

return DA

else

return NE

9. Trivijalno resenje slozenosti O(n2): za svaki element ai ispitujemo redom elemente ai−1, ai−2 . . .dok ne naidemo na prvi strogo veci ili do pocetka niza.

Pametnije resenje je da idemo od pocetka niza i elemente ubacujemo na stack. Preciznije, napocetku je stack prazan i za svako i od 1 do n radimo sledece: izbacujemo elemente sa vrha stackasve dok su oni manji ili jednaki od ai ili dok se stack ne isprazni; element koji je ostao na stackuposle ovog je prvi s leve strane koji je strogo veci od ai odnosno takav element ne postoji ako je stackprazan (∗); posle ovoga ubacimo ai na vrh stacka. Tvrdenje (∗) je tacno jer svaki element ”uklanja”sve elemente manje od njega koji nikako ne mogu biti resenja za buduce elemente; primetimo dasu u svakom trenutku elementi na stacku u opadajucem poretku (od dna do vrha stacka-a) panijedan element na stack-u nije ”zaklonjen” i doci ce se do njega ukoliko je bas on resenje. Kakosvaki element ubacimo tacno jednom na stack a izbacimo najvise jednom, vremenska i memorijskaslozenost ovog algoritma je O(n).

Solve1(n, a[]) (* koristimo klasicni stack *)

Stack S.clear()

for i ← 1 to n do

while (not S.empty() and a[S.top()] ≤ a[i])

S.pop()

if (S.empty())

d[i] ← -1

else

d[i] ← S.top()

S.push(i)

return d[]

Solve2(n, a[]) (* simuliramo stack nizom S *)

ssize ← 0

for i ← 1 to n do

while ((ssize > 0) and (a[ S[ssize] ] ≤ a[i]))

ssize ← ssize - 1

Page 18: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 17

if (ssize = 0)

d[i] ← -1

else

d[i] ← S[ssize]

ssize ← ssize + 1

S[ssize] ← i

return d[]

10. Samo sortiramo ucenike prema visini, za svakog izracunamo apsolutnu vrednost razlike njegovetrenutne pozicije i pocetne pozicije i uzmemo maksimum. Da bismo pamtili stare pozicija, najboljeje sortirati niz struktura (ili uredenih parova) gde svaka ima polja visina i pocetna pozicije. Koristecineki od brzih algoritama sortiranja (poput Merge Sorta) postize se vremenska slozenost O(n log n)dok je memorijska slozenost O(n) jer moramo pamtiti pocetnu poziciju za svakog ucenika.

Solve(n, a[])

for i ← 1 to n do

student[i].h ← a[i]

student[i].p ← i

Sort(n, student[]) na osnovu vrednosti student[i].h

sol ← 0

for i ← 1 to n do

sol = max(sol, |i - student[i].p|)

return sol

11. Jasno, ne mozemo samo sabrati duzine segmenata jer neki od njih mogu da se seku. Jednood resenja je sledece: sortirajmo sve segmente po levom kraju (npr. pretpostavimo da su segmentizadati kao niz struktura s gde imamo s[i].l i s[i].r umesto ai i bi). Na pocetku obelezimo segment s[1]kao aktivni a zatim obilazimo segmente redom i u svakom koraku radimo sledece: ukoliko trenutnisegment ima presek sa aktivnim, prosirimo aktivni segment sa desne strane ako je desni kraj novogsegmenta veci od desnog kraja aktivnog (gledamo samo desni kraj jer obilazimo niz segmenatasoritranih po levom kraju); u suprotnom, dodamo ukupnoj duzini duzinu aktivnog segmenta ipostavljamo trenutni segment kao aktivni (to znaci da je doslo do ”prekida” u pokrivanju x-ose;aktivni segmenti tokom izvrsavanja algoritma predstavljaju uniju segmenata koji imaju neprazanpresek). Vremenska slozenost ovog pristupa je O(n log n) zbog pocetnog sorta a memorijska O(1)ukoliko je dozvoljeno da se menja pocetni niz.

Solve(n, s[])

Sort(n, s[]) po vrednosti s[i].l

sol ← 0

L ← s[1].l

R ← s[1].r

for i ← 2 to n do

if (s[i].l ≤ R)

R ← max(R, s[i].r)

else

sol ← sol + (R - L)

L ← s[i].l

R ← [i].r

(* u for petlji se nece uracunati duzina poslednjeg aktivnog segmenta! *)

Page 19: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 18

sol ← sol + (R - L)

return sol

12. Trivijalno resenje je da isprobamo svake 3 duzi i vidimo da li one cine stranice trougla; slozenostovog pristupa je O(n3). Uz pomoc sortiranja i/ili binarne pretrage ovo je moguce poboljsati naO(n2 log n) ili O(n2).

Moze i bolje. Na pocetku sortiramo duzi neopdajuce d1 ≤ d2 ≤ . . . ≤ dn nekim sort-omslozenosti O(n log n). Sada vazi: za i < j < k, duzi di, dj i dk cine trougao ako i samo ako vazidi + dj > dk (zbor uredenosti nema potrebe proveravati i ostale dve nejednakosti).

Pretpostavimo da za neke i < j < k postoji trougao cije su stranice di, dj , dk. Tada sigurnopostoji i trougao sa stranicama di, dj i dj+1 jer je dj+1 ≤ dk < di + dj . Dodatno, tada sledi i dapostoji trougao sa stranicama dj−1, dj i dj+1 jer je dj+1 < di + dj ≤ dj−1 + dj . Dakle, pokazalismo da ako je moguce formirati trougao (na bilo koji nacin) tada je moguce formirati trougao ipomocu tri uzastopne duzi u sortiranom nizu; sledi da je dovoljno proveravati samo po tri uzastopneduzi u sortiranom nizu a takvih trojki ima O(n). Prema tome, vremenska slozenost algoritma jeO(n log n) a memorijska O(1).

Solve(n, d[])

Sort(n, d[])

for i ← 1 to n - 2 do

if (d[i] + d[i + 1] > d[i + 2])

return (d[i], d[i + 1], d[i + 2])

return "Ne postoje"

13. TODO

14. Jasno je da na kraju svaki drug treba da dobije s = xa+yb2 evra (ukoliko xa + yb nije paran

broj, odmah mozemo zakljuciti da ne postoji resenje). Najtrivijalniji algoritam je isprobavanje svihmogucnosti: za svako 0 ≤ i ≤ x i svako 0 ≤ j ≤ y dodeliti prvom drugu i novcanica od a evra ij novcanica od b evra i proveriti da li one u sumi daju s. Ukoliko postoji bar jedan par (i, j) satrazenom osobinom, vracamo resenje a suprotnom resenje ne postoji. Slozenost ovog pristupa jeO(xy) zbog ugnjezdene petlje.

SolveSlow(x, a, y, b)

for i ← 0 to x do

for j ← 0 to y do

if (i·a + j·b = (x·a + y·b) / 2)

return (i, j)

return "nemoguce"

Medutim, ispitivanje svih raspodela novcanica mozemo odraditi mnogo pametnije: ako smo odlucilida prvom drugu damo i novcanica vrednosti a evra tada ne moramo da isprobavamo sve mogucevrednosti j od 0 do y. Zaista, kako oba drugara moraju imati po s evra na kraju, iz i·a+j ·b = s sledij = s−i·a

b , tj. j je jedinstveno odredeno i samo treba proveriti da li je ova vrednost celobrojna i dali pripada segmentu [0, y]. Slozenost ovog pristupa je svega O(x) (memorijska je kod oba algoritmaO(1)). Kako je svejedno po kojim novcanicama iteriramo, izbracemo one kojih ima manje i time”blago” ubrzavamo algoritam sa O(x) na O(minx, y).

Solve(x, a, y, b)

Page 20: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 19

if ((x·a + y·b) mod 2 6= 0) (* ukupna vrednost nije paran broj *)

return "nemoguce"

s ← (x·a + y·b) / 2

if (x > y) (* da bismo iterirali do manje od vrednosti x i y *)

swap(x, y)

swap(a, b)

for i ← 0 to x do

if ((s - i · a) mod b = 0 and (s - i · a) / b ≥ 0 and (s - i · a) / b ≤ y)

return (i, (s - i · a) / b)

return "nemoguce"

15. Prva dva zapazanja Programera Pere nisu tacna. Za zapazanje 1) jedan od kontraprimera je2 2 -4 3 (optimalno resenje je podniz 2 2 i ne sadrzi najveci element 3); za zapazanje 2) jedan odkontraprimera je 2 -1 2 (otimalno resenje je ceo niz 2 -1 2 i sadrzi najmanji element -2).

Trece zapazanje je tacno: kako niz sadrzi bar jedan nenegativan element, optimalni podniztakode sadrzi bar jedan nenegativni element (inace bi suma bila negativan broj); ukoliko otimalnipodniz pocinje negativnim elementom, mozemo izbaciti element sa pocetka niza i dobiti podnizsa vecom sumom (jer je izbaceni element negativan i pocetni podniz ima bar 2 elementa) sto jenemoguce jer smo pretpostavili da je pocetni niz optimalan. Analogno i za kraj optimalnog podniza.

16. Potrebno je izracunati vrednost izraza anxn+an−1x

n−1+. . .+a1x+a0 po modulu m (tj. ostatakpri deljenju pomenutog izraza brojem m). Ukoliko bismo svaki clan aix

i racunali u slozenosti O(i)tj. ponovnim stepenovanjem, ukupno bismo izvrsili otprilike 1 + 2 + . . . + n = Θ(n2) operacijasto nije optimalno. Jedan od linearnih algoritama je da pamtimo trenutnu vrednost X = xi (napocetku X = 1) i u svakom narednom koraku je pomnozimo sa x.

Moguce je i iskoristiti i cinjenicu da je

P (x) = a0 + x(a1 + x(a2 + . . .+ x(an−1 + xan) . . .))

pa P (x) mozeo racunati iterativo simulacijom prethodnog izraza: na pocetku stavimo P = 0 azatim za svako i od n do 0 odradimo ”update” P ← (P · x+ ai) mod m. Memorijska slozenost jeO(1).

Solve(n, x, m, a[])

P ← 0

for i ← n downto 0 do

P ← (P · x + a[i]) mod m

return P

17. TODO

18. Primetimo da je presek dva pravougaonika (podrazumevamo da su njihove stranice, kao uuslovu zadatka, paralelne osama) ili pravouganik (mozda degenerisan u duz ili tacku) ili prazanskup. Za pravougaonike (x1, y1, x2, y2) i (x′1, y

′1, x′2, y′2) presek je pravougaonik (max(x1, x

′1),max(y1, y

′1),

min(x2, x′2),min(y2, y

′2)) Slicno, presek svih paravougaonika je pravougaonik cija je x-koordinata

leve strane jedana najvecoj od svih x-koordinata levih strana, x-koordinata desna stranje je naj-manja od svih x-koordinata desnih strana i slicno za gornje i donje strane. Ukoliko se leva i desna

Page 21: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 20

ili gornja i donja koordinata preseka ”mimoilaze”, presek je prazan. Na osnovu ovoga, zadatak selako resava u O(n) vremana i O(1) memorije.

Sove(n, x1[], y1[], x2[], y2[])

(X1, Y1, X2, Y2) ← (x1[1], y1[1], x2[1], y2[1])

for i ← 2 to n do

X1 ← max(X1, x1[i])

Y1 ← max(Y1, y1[i])

X2 ← min(X2, x2[i])

Y2 ← min(Y2, y2[i])

if (X1 ≤ X2 and Y1 ≤ Y2)

return (X2 - X1)(Y2 - Y1)

else

return -1

19. Ispitivanjem svih mogucih uzastopnih podnizova dolazimo do trivijalnog resenja slozenostiO(n3) i malo manje trivijalnog resenja slozenosti O(n2).

Za bolje resenje ponovo koristimo niz prefiksinh suma s. Niz a ima parnu sumu od pozicijei do pozicije j akko su brojevi si−1 i sj iste parnosti. Dakle, svakom parnom nizu (jedinstveno)odgovara par razlicitih elmenata niza s koji su iste parnosti. Ako s ima x parnih elemenata i yneparnih elemenata (x + y = n + 1 jer je s indeksiran od nule), resenje je

(x2

)+(y2

). Vremenska i

memorijska slozenost algoritma je O(n).

Sove(n, a[])

s[0] ← 0

for i ← 1 to n do

s[i] ← s[i - 1] + a[i]

x ← 0

y ← 0

for i ← 0 to n do

if (s[i] mod 2 = 0)

x ← x + 1

else

y ← y + 1

return x(x - 1)/2 + y(y - 1)/2

20. TODO

21. Koristimo slican pristup kao i u 4. zadatku. Definisimo matricu prefiksnih suma S kao S[i][j] =suma svih elemenata matrice A u pravougaoniku cije je gornje-levo polje (1, 1) a donje desno (i, j).Specijalno S[i][0] = S[0][j] = 0 za svako i i j. Ova matrica se moze izracunati u slozenosti O(nm)koristeci rekurentnu vezu

S[i][j] = A[i][j] + S[i− 1][j] + S[i][j − 1]− S[i− 1][j − 1].

Sada, za svaki pomenuti upit (Xi, Yi, Zi, Ti) iz zadatka, odgovaramo u O(1) tako sto vratimo broj2

S[Zi][Ti]− S[Zi][Yi − 1]− S[Xi − 1][Ti] + S[Xi − 1][Yi − 1].

2Obavezno nacrtati sliku (matricu) i pokazati tacnost ove formule i rekurentne veze!

Page 22: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 21

Vremenska slozenost ovog algoritma je O(nm+ k) a memorijska O(nm) zbog matrice S.

22. Trivijalno resenje: za svako polje (i, j), u kome se nalazi jedinica, izracunamo (obicnim pro-laskom po i-toj vrsti i j-toj koloni) koliko najvise njegovih uzastopnih suseda gore, dole, levo idesno ima vrednost 1; najmanji od ta 4 broja je dimenzija najveceg plusa sa centrom u (i, j). Nakraju uzmemo najveci od svih pluseva. Vremenska slozenost ovog algoritma je O(nm(n + m)) amemorijska O(1).

Definisimo matricu gore[i][j] - najduzi niz usastopnih jedinica kada se od polja (i, j) ide nagore, racunajuci i njega samog (npr. u primeru iz teksta zadatka gore[5][2] = 2, gore[6][2] =0). Ovo se moze racunati u O(1) po polju obilaskom matrice odozgo-nadole i cinjenice da jegore[i][j] = 0 ukoliko je na polju (i, j) nula a inace gore[i][j] = 1 + gore[i − 1][j]. Potpunoanalogno definisimo matrice dole, levo i desno. Na osnovu prethodnog, sve matrice racunamo uslozenosti O(nm). Sada samo prodjemo kroz svako polje (i, j) i uzmemo ono sa najvecom vrednoscumin(gore[i][j], dole[i][j], levo[i][j], desno[i][j]). Vremenska i memorijska slozenost ovog pristupa jeO(nm).

Page 23: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 2

Algoritmi teorije brojeva

2.1 Teorija

Definicija 2.1 Prirodan broj p > 1 je prost ukoliko p nema nijedan delilac d za koji vazi 1 < d < p.Prirodan broj m > 1 je slozen ako nije prost.

Primetimo da broj 1 nije ni prost ni slozen.

Teorema 2.2 (Osnovna teorema aritmetike) Svaki prirodan broj n veci od 1 moze se jed-noznacno predstaviti kao proizvod prostih cinilaca (sa tacnoscu do njihovog poretka). Preciznije, zasvaki prirodan broj n > 1 postoji jedinstven broj k, jedinstveni prosti brojevi p1 < p2 < . . . < pk ijedinstveni prirodni brojevi α1, α2, . . . , αk za koje vazi

n = pα11 pα2

2 · · · pαkk .

O(√n)-algoritmi za faktorizaciju

Teorema 2.3 Svaki slozen prirodan broj n ima delilac d za koji vazi 1 < d ≤√n.

Dokaz. Kako je n slozen broj, postoji njegov delilac d za koji vazi 1 < d < n. Medutim, tada jei broj n

d takode delilac broja n (d · nd = n). Ukoliko bi vazilo da je i d >√n i n

d >√n dobili bismo

da je n = d · nd >√n ·√n = n sto je kontradikcija. Dakle, bar jedan od delilaca d, nd je u segmentu

[2,√n] sto je i trebalo dokazati.

Problem 2.4 Dat je prirodan broj n.

a) Proveriti da li broj n prost.

b) Ispisati sve (pozitivne) delioce broja n.

c) Faktorisati broj n (predstaviti ga u obliku p1α1 · p2α2 · · · pkαk).

Ovde cemo izloziti tri glavna ”√n-algoritma” za resavanje prethodnog problema koji se

baziraju na Teoremi 2.3 i koji su u mnogim zadacima potrebni kao pomocne funkcije.1 Svaki odovih algoritama (kao sto naziv sugerise) radi u slozenosti O(

√n).

Deo a) Trivijalan algoritam za proveru da li je broj prost radi u slozenostO(n) tako sto proveravada li je n deljiv nekim brojem iz segmenta [2, n− 1]. Medutim, na osnovu Teoreme 2.3 sledi da jedovoljno proveriti da li je n deljiv nekim od brojeva 2, 3, . . . , b

√nc; ako nije, sigurno je prost. Ovim

dobijamo algoritam vremenske slozenosti O(√n) i memorijske O(1).

1Razumeti ih u potpunosti jer ce se cesto pojavljivati u pseudo-kodovima! Iako cemo ubuduce samo pozivati ovefunkcije, na kolokvijumima se moraju implementirati.

22

Page 24: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 23

IsPrime(n)

if (n = 1)

return false;

for d ← 2 to b√nc do

if (n mod d = 0)

return false

return true

Deo b) Iz dokaza Teoreme 2.3 imamo jedno korisno zapazanje - delioci prirodnog broja n ”dolazeu paru”, tj. ako d | n tada i n

d | n; npr. parovi delilaca broja 12 su (1, 12), (2, 6), (3, 4). Jedini”izuzetak” je d =

√n ukoliko je n potpun kvadrat (tada je d = n

d ). Dakle, svakom deliocu manjemod√n odgovara jedinstven delilac veci od

√n pa broj n ima najvise 2

√n delilaca.

Prema tome, umesto klasicne provere svih brojeva iz [1, n] dovoljno je za svaki broj 1 ≤ d ≤ b√nc

ispitati da li d | n i u slucaju pozitivnog odgovora ispisati brojeve d i nd (osim kada je d =√n, tada

se ispise samo jedan broj).

AllDivisors(n)

divisors ← empty vector

d ← 1

while (d · d < n) do

if (n mod d = 0)

divisors.add(d)

divisors.add(n/d)

d ← d + 1

if (d · d = n)

divisors.add(d)

return divisors[]

Deo c) - neka je n = pa11 pa22 · · · p

akk . Ideja algoritma je jednostavna: ispitivati redom brojeve

2, 3, 4, . . . (najvise do b√nc) i prvi (najmanji) koji deli n mora biti njegov najmanji prost cinilac

p1. Zatim, dok god je moguce, delimo broj n brojem p1 (tako odredujemo a1). Ostaje nam brojn′ = pa22 · · · p

akk nad kojim ponavljamo prethodni postupak pri cemu ne krecemo sa trazenjem broja

p2 ispocetka (2, 3, . . .) vec od p1 + 1, p1 + 2, . . . (najvise do b√n′c) jer je p2 > p1. Ovo ponavljamo

dok nam brojac (potencijalni delilac) ne bude vei od korena trenutno posmatranog broja (oznacimoga sa x). Mogue su dve situacije:

• x = 1: Kraj algoritma, broj n je faktorisan;

• x > 1: Kako x nema delilac ≤√x, prema Teoremi 2.3, on je prost. Dakle x = pk i ak = 1.

Slozenost opisanog algoritma (vidi pseudokod) je zaista O(√n) - ovo je jasno ako se zanemari

”unutrasnja” while petlja. Medutim, unutrasnja while petlja se ukupno (tokom celog algoritma)izvrsi a1 + a2 + . . . + ak puta (svaki put kada podelimo trenutnu vrednost n nekim brojem pi).Kako je n = pa11 p

a22 · · · p

akk ≥ 2a12a2 · · · 2ak = 2a1+a2+...+ak sledi a1 + a2 + . . .+ ak ≤ log n sto spada

u O(√n).

Factorization(n)

k ← 0

d ← 2

Page 25: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 24

while (d · d ≤ n) do

if (n mod d = 0)

k ← k + 1

p[k] ← d

a[k] ← 0

while (n mod d = 0)

n ← n / d

a[k] ← a[k] + 1

d ← d + 1

if (n > 1)

k ← k + 1

p[k] ← n

a[k] ← 1

return k, p[], a[]

Eratostenovo sito

Sta ako je potrebno odrediti sve proste brojeve iz segmenta [1, n]? Najjednostavniji pristup je zasvaki broj i ∈ [1, n] proveriti da li je prost koristeci algoritam iz prethodnog problema slozenostiO(√i) - ukupna vremenska slozenost ovog pristupa je O(n

√n) a memorijska O(1).

Bolje resenje dobijamo Eratostenovim sitom: na pocetku ”precrtamo” broj 1 a zatim idemoredom od 2 do n i radimo sledece: ukoliko je trenutni broj i precrtan, nastavljamo dalje; u suprot-nom, zaokruzimo trenutni broj i a zatim precrtamo sve brojeve iz [2, n] koji su deljivi sa i. Kadazavrsimo i sa brojem n, tada vazi: broj x ∈ [1, n] je prost ako i samo ako je zaokruzen (a neprecrtan).

Zaista, jedini nacin da broj bude precrtan je da ga precrta neki od njegovih delilaca (vecih od1). Dakle, ukoliko broj nije precrtan i veci od 1 (dakle, zaokruzen) on mora biti prost. Iz istograzloga, svaki precrtan broj mora biti slozen (precrtao ga je neki njegov delilac > 1).

Implementacija ovog pristupa je jednostavna – umesto precrtavanja koristimo logicki niz primeduzine n ciji su svi elementi na pocetku true (neprecrtani) a precrtati i-ti broj znaci postavitiprime[i] na false. Najveci deo posla se trosi prilikom precrtavanja – kada precrtavamo brojem i,moramo precrtati brojeve 2 · i, 3 · i, . . . bni c · i, njih bni c - 12 Dakle, alogoritam sigurno ne izvrsi viseod n

1 + n2 + . . .+ n

n = n(11 + 12 + . . .+ 1

n) = Θ(n log n) operacija. Prema tome, vremenska slozenostEratostenovog sita3 je O(n log n) a memorijska O(n) zbog niza prime.

Eratosten(n)

prime[] ← true

prime[1] ← false

for i ← 2 to n do

if (prime[i] = true)

for j ← 2 to bni c do

prime[i · j] ← false

return prime[]

Solve(n)

2Zapravo manje jer mozemo krenuti od broja i · i - ostali su vec precrtani manjim brojevima.3Uz nekoliko zapacanja i poznavanja teorije brojeva, moze se pokazati da je slozenost zapravo O(n log logn).

Page 26: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 25

prime[] ← Eratosten(n)

for i ← 1 to n do

if (prime[i])

print i

NZD i NZS

Definicija 2.5 Neka su a i b celi brojevi koji nisu oba jednaka nuli. Najveci zajednicki delilac(eng. greatest common divisor) brojeva a i b, u oznaci NZD (eng. GCD) je najveci prirodanbroj koji deli i a i b.

Definicija 2.6 Neka su a i b prirodni brojevi. Najmanji zajednicki sadrzalac (eng. leastcommon multiplier) brojeva a i b, u oznaci NZS (eng. LCM) je najmanji prirodan broj kojije deljiv i sa a i sa b.

Najveci zajednicki delilac brojeva a i b oznacavacemo sa nzd(a, b), gcd(a, b) ili samo (a, b).Najmanji zajednicki sadrzalac brojeva a i b oznacavacemo sa nzs(a, b), lcm(a, b) ili samo [a, b].

Teorema 2.7 Neka su a, b, q i r (b 6= 0) celi brojevi za koje vazi a = bq+r. Tada je (a, b) = (b, r).

Dokaz. Neka je d proizvoljan zajednicki delilac brojeva a i b. Tada d | a− bq = r pa je d ujednoi zajednicki delilac brojeva b i r. Iz iste relacije (a = bq + r) sledi i da je svaki zajednicki delilacbrojeva b i r ujedno i zajednicki delilac brojeva a i b. Dakle, (konacni) skupovi zajednickih delilacabrojeva a i b i brojeva b i r su jednaki pa su im jednaki i najveci elementi, tj. (a, b) = (b, r).

Prethodna teorema najcesce se primenjuje kada je q kolicnik a r ostatak celobrojnog deljenjabroja a bojem b i predstavlja osnovu sledeceg (Euklidovog) algoritma za racunanje gcd(a, b):

gcd(a, b)

if (b = 0)

return a

else

return gcd(b, a mod b)

Teorema 2.8 (Euklidov algoritam) Za prirodne brojeve a i b, Euklidov algoritam vraca gcd(a, b)i radi u slozenosti O(log mina, b).

Dokaz. Kako je a = (a div b) · b + (a mod b), na osnovu Teoreme 2.7 vazi gcd(a, b) = gcd(b, amod b). Algoritam je konacan jer se prvi argument stalno smanjuje (a mod b < b) i vazi gcd(n, 0) =n za svaki prirodan broj n.

Ukoliko je a < b u prvom koraku algoritma dolazi do zamene ovih vrednosti; pretpostavimo daje a ≥ b. Ukoliko je b ≤ a/2 tada je a mod b < b ≤ a/2; u suprotnom (b > a/2) vazi a mod b =a− b < a/2. Dokazali smo da je a mod b < a/2 pa se argumeti funkcije gcd ”prepolovljavaju” nasvaka dva poziva odakle sledi da je slozenost ovog algoritma logaritamska.

Teorema 2.9 Neka su a i b prirodni brojevi. Tada vazi (a, b) · [a, b] = ab.

Jedna od posledica ove teoreme je da ako znamo algoritam za racunanje (a, b), tada u istojslozenosti mozemo izracunati i [a, b] jer je [a, b] = ab

(a,b) .

Page 27: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 26

Korisne teoreme iz teorije brojeva

Teorema 2.10 (Teorema o prostim brojevima) Oznacimo sa π(x) broj prostih brojeva man-jih ili jednakih od x. Tada vazi

π(x) ∼ x

log x.

Posledica 2.11 Oznacimo sa π(n) broj prostih brojeva manjih ili jednakih od n i oznacimo n-tiprost broj sa pn. Tada vazi:

• π(n) = Θ( nlogn),

• pn = Θ(n log n).

Ovo nam daje nacin za precizniju analizu algoritama - npr. ukoliko treba izracunati n-ti prostbroj a mi to radimo tako sto proveravamo svaki broj od 1 i povecavamo brojac, sada znamo dacemo proveriti Θ(n log n) brojeva pa to mozemo pomnoziti sa slozenoscu provere. Jos jedan primer:ako je potrebno pamtiti sve proste brojeve manje do n, jasno je da ce nam trebati O(n) memorijeali sada imamo precizniju procenu - trebace nam svega Θ( n

logn) memorije.

Teorema 2.12 (Mala Fermaova teorema) Neka je a prirodan broj a p prost broj koji ne delia. Tada vazi4

ap−1 ≡p 1.

4Ova teorema je specialan slucaj Ojlerove teoreme: ako su a i n uzajamno prosti prirodni brojevi tada je aφ(n) ≡n 1.

Page 28: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 27

2.2 Zadaci

Zadatak 1. Prirodan broj zovemo poluprost ukoliko je jednak proizvodu dva (ne nuzno razlicita)prosta broja. Ispitati da li je dati prirodan broj n poluprost. Trazi se resenje vremenske slozenostiO(√n).

Ulaz Izlazn = 65 DA

Zadatak 2. Ispitati da li se dati prirodan broj n moze predstaviti kao zbir dva slozena broja.Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 29 DA

(npr. 21 + 8)

Zadatak 3. Programer Pera tvrdi da moze uraditi prethodni zadatak u slozenosti O(1). Da lividite kako? Da li je moguce odrediti koliko ima prirodnih brojeva izmedu 1 i n koji se mogupredstaviti kao zbir dva slozena broja u slozenosti O(1)?

Zadatak 4. Za dati prirodan broj n, naci sve parove prostih brojeva (A,B) za koje je A ≤ B iA+B je prost broj ne veci od n. Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 8 (2, 3)

(2, 5)

Zadatak 5. Za prirodan broj definisimo njegovu trivijalnost kao kolicnik zbira njegovih pozitivnihdelioca (ne ukljucujuci njega) i njega samog. Npr. trivijalnost broja 12 je 1+2+3+4+6

12 ≈ 1.33. Datje prirodan broj n.

a) Izracunati trivijalnost broja n.

b) Odrediti broj iz segmenta [1, n] cija je trivijalnost najmanja.

Za deo a) trazi se resenje vremenske slozenosti O(√n), a za deo b) resenje vremenske slozenosti

O(n log n).

Ulaz Izlazn = 8 a) 0.875

b) 7

Zadatak 6. Ispitati da li se dati prirodan broj n moze predstaviti kao proizvod dva potpunakvadrata veca od 1. Trazi se resenje vremenske slozenosti O( 4

√n).

Ulaz Izlazn = 144 DA

(Npr. 144 = 22 · 62)

Zadatak 7. Pera ima gomilu novcanica u vrednosti od x dinara a Mika ima gomilu novcanicau vrednosti od y dinara. Svako zeli da sa svoje gomile uzme odredeni broj novcanica tako da nakraju obojica imaju isti iznos a da su ukupno uzeli najmanji moguci broj novcanica. Odrediti taj

Page 29: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 28

najmanji moguci broj. Trazi se resenje vremenske slozenosti O(log min(x, y)).

Ulaz Izlazx = 6 y = 4 5

(Pera uzme dve a Mika tri novcanice)

Zadatak 8. Dat je skup S prirodnih brojeva od 1 do n kao i prirodni brojevi a, b ≤ n. Svaki brojiz S koji je deljiv sa a treba ofarbati u plavo a svaki broj iz S koji je deljiv sa b treba ofarbati ucrveno. Brojevi koji su deljivi i sa a i sa b mozemo ofarbati po izboru (plavo ili crveno). Za svakiplavi ofarbani broj dobijamo p cokoladica a za svaki crveni ofarbani broj dobijamo q cokoladica.Koliko najvise cokoladica mozemo dobiti? Trazi se resenje vremenske slozenosti O(log n).

Ulaz Izlazn = 20 a = 2 b = 3

p = 3 q = 5

51

Zadatak 9. Za date prirodne brojeve n i m (n+ 3 ≤ m) napraviti permutaciju prirodnih brojevaod n do m tako da zbir svaka dva uzastopna broja u toj permutaciji bude slozen broj ili detekto-vati da to nije moguce. Ukoliko ima vise resenja, stampati bilo koje. Trazi se resenje vremenskeslozenosti O(m− n).

Ulaz Izlazn = 4 m = 9 5 7 8 4 6 9

Zadatak 10. Programer Pera tvrdi da se u algoritmu Eratostenovog sita u prvoj for petlji (po i)gornja granica moze smanjiti sa n na

√n kao i da se u drugoj for petlji (po j) donja granica moze

povecati sa 2 na i i da ce nakon toga algoritam i dalje raditi korektno. Da li je Pera u pravu? Dali gornja granica u prvoj for petlji moe smanjiti na 3

√n?

Zadatak 11. Dato je n kesa bombona, u i-toj kesi je ai bombona i svi brojevi ai su iz segmenta[1,m]. Mi imamo pravo da na pocetku izaberemo prirodan broj x a zatim svake sekunde biramoneku kesu i ukoliko u njoj ima bar x bombona, uzimamo x bombona iz nje. Cilj je isprazniti svekese osim najvise jedne. Koja je najveca moguca vrednost broja x za koju je moguce ostvariti cilj?Trazi se resenje vremenske slozenosti O(n logm).Ulaz Izlazn = 4

30 12 20 18

6

Zadatak 12. Dat je niz a prirodnih brojeva duzine n cija je suma elemenata jednaka S. U jednompotezu je dozvoljeno odabrati proizvoljna dva susedna broja u nizu i zameniti ih njihovim zbirom;ovo zatim ponavljamo nad novodobijenim nizom. Primeniti odreden broj poteza tako da na krajuostane tacno k brojeva ciji je NZD najveci moguc. Trazi se resenje vremenske slozenosti O(n

√S).

Ulaz Izlazn = 6 k = 3

12 7 3 2 15 15

MaxNZD = 6

(12, 7, 3, 2, 15, 15) → (12, 10, 2,

15, 15) → (12, 10, 2, 30) → (12, 12,

30)

Page 30: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 29

2.3 Resenja

1. Broj n je poluprost ako je n = pq gde su p ≤ q prosti brojevi. Kako znamo da delioci idu uparu, vazi p ≤

√n ≤ q pa vidimo da je n poluprost ako i samo ako ima tacno jednog delioca iz

segmenta [2,√n] (to ce biti bas p). Ovo mozemo proveriti jednim prolaskom kroz taj segment pa

je vremenska slozenost algoritma O(√n) a memorijska O(1).

Solve(n)

d ← 0

for i ← 1 to b√nc do

if (n mod i = 0)

d ← d + 1

if (d = 1)

return DA

else

return NE

Jos jedno moguce resenje je faktorisati broj n (standardnim algoritmom) i proveriti da li je brojprostih faktora jednak 2 i da li su oba eksponenta jednaka 1. Vremenska i memorijska slozenostovog pristupa su iste kao i za prethodni algoritam.5

2. Najjednostavniji nacin je proci kroz sve mogucnosti za predstavljanje broja n kao zbir dvaprirodna broja (1 + (n − 1), 2 + (n − 2), . . ., bn2 c + dn2 e) i za svaku od njih ispitati da li su obasabirka slozeni brojevi (standardnim

√n algoritmom). Ukoliko naidemo na bar jedan takav par,

vracamo DA a inace NE. Vremenska slozenost ovog pristupa je O(n√n) jer imamo O(n) parova

i nijedan broj nije veci od n pa je slozenost ispitivanje da li je broj prost O(√n). Memorijska

slozenost je O(1).

Solve(n)

for i ← 1 to bn2 c do

if ((not IsPrime(i)) and (not IsPrime(n - i)))

return DA

return NE

Bolje resenje je na pocetku odrediti sve proste (samim tim i slozene) brojeve iz segmenta [1, n]koristeci Eratostenovo sito i formiranjem logickog niza prime[]. Sada proveru da li je dati brojx prost mozemo odraditi u slozenosti O(1) (”if prime[x] ...”) pa je ukupna vremenska slozenostjednaka O(n log n) zbog Eratostenovog sita. Memorijska slozenos je O(n).

SolveFaster(n)

prime[] ← Eratosten(n)

for i ← 1 to bn2 c do

if ((not prime[i])) and (not prime[n - i]))

return DA

return NE

3. TODO

4. Trivijalno resenje je ispitati sve moguce parove (A,B) (njih O(n2)) i za svaki od njih proveritida li su A, B i A + B prosti. Svaku proveru mozemo odraditi na klasican nacin u O(

√n) (jer su

5Iako je memorijska slozenost faktorizacije O(logn) mi mozemo prekinuti algoritam kada vidimo da nam trebajubar 3 prosta faktora.

Page 31: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 30

sva tri broja ne veca od n) sto daje ukupnu vremensku slozenost od O(n2√n) dok je memorijska

slozenost O(1).Ovo mozemo ubrzati tako sto prvo odradimo Eratostenovo sito na brojeve iz [1, n] pa na osnovu

dobijenog logickog niza prime mozemo u O(1) proveriti da li je neki broj x ∈ [1, n] prost ili ne (ifprime[x] = true). Sada je vremenska slozenost algoritma O(n log n) (Eratosten) + O(n2) (proveraza svaki par) = O(n2)6 dok je memorijska O(n).

Mnogo bolja slozenost se postize jednostavnim zapazanjem: ako su A i B prosti brojevi veci od2, tada su oba neparna pa im je zbir paran broj veci od 2 sto znaci da tada A + B ne moze bitiprost broj. Dakle, jedini kandidati za (A,B) su A = 2 i B = neki prost broj. Prema tome, sadasamo treba proveriti sve mogucnosti za B (njih O(n)) i za svaki izbor broja B proveriti (u O(1)posle Eratostenovog sita) da li su B i B + 2 prosti brojevi. U ovom slucaju, slozenoscu algoritmadominira Eratostenovo sito pa su vremenska i memorijska slozenost O(n log n) i O(n), redom.

Solve(n)

prime[] ← Eratosten(n)

for B ← 3 to n - 2 (* jer A + B = 2 + B ne sme biti vece od n *)

if (prime[B] and prime[B + 2])

print (2, B)

5. TODO

6. Ukoliko se n moze predstaviti kao proizvod dva potpuna kvadrata veca od 1, sledi da je n = x2y2

za neke prirodne brojeve x > 1 i y > 1. Bez umanjenja opstosti, neka je x ≤ y. Sledi x4 ≤ x2y2 = npa je x ≤ 4

√n. Dakle, dovoljno je ispitati sve prirodne brojeve iz [2, 4

√n] za x i (u O(1)) proveriti

da li je nx2

potpun kvdadrat7). Vremenska slozenost ovog pristupa je O( 4√n) a memorijska O(1).

Solve(n)

for x ← 2 to b 4√nc do

y ← n / x2

if (b√yc · b√yc = y)

return "DA"

return "NE"

Moglo je i malo drugacije – na osnovu diskusije iz prvog dela, vidimo da n zadovoljava dati uslovako i samo ako je potpun kvadrat i

√n nije prost broj (jer n = x2y2 = (xy)2). Dakle, dovoljno je

prvo proveriti da li je n potpun kvadrat (tj. da li je√n ceo broj) a zatim da li je

√n prost sto

mozemo odradit u O(√√

n) = O( 4√n).

7. Pretpostavimo da u optimalnom resenju na kraju obojica imaju po n dinara. Tada x | n i y | n.Pera je uzeo n

x svojih novcanica a Mika ny svojih novcanica. Da bi vrednost n

x+ny = n( 1x+ 1

y ) (ukupanbroj uzetih novcanica) bila minimalna, potrebno je minimizirati n jer su x i y fiksni brojevi. Dakle,treba nam najmanji prirodan broj n koji je deljiv i sa x i sa y a to je upravo najmanji zajednickisadrzalac za brojeve x i y koji umemo da odredimo na osnovu Euklidovog algoritma i Teoreme 2.9u slozenosti O(log minx, y) (uz memorijsku slozenost O(1)).

Solve(x, y)

6I ovde mozemo postici malo bolju slozenost: ukoliko nakon Eratostenovog sita izdvojimo sve proste brojeve iz[1, n] u jedan poseban niz, taj niz ce na osnovu posledice Teoreme o prostim brojevima imati Θ( n

logn) elemenata.

Pametnije je da parove (A,B) trazimo samo u okviru ovog novog niza (jer su tu samo prosti brojevi koji nam i

trebaju) pa tada imamo O( n2

log2 n) parova za proveru sto je i slozenost naseg algoritma.

7Podsetimo se da operacije√x i bxc smatramo osnovnim.

Page 32: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 31

n ← (x / gcd(x, y)) · yreturn n/x + n/y

8. TODO

9. TODO

10. TODO

11. TODO

12. Zadatak je ekvivalentan sa: naci najveci broj x (to je trazeni NZD) tako da je moguce podelitiniz a na k uzastopnih podnizova tako da x deli sumu svakog od njih.

Za pocetak, x je u segmentu [1, S] i mozemo ispitati svaku od tih vrednosti. Za fiksirano x,najvise nam se isplati da sabiramo sve brojeve od pocetka sve dok nam suma ne bude deljiva sax; to ce nam biti prvi podniz. Zatim krenemo od narednog elementa i sabiramo sve brojeve doksuma opet ne bude deljiva sa x - to ce biti drugi podniz itd. Ukoliko smo na ovaj nacin dobilibar k podnizova, x je potencijalno resenje (mozemo spojiti neke podnizove ako ih ima vise od k);u suprotnom x ne moze biti resenje (zasto?). Na kraju uzimamo najvece potencijalno resenje.Dakle, S mogucnosti i prolazak kroz ceo niz za svaku proveru - vremenska slozenost je O(S · n) amemorijska O(1).

Ovo mozemo jos ubrzati - primetimo da ako x deli sumu svakog podniza onda x deli i sumusuma svih podnizova tj. x | S. Dakle, ne treba ispitivati sve brojeve iz [1, S] vec samo deliocebroja S. Kako smo ranije pokazali da je broj delioca prirodnog broja n ne veci od 2

√n, sledi da

S ima O(√S) delilaca. Dakle, ovo zapazanje ubrzava prethodni algoritam pa dobijamo vremensku

slozenost O(n ·√S) i memorijsku O(1).

Page 33: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 3

Podeli pa vladaj

3.1 Teorija

Strategija podeli–pa–vladaj se sastoji u sledecem:

• Podeliti dati problem na nekoliko delova/potproblema pri cemu je svaki deo zapravo samomanja instanca originalnog problema (tj. predstavlja isti tip problema samo sa manjimogranicenjima)

• Rekurzivno resiti te potprobleme

• Iskoristiti i iskombinovati resenja potproblema u cilju dobijanja resenja polaznog problema

U prethodnom opisu, rekurzija se tipicno zavrsava kada dodemo do potproblema konstantnevelicine (najcesce velicine 1). Ponekad nije potrebno resavati sve potprobleme, vec samo neke odnjih. Nacin podele problema i kombinovanja potproblema, jasno, zavisi od samog tipa problema.1

U (prilicno) opstem slucaju, mozemo zamisliti da je originalni problem velicine n i da ga usvakom rekurzivnom koraku delimo na a potproblema priblizno jednakih velicina n

b , resavamo ih,a zatim te probleme kombinujemo u slozenosti O(f(n)). Obratiti paznju da ne mora vaziti a = b(iako je to ”najprirodnije”) – potproblemi mogu da se (delimicno) preklapaju pa ne mora da vazida je broj problema (a) · velicina potproblema (nb ) = velicina problema (n); cak i da su potproblemidisjunktni, mozda se problem zaista sastoji od b priblizno jednakih potproblema velicine n

b ali daje nama bilo dovoljno da resavamo samo a njih.

Ukoliko sa T (n) oznacimo vremensku slozenost prethodno opisanog podeli–pa–vladaj metoda,tada vazi

T (n) = aT(nb

)+O(f(n)).

Za resavanje jednacina ovog tipa, koristimo takozvanu Master Teoremu koju prvo dajemo u opstijem(ali i komplikovanijem) obliku a zatim i njen specijalan slucaj koji ce nam uglavnom biti dovoljan.

Teorema 3.1 (Master Teorema) Neka su a ≥ 1 i b > 1 realne konstante, f(n) nenegativnafunkcija i T (n) funkcija definisana na skupu N0 rekurentnom jednacinom T (n) = aT (nb )+f(n) gdese vrednost n

b interpretira kao bnb c ili dnb e. Tada vazi:

• Ako je f(n) = O(nlogb a−ε) za neku konstantu ε > 0, tada je T (n) = Θ(nlogb a).

• Ako je f(n) = Θ(nlogb a), tada je T (n) = Θ(nlogb a log n).

• Ako je f(n) = Ω(nlogb a+ε) za neku konstantu ε > 0 i ako je af(nb ) ≤ cf(n) za neku konstantuc < 1 i za sve dovoljno velike n, tada je T (n) = Θ(f(n)).

1Naravno, pod uslovom da je problem uopste moguce resiti ovom metodom.

32

Page 34: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 33

U svakom od slucajeva iz Master Teoreme uporeduju se vrednosti f(n) (slozenost kombinovanjapotproblema) i nlogb a (broj ”zavrsnih” potproblema i ujedno red velicine ukupnog broja potprob-lema). Intuitivno, veca od ovih vrednosti je slozenost algoritma a u slucaju da su istog reda velicine(slucaj 2), mnoze se logaritamskim faktorom.

Najcesce je f(n) oblika nd za neko d ≥ 0 i u tom slucaju je Master Teorema znacajno jednos-tavnija.

Teorema 3.2 (Master Teorema – specijalan slucaj) Neka su a ≥ 1, b > 1 i d ≥ 0 realnekonstante i T (n) funkcija definisana na skupu N0 za koju vazi T (n) = aT (nb ) + O(nd) gde sevrednost n

b interpretira kao bnb c ili dnb e. Tada vazi:

• Ako je d < logb a, tada je T (n) = O(nlogb a).

• Ako je d = logb a, tada je T (n) = O(nd log n).

• Ako je d > logb a, tada je T (n) = O(nd).

Klasican primer primene metoda podeli–pa–vladaj je Merge Sort – algoritam za sortiranje kojiradi tako sto podeli niz na dva jednaka dela (prvih n

2 i drugih n2 elemenata), rekurzivno ih sortira a

zatim ”pametno” spaja dva soritrana niza u slozenosti O(n). Rekurentna jednacina za Merge Sortje T (n) = 2T (n2 ) +O(n) pa je na osnovu Master Teoreme njegova slozenost T (n) = O(n log n).

Binarna pretraga

Centralni deo ovog poglavlja je binarna pretraga. Osnovna ideja binarne pretrage je podelaprostora pretrage na dva (priblizno) jednaka dela a zatim odbacivanjem jednog od njih (najcescepostavljanjem jednog upita, tj. u slozenosti O(1)). Ovim se prostor pretrage efektivno prepolovljavasve dok ne dodjemo do jednog elementa (ili ”dovoljno malog” problema).

Problem 3.3 Dat je neopadajuce soritrani niz a realnih brojeva duzine n i broj x. Proveritida li se broj x nalazi u nizu a i ukoliko se nalazi, vratiti indeks i za koji vazi ai = x (ukoliko ih imavise, vratiti bilo koji).

Trivijalan pristup je obicno pretrazivanje proverom svakog elementa cija je slozenost O(n) aliovaj pristup ne koristi cinjenicu da je niz sortiran. Pametniji pristup je da prvo uporedimo xsa ”srednjim” elementom niza a, tj. sa am gde je m = bn2 c. Ukoliko je x = am, zavrsili smo; usuprotnom, ako je x < am znamo da x sigurno ne moze biti u delu niza a[m+1 . . . n] pa odbacujemopolovinu niza i pretragu nastavljamo u prvoj polovini niza, tj. u delu a[1 . . .m−1]; analogno, ako jex > am, tada nastavljamo pretragu u drugoj polovini niza, tj. u delu a[m+1 . . . n]. U odgovarajucimpolovinama ponavljamo isti postupak - u opstem slucaju smo u delu niza [l, r] a zatim prelazimona deo [l, b l+r2 c − 1] ili [b l+r2 c+ 1, r].

BinSearch(n, a[], x) (* ne-rekurzivna verzija *)

l ← 1

r ← n

while (l ≤ r) do

m ← b l+r2 c

if (a[m] = x)

return m

if (x < a[m])

r = m - 1

else

l = m + 1

Page 35: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 34

return -1

Slozenost binarne pretrage je O(log n) jer u svakom koraku prepolovljavamo duzinu prostorapretrage koja je na pocetku n; dakle, u najgorem slucaju cemo izvrsiti Θ(log n) koraka a kako jesvaki konstantne slozenosti, ukupna slozensot je O(log n).2

Binarna pretraga se cesce implementira rekurzivno gde se kao parametri zadaju leva i desnagranica pretrage (indeksi u nizu) - ukoliko zelimo da pretrazujemo ceo niz, pretragu treba pozvatisa parametrima l = 1 i r = n:

BinSearch(l, r, a[], x) (* rekurzivna verzija *)

if (l > r)

return -1;

m ← b l+r2 c

if (a[m] = x)

return m

if (x < a[m])

return BinSearch(l, m - 1, a, x)

else

return BinSearch(m + 1, r, a, x)

Teorema 3.4 (Optimalnost binarne pretrage) Svaki algoritam koji resava Problem 3.3 i kojise bazi iskljucivo na poredenjima (tj. upitima oblika ”uporedi x sa i-tim elementom niza a”) jeslozenosti Ω(log n).

Problem 3.3 cesto ide u razlicitim oblicima gde nije nuzno naci bas element koji je jedank brojux vec neki ”njemu priblizan” - npr. problem moze glasiti:

Problem 3.5 Dat je neopadajuce soritrani niz a realnih brojeva duzine n i broj x. Pronacielement sa najvecim indeksom koji je strogo manji od datog broja x (ili ustanoviti da takav elementne postoji).

Ovakvi problemi se resavaju u istoj slozenosti (O(log n)) neznatnom modifikacijom binarnepretrage. Jedan od nacina je sledeci:

BinSearchRightmostSmaller(l, r, a[], x) (* pod pretpostavkom da resenje postoji *)

if (l = r)

return l;

m ← d l+r2 e (* obratiti paznju na "gornji" ceo deo *)

if (a[m] < x)

return BinSearchRightmostSmaller(m, r, a, x)

els

return BinSearchRightmostSmaller(l, m - 1, a, x)

Solve(n, a[], x) (* "Glavna" funkcija *)

if (x ≤ a[1]) (* resenje ne postoji *)

return -1

else

return BinSearchRightmostSmaller(1, n, a, x)

2Mogli smo pokazati i drugacije: neka je T (n) slozenost binarne pretrage za niz od n elemenata. Kako u svakomkoraku odbacujemo polovinu niza i vrsimo jedno poredenje, vazi rekurentna jednacina T (n) = T (n

2) + O(1), cije je

resenje, prema Master Teoremi, dato sa T (n) = O(logn).

Page 36: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 35

3.2 Zadaci

Zadatak 1. Implementirati (sto efikasnije) proceduru Merge(A,B) koja spaja dva sortirana nizaA i B duzine n i m (i vraca novi niz). Kako spojiti 4 niza duzine n? A k nizova duzine n? Odreditislozenost algoritma i iskoristiti analizu za dizajn Merge–Sorta.

Zadatak 2. Dat je celobrojni niz a duzine n. Odrediti uzastopni podniz niza a sa najvecom sumomsvojih elemenata (stampati sumu) koristeci metod podeli–pa–vladaj u slozenosti O(n log n).3

Ulaz Izlazn = 7

1 5 -10 5 -2 6 -4

9

(od 4. do 6. pozicije)

Zadatak 3. Odrediti broj inverzija u datoj permutaciji p prirodnih brojeva od 1 do n. Pod inverz-ijom podrazumevamo uredeni par (pi, pj) za koji vazi i < j i pi > pj . Trazi se resenje vremenskeslozenosti O(n log n). Hint: modifikovati Merge–Sort.

Ulaz Izlazn = 5

3 5 1 4 2

6

(npr. jednu od 6 inverzija cini par

(p2, p3))

Zadatak 4. Programer Pera je uocio slicnost izmedu poslednjeg zadatka (3.) i zadatka 6 iz prveglave i misli da moze da uradi zadatak 6 iz prve glave u slozenosti O(n log n) koristeci resenjeZadatka 7 tako sto izvrsi ”renumeraciju” ucenika tako da prvi niz izgleda 1, 2, . . . , n a zatim odsvih mogucih parova oduzme broj inverzija u (renumerisanom) drugom nizu. Da li je Pera u pravu?

Zadatak 5. Za date prirodne brojeve a, n,m, izracunati an mod m. Trazi se resenje vremenskeslozenosti O(log n).

Ulaz Izlaza = 7 n = 8 m = 1000 801 (tj. 5764801 mod 1000)

Zadatak 6. U resenju problema 3.5 (u neopadajuce sortiranom nizu pronaci element sa najvecimindeksom koji je strogo manji od datog broja x) je u funkciji BinSearchRightmostSmaller koriscen”gornji” ceo deo u naredbi m← d l+r2 e. Programer Pera tvrdi da ovu liniju mozemo zameti sa m←b l+r2 c (tj. koristiti obican donji ceo deo) i da ce kod i dalje biti ispravan. Da li je Pera u pravu?

Zadatak 7. U nizu je, prema visini, poredano n ucenika, od najnizeg do najviseg. U zadatomredosledu dolaze jos m ucenika i treba ih ubaciti u niz. Za i-tog pridoslog ucenika treba naci ucenikau nizu sa najvecim indeksom cija je visina strogo manja od visine i-tog pridoslog ucenika, izbacitiga, i na njegovo mesto ubaciti pridoslog ucenika (ukoliko takav ucenik ne postoji, pridosli ucenikne ulazi u red). Stampati niz posle dolaska svih ucenika. Trazi se resenje vremenske slozenostiO(m log n).

3Podsetimo se da smo ranije uradili ovaj zadatak u boljoj slozenosti.

Page 37: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 36

Ulaz Izlazn = 5

150 160 160 165 180

m = 6

170 155 162 163 210 160

160 160 163 170 210

Zadatak 8. Dat je niz razlicitih realnih brojeva a duzine n. Element niza se naziva vrh ako je veciod svojih susednih elemenata (za 1 < i < n susedi elementu ai su ai−i i ai+1; a1 i an imaju samopo jednog suseda). Stampati indeks elementa koji je vrh u ovom nizu ili ’-1’ ako takav element nepostoji. Ukoliko ima vise resenja, stampati bilo koje. Trazi se resenje vremenske slozenosti O(log n).

Ulaz Izlazn = 8

2 3 5 4 1 6 7 10

3

(tj. a[3] = 5; resenje je i a[8] = 10)

Zadatak 9. Dva drugara treba da plate racun od k dinara. Prvi ima n novcanica u vrednosti oda1 ≤ a2 ≤ . . . ≤ an dinara a drugi ima m novcanica u vrednosti od b1 ≤ b2 ≤ . . . ≤ bm dinara(nizovi novcanica su sortirani neopadajuce). Da li je moguce da plate tacan iznos racuna tako stoce svako od njih dati po jednu novcanicu (ispisati koje je novcanice potrebno dati ili -1 ako je tonemoguce)? Trazi se resenje vremenske slozenosti O(n+m).

Ulaz Izlazn = 4 m = 3 k = 100

a = (2, 10, 17, 90)

b = (83, 91, 100)

DA

17 + 83

Zadatak 10. Igraonica radi n sekundi dnevno i da bi igrac mogao da se igra u i-toj sekundi,on mora da plati ci ≥ 0 dinara. Jednog dana igaonicu je posetilo m igraca. Za svakog igraca jepoznato ti - sekunda u kojoj je dosao i pi - kolicina para koju poseduje. Za svakog od njih odreditikoliko najvise uzastopnih sekundi, pocevsi od sekunde u kojoj je stigao, moze da se igra. Trazi seresenje vremenske slozenosti O(n+m log n).

Ulaz Izlazn = 8 m = 3

c: 4 3 10 20 2 0 0 1

(t1, p1) = (3, 32)

(t2, p2) = (3, 34)

(t3, p3) = (2, 1)

5

6

0

Zadatak 11. Dato je n duzi svojim duzinama di > 0. Sve duzine su razlicite i sortirane su rastuce.Izracunati koliko razlicitih trouglova mozemo napraviti pomocu datih duzi. Trazi se resenje vre-menske slozenosti O(n2 log n).

Ulaz Izlazn = 4

2 3 4 6

2

Zadatak 12. Programer Pera je imao sortirani niz a razlicitih brojeva duzine n (a1 < a2 <. . . < an) a zatim ga je ciklicno rotirao za nekoliko pozicija ulevo i dobio novi niz b koji izgledab = (ak, ak+1, . . . , an, a1, a2, . . . , ak−1). Medutim, zaboravio je vrednost k (tj. za koliko pozicija jerotirao niz) i sada treba da proveri da li se dati broj x nalazi u nizu b. Pomozite mu da ovo uradi

Page 38: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 37

u vremenskoj slozenosti O(log n).

Ulaz Izlazn = 4

2 3 4 6

2

Zadatak 13. Za dati prirodan broj n odrediti njegov kvadratni koren (pretpostaviti da je n pot-pun kvadrat) koristeci samo osnovne aritmeticke operacije (bez koriscenja operacije korenovanja).Trazi se resenje vremenske slozenosti O(log n).

Ulaz Izlazn = 237169 487

Zadatak 14. Dato je n tacaka na x-osi svojim celobrojnim koordinatama xi. Od njih treba iz-abrati k (k < n) tacaka tako da dve najblize od izabranih tacaka budu sto udaljenije (stampatiudaljenost dve najblize tacke). Preptostaviti da su tacke sortirane po x-koordinati. Trazi se resenjevremenske slozenosti O(n log |xn − x1|).

Ulaz Izlazn = 5 k = 3

2 5 10 20 50

18 (za izbor 2, 20, 50)

Zadatak 15. Programer Pera je lenj programer. Prvog dana napise x linija koda. Drugog dananapise jos bxk c linija koda. Treceg dana napise jos b x

k2c linija, cetvrtog jos b x

k3c itd. svakog dana

optrilike k puta manje (”otprilike” zbog celog dela). Ako je potrebno da napise ukupno bar n linijakoda i poznata je vrednost k, koliko najmanje linija koda Pera mora napisati prvog dana? Trazi seresenje vremenske slozenosti O(log2 n).

Ulaz Izlazn = 7 k = 2 4

Zadatak 16. U matrici dimenzije n ×m redovi su numerisani od 1 do n, kolone od 1 do m a napoziciji (i, j) se nalazi broj i · j. Stampati k-ti po velicini broj u matrici (1 ≤ k ≤ nm). Trazi seresenje vremenske slozenosti O(minn,m · log(nm)).

Ulaz Izlazn = 2 m = 3 k = 4 3

Zadatak 17. Dat je niz prirodnih brojeva a duzine n (neka je suma svih elemenata ovog niza jed-naka S). Podeliti ovaj niz na tacno k uzastopnih podnizova tako da je maksimum medu sumamaelemenata u podnizovima - minimalan moguc (stampati trazeni minimum). Trazi se resenje vre-menske slozenosti O(n logS).

Ulaz Izlazn = 9 k = 3

10 50 40 30 20 60 70 90 80

170

| 10 50 40 30 20 | 60 70 | 90 80 |

Zadatak 18. Dato je n burica i u svakom se nalazi odredena kolicina vode (u i-tom ai litara).Mozemo probusiti ukupno m rupa na dnima burica, pri cemu kroz svaku probusenu rupu izlazi1 litar vode u sekundi. Sve rupe busimo istovremeno i zelimo da ih probusimo tako da sva vodaistece sto pre. Odrediti koje je minimalno vreme posle koga ni u jednom buretu nece biti vode.

Page 39: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 38

Stampati resenje sa preciznoscu ε (npr. za ε = 10−2, resenje treba stampati sa preciznosucu na dvedecimale). Trazi se resenje vremenske slozenosti O(n log(ε−1 max ai)).

Ulaz Izlazn = 3 m = 9 ε = 0.016 10 2

2.00

Page 40: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 39

3.3 Resenja

1. Neka su duzine nizova A i B, redom, n i m. U svakom koraku uzimamo najmanji elementmedu prvim elementima nizova A i B, izbacujemo ga iz odgovarajuceg niza i ubacimo ga u noviniz. Svaki korak je slozenosti O(1) jer su nizovi sortirani - ukupna slozenost je O(n + m) (trebanam i toliko memorije za novi niz). Slabije resenje bi bilo nadovezati niz B na niz A i sortirati ceoniz bez ikakvih dodatnih pretpostavki.

Kada imamo vise nizova, najoptimalnije je spajati ih u parovima (”dva po dva”), zatim novodobi-jene nizove spajati po istom principu dok ne ostane samo jedan. Slozenost ovoga je O(nk log k)jer izvrsimo log k faza spajanja ”dva po dva” (u svakoj fazi se broj nizova duplo smanji) a ukupnaduzina nizova je nk i tolika je slozenost svih spajanja u jednoj fazi. Ovo je zapravo MergeSort zaniz velicine nk ali od trenutka kada smo dosli do faze gde su grupe velicine k.

Najgori nacin spajanja nizova bi bio prvi i drugi, zatim novodobijeni i treci, zatim novodobijenii cetvrti itd. Kolika je slozenost ovog postupka?

2. Posmatrajmo dati niz a duzine n i neka je m = n2 . Posmatrajmo dva njegova podniza a[1,m]

i a[m + 1, n]. Trazeno resenje (uzastopni podniz sa najvecom sumom elemenata) se nalazi ilikompletno u podnizu a[1,m] ili kompletno u podnizu a[m + 1, n] ili pripada i jednom i drugompodnizu. U prva dva slucaja problem mozemo resiti rekurzivno (sa duplo manjim parametrom) au trecem slucaju imamo sitaciju da nam treba uzastopni podniz sa najvecom sumom koji sadrzielemente a[m] i a[m + 1]. Medutim, tada je dovoljno naci takvo i ≤ m sa osobinom da je ai +ai+1 + . . . + am najvece moguce i takvo j ≥ m + 1 sa osobinom da je am+1 + am+2 + . . . + ajnajvece moguce i podniz a[i, j] ce biti resenje za taj slucaj; ukupno resenje ce biti maksimum odtri dobijene vrednosti (po jedna za svaki od tri slucaja).

Ukoliko ovo trazenje indeksa i i j odradimo u linearnoj slozenosti, za slozenost naseg algoritmaT (n) vazice T (n) = 2T (n2 ) + O(n) pa je prema Master Teoremi T (n) = O(n log n). Memorijskaslozenost algoritma je O(n) jer imamo O(n) poziva rekurzije sa konstantnim brojema lokalnihpromenljivih.

Solve(l, r, a[]) (* nalazi resenje za podniz a[l,r]; na pocetku se poziva Solve(1,n,a) *)

if (l = r)

return a[l];

m ← b l+r2 c

sol1 ← Solve(l, m, a)

sol2 ← Solve(m+1, r, a)

leftSum ← a[m]

leftMax ← a[m]

for i ← m - 1 downto l do

leftSum ← leftSum + a[i]

leftMax ← max(leftMax, leftSum)

rightSum ← a[m + 1]

rightMax ← a[m + 1]

for i ← m + 2 to r do

rightSum ← rightSum + a[i]

rightMax ← max(rightMax, rightSum)

return max(sol1, sol2, leftMax + rightMax)

3. TODO

Page 41: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 40

4. TODO

5. Direktno mnozenje (i koriscenje operacije mod) dovodi do trivijalnog resenja slozenosti O(n).Mozemo i bolje – ideja je da ne vrsimo nepotrebna mnozenja. Npr. ako treba izracunati a20 nemoramo odraditi 20 mnozenja vec (za pocetak) samo 11; sa 10 mnozenja izracunamo x = a10 azatim a20 dobijamo uz pomoc samo jos jednog mnozenja kao x ·x. Naravno, istu pricu (rekurzivno)mozemo primeniti i na a10 i dodatno smanjiti broj mnozenja.

Implementiracemo rekurzivnu funkciju F (a, n,m) koja rauna an mod m na sledeci nacin:

• Ako je n = 0, vrati 1; inace

• Ako je n parno, vrati x2 mod m gde je x = F (a, n/2,m) tj. x = an/2 mod m;

• Ako je n neparno, vrati a · x2 mod m gde je x = F (a, (n− 1)/2,m) tj. x = a(n−1)/2 mod m.

Na osnovu rekurentne formule, algoritam je ocigledno tacan.4 Kako u svakom rekurzivnom pozivupolovimo parametar n, izvrsicemo O(log n) poziva funkcije F a to je i vremenska slozenost algo-ritma; memorijska slosenost je O(1). Vremensku slozenost smo mogli odrediti i na sledeci nacin:ukoliko je T (n) slozenost algoritma, tada ocigledno vazi T (n) = T (n2 )+O(1) pa je na osnovu MasterTeoreme T (n) = O(log n).

F(a, n, m)

if (n = 0)

return 1

if (n mod 2 = 0)

x ← F(a, n/2, m)

return x2 mod m

else

x ← F(a, (n - 1)/2, m)

return (a · x2) mod m

6. Pera nije u pravu. Nama treba indeks i takav da je ai < x ≤ ai+1 (ukoliko takav postoji,smatrati da je an+1 =∞). Zbog nesimetricnog uslova (sa leve strane ”<” a sa desne ”≤”) imamoi nesimetricno grananje u datom kodu; ako smo u segmentu [l, r] i m je ”sredisnji” element kogaposmatramo, mi nastavljamo pretragu ili u segmentu [l,m − 1] ili u segmentu [m, r]. Ovde jeproblem sto novi segment ne mora nuzno biti kraci od prethodnog.

Pretpostavimo da smo u nekom trenutku pretrage dosli do segmenta duzine 2, tj. r = l+1 i ostalisu samo brojevi al i al+1. Ukoliko koristimo ”donji” ceo deo za m, dobijamo da je m = b l+(l+1)

2 c = l.Posmatrajmo slucaj kada je al < x ≤ al+1 (tj. kada je l resenje). Na osnovu datog koda (if a[m]

< x), pretraga se nastavlja u segmentu [m, r] = [l, r] tj. u istom segmentu. Ova situacija se stalnoponavlja i algoritam ulazi u beskonacnu petlju i nikada se ne zavrsava ⇒ postoji ulaz za koji sealgoritam ne zavrsava ⇒ algoritam nije dobar.5

7. Neka je hi visina i-tog ucenika u nizu; po uslovu zadatka, ovaj niz je sortiran neopadajuce.Kada dodje prvi ucenik (neka mu je visina x), potrebno je u nizu h naci najveci indeks i takav da

4Jedan od najlaksih nacina za dokaz tacnosti rekurzivnog algoritma je matematicka indukcija.5Formalno, mi smo ”pretpostavljali” i ”posmatrali los slucaj” a nismo pokazali da se tako nesto zaista moze i

desiti; medutim, u ovom slucaju je trivijalno na osnovu objasnjenja konstruisati primer (niz) gde algoritam upada ubeskonacnu petlju.

Page 42: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 41

je hi < x ili, alternativno, naci (jedinstevni) indeks i za koji vazi hi < x ≤ hi+1 (zamislimo da jehn+1 =∞). Ovaj indeks nece postojati akko je x ≤ h1. Ono sto je jako bitno primetiti je da nakonubacivanja novog ucenika na odgovarajuce (recimo i-to) mesto, niz h i dalje ostaje sortiran jer jena osnovu gornjih nejednakosti hi−1 ≤ hi < x = h′i i h′i = x ≤ hi+1.

Trivijalan algoritam je proveravanje svakog indeksa i od 1 do n dok ne naidemo na onaj za kojivazi hi < x ≤ hi+1 (ili ako ne ustanovimo da je x ≤ h1). Ovaj algoritam je slozenosti O(nm).Bolji algoritam dobijamo tako sto koristimo cinjenicu da je niz h u svakom koraku sortiran i indeksi sa trazenom osobinom nalazimo binarnom pretragom kao u resenju Problema 3.5. Vremenskaslozenost ovog pristupa je O(m log n) jer radimo m binarnih pretraga nad nizom duzine n, dok jememorijska slozenost O(1).

Solve(n, h[], m, x[])

for i ← 1 to m do

if (x[i] > h[1]) (* ukoliko ovo ne vazi, i-ti ucenik se ne ubacuje *)

ind ← BinSearchRightmostSmaller(1, n, h, x[i])

h[ind] ← x[i]

return h[]

8. Jasno je da problem mozemo resiti u slozenosti O(n) tako sto svaki element uporedimo sa svojimsusedima. Ovde je jako bitno jedno trivijalno zapazanje: svaki niz razlicitih elemenata sadrzi barjedan vrh - jedan od vrhova je sigurno najveci element u nizu. Uz ovo zapazanje mozemo primenitistrategiju podeli-pa-vladaj i dizajnirati jos jednu verziju binarne pretrage.

Neka je m ”srednja” pozicija u nizu. Ukoliko je am−1 < am i am > am+1 element am je vrhi zavrsili smo. U suprotnom (svi elemnti su razliciti) vazi am−1 > am ili am < am+1 (ili obenejednakosti). Neka je am−1 > am. Kljucno zapazanje je da iz ove nejednakosti sledi da podniza[1,m− 1] sigurno sadrzi vrh. Zaista, najveci element ovog podniza je sigurno vrh – cak i da je toam−1 njemu ”ne smeta” am jer vazi am−1 > am. Slicno vazi i u drugom slucaju. Dakle, u svakomkoraku mozemo odbaciti polovinu niza i ponavljati sve dok ne naidemo na vrh. Princip je isti kaoi kod binarne pretrage pa je vremenska slozenost O(log n) a memorijska O(1).

Solve(n, a[], x)

if (a[1] > a[2])

return 1

if (a[n] > a[n-1])

return n

l ← 2

r ← n - 1

while (true) do

m ← b l+r2 c

if (a[m-1] < a[m] and a[m] > a[m + 1])

return m

if (a[m-1] > a[m])

r ← m - 1

else

l ← m + 1

9. TODO

Page 43: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 42

10. TODO

11. TODO

12. TODO

13. Najtrivijalniji pristup je da za svako i = 1, 2, 3, . . . proveravamo da li je i · i = n i ukoliko jesteda prekinemo algoritam i vratimo tu vrednost. Slozenost ovog pristupa je O(

√n) jer prekidamo

kada nademo koren (iako ne znamo tacnu vrednost korena).

Sa druge strane, mozemo raditi binarnu pretragu po resenju. Na pocetku znamo da jekvadratni koren (resenje) negde na segmentu [1, n] (n kandidata). Uzmemo srednji broj (x = b1+n2 c)i proverimo da li je x2 = n. Ukoliko jeste, zavrsili smo; ukoliko je x2 < n, resenje treba trazitina segmentu [x + 1, n] a ukoliko je x2 > n, resenje treba traziti na segmentu [1, x − 1]. Zatim sepostupak ponavlja na manjim segmentima (uzima se srednji broj itd). U svakom koraku se velicinasegmenta prepolovi pa pravimo O(log n) koraka sto je i vremenska slozenost algoritma; memorijskaje O(1).

Solve(n)

l ← 1

r ← n

while (true) do

m ← b l+r2 c

if (m · m = n)

return m

if (m · m < n)

l ← m + 1

else

r ← m - 1

14. TODO

15. Oznacimo sa F (x) ukupan broj linija koda koje ce napisati Pera ako prvog dana napise xlinija. Koristicemo binarnu pretragu po resenju. Pretpostavimo da proveravamo da li je broj mpotencijalno resenje – za pocetak treba izracunati F (m) a ovo mozemo izracunati direktno poformuli. Racunanje se zavrsava kada ki postane vece od m a to ce se desiti za i = Θ(logkm) =Θ(logm) pa nam svega toliko koraka treba. Kako je F (m) neopadajuca funkcija, ako vazi F (m) < nsledi da je resenje sigurno vece od m a ukoliko je F (m) ≥ n znamo da je resenje manje ili jednakood m. Dakle, ispunjeni su uslovi za binarnu pretragu po resenju.

Resenje je bar 1 (jer n > 0) a najvise moze biti n (ako prvog dana napise n linija koda, sigurnoce na kraju imati bar n linija koda, tj. F (n) ≥ n) pa cemo izvrsiti O(log n) koraka a kako zasvako m ∈ [1, n] racunamo F (m) u slozenosti O(logm) = O(log n), ukupna vremenska slozenostalgoritma je O(log2 n). Memorijska slozenost je O(1).

F(n, k)

sol ← 0

Page 44: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 43

m ← 1

while (m ≤ n) do

sol ← sol + b nmcm ← m · k

return sol

Solve(n, k)

l ← 1

r ← n

while (l < r) do

m ← b l+r2 c

if (F(m, k) < n )

l ← m + 1

else

r ← m

return l

16. TODO

17. Kako su svi elementi prirodni brojevi, trazeno resenje (minimum) ne moze biti manje od 1;6 sadruge strane, ono ne moze biti vece od S = a1 + a2 + . . .+ an. Dakle potrebno je pronaci najmanjibroj x iz segmenta [1, S] za koji je moguce podeliti niz a na k uzastopnih podnizova tako da jesuma svakog dela ne veca od x.

Prvo, primetimo da za dato x mozemo u slozenosti O(n) proveriti da li se niz moze podeliti natrazeni nacin. Zaista, dovoljno je da krenemo od a1 i da nademo najvece i za koje je a1 +a2 + . . .+ai ≤ x < a1 + a2 + . . . + ai+1; stavimo da je prvi podniz od prve do i-te pozicije i nastavimo odai+1, tj. sada nalazimo najvece j za koje vazi ai+1 + ai+2 + . . .+ aj ≤ x < ai+1 + ai+2 + . . .+ aj+1

i stavimo da je drugi podniz od (i+ 1)-ve do j-te pozicije itd. - prakticno pravimo podnizove takoda ubacimo sto vise brojeva a da im suma ne prede x. Ukoliko smo na ovaj nacin niz podelili nane vise od k podnizova, tada je x potencijalno resenje (jer mozemo dodatno razbiti podnizove daih bude tacno k); u suprotnom je trazena podela (za datu vrednost x) nemoguca7.

Drugo, primetimo da ukoliko za dato x ne mozemo izvrsiti podelu na k podnizova u kojoj jesuma svakog podniza manja ili jednaka x, tada to ne mozemo odraditi ni za jedan broj manji odx. Sa druge strane, ako dobijemo da je x potencijalno resenje, ne treba ispitivati brojeve vece odx jer nama treba najmanji x.

Zakljucak: mozemo raditi binarnu pretragu po resenju - krenemo od segmenta [1, S] uzmemosrednji broj x = b1+S2 c i u slozenosti O(n) proverimo da li je x potencijalno resenje; ukoliko jeste(tj. ukoliko postoji podela za dati broj x), pretragu nastavljamo na segmentu [1, x] jer nam trebanajmanje resenje; u suprotnom, nastavljamo pretragu na segmentu [x+ 1, S]. Ovo ponavljamo dokne dodemo do segmenta velicine 1 - izvrsimo O(logS) koraka i u svakom koraku proveru od O(n)pa je vremenska slozenost algoritma O(n logS) dok memorijsku mozemo svesti na O(1).

6Zapravo, ne moze biti manje od a1+a2+...+ank

.7Iako je relativno ocigledno, razmisliti zasto je ovo tacno!

Page 45: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 44

18. TODO

Page 46: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 4

Grafovski algoritmi I (Obilazakgrafova)

4.1 Teorija

Definicija 4.1 Graf G (eng. graph) je uredeni par (V,E), gde je E ⊆(V2

)1. Elementi skupa V se

zovu cvorovi (eng. vertex), a elementi skupa E grane (eng. edge) grafa G.

Definicija 4.2 Dva cvora u i v grafa G = (V,E) su susedna ako je u, v ∈ E; za njih kazemoda su spojena granom e = uv. Pod okolinom cvora v ∈ V grafa G = (V,E) (eng. neighborhood)podrazumeva se skup N(v) = u ∈ V : vu ∈ E suseda cvora v. Stepen cvora v (eng. degree), uoznaci deg(v) ili d(v) ili dv, je broj suseda cvora v, d(v) = |N(v)|.

Prethodne definicije se odnose na proste grafove - neorjentisane grafove bez petlji i visestrukihgrana. Definicija orijentisanog grafa je slicna, jedino se umesto skupa dvoelementnih podskupovaskupa V posmatra skup uredenih parova elemenata skupa V .

Grafove je najlakse (i najprirodnije) zamisljati kao skupove tacaka (cvorovi) od kojih su nekeod njih povezane linijama (grane). Zavisno od toga da li na krajevima ovih grana stoje ”strelice”,razlikujemo usmerene i neusmerene grafove.

U ovom poglavlju se podrazumeva da se radi o netezinskim grafovima – smatra se da su svegrane jedinicne duzine. O tezinskim grafovima bice reci u narednom poglavlju.

Standardni nacini predsavljanja grafa u racunaru su matrica susedstva i lista susedstva. Zbogmemorijske efikasnosti i mogucnosti obilaska svih suseda proizvoljnog cvora u u slozenosti O(d(u))cece se koristi lista susedstva i podrazumevacemo da su svi eksplicitni grafovi zadati u tomobliku. Ukoliko nije drugacije naglaseno, pretpostavlja se da su cvorovi indeksirani brojevima od1 do |V |. Dakle, graf G je prakticno odreden vrednostima |V |, |E| i listama susedstava N(v) zasvako v = 1, |V |. Radi preglednosti pseudo-koda, ukoliko radimo samo sa jednim grafom, necemoeksplicitno prenositi ove parametre funkcijama.2

Obilazak grafova

Standardni algoritmi za obilazak grafova su DFS (eng. depth-first search) i BFS (eng. breadth-first search). Ovi algoritmi se najcesce koriste kada zelimo ispitati povezanost ili udaljenost cvorova.Za implementaciju oba algoritama koristimo pomocni niz mark koji ce oznacavati da li je dati cvor

1Podsetimo se da za skup X i prirodan broj k,(Xk

)oznacava skup svih k-elementnih podskupova skupa X.

2Npr. umesto Solve(G) zvacemo samo Solve() i smatracemo da su broj cvorova, grana i liste susedstva globalnepromenljive.

45

Page 47: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 46

obiden ili ne i pomocni niz parent koji ce oznacavati prethodnika datog cvora u obilasku grafa.

DFS je algoritam koji je nesto jednostavniji za implementaciju i koristi se kada nam je dovoljnosamo ”obici” graf, bez racunanja najkracih rastojanja. Kao sto mu samo ime kaze, on je po prirodirekurzivan.

DFS(u)

mark[u] ← true

for each v ∈ N(u) do

if (not mark[v])

parent[v] ← u

DFS(v)

Solve() (* glavni program *)

mark[] ← false

parent[] ← 0

(* ako zelimo obici sve cvorove, koristimo for petlju (graf ne mora biti povezan) *)

for u ← 1 to |V | doif (not mark[u])

DFS(u)

Gore opisani algoritam samo popunjava niz parent ali se funkcija DFS moze malo modifikovati3

tako da se osnovni ”obilazak” pretvori u nesto mnogo korisnije kao sto je npr. prebrojavanjekomponenti povezanosti ili detekcija ciklusa u grafu.

Na osnovu pseudo-koda, jasno je da se svaki cvor posecuje najvise jednom (zbog niza mark)kao i da se svaka grana posecuje najvise dva puta (po jednom sa oba kraja, to je deo ”for eachv ∈ N(u)”) pa je vremenska slozenost algoritma O(|V |+ |E|). Memorijska slozenost je O(|V |+ |E|)ako racunamo i sam graf, odnosno O(|V |) ukoliko ne racunamo memoriju za cuvanje samog grafa(vec samo dodatne nizove mark i parent).

Ukoliko je potrebno odrediti najkraci put od datog pocetnog cvora start do svih ostalih cvorova,tada koristimo BFS. Ovaj algoritam koristi strukturu queue – kako obilazimo cvorove, stavljamoih u red a zatim ih redom uzimamo i update-ujemo rastojanja (niz d).

BFS(start)

mark[] ← false

d[] ← ∞queue.clear()

parent[start] ← 0

d[start] ← 0

queue.push_back(start)

mark[start] ← true

while (not queue.empty()) do

u ← queue.pop_front()

for each v ∈ N(u) do

if (not mark[v])

mark[v] ← true

parent[v] ← u

d[v] ← d[u] + 1

queue.push_back(v)

3najcesce dodavanjem par linija na pocetku ili na kraju, videti resenja nekih zadataka

Page 48: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 47

return d, parent

Kao rezultat, BFS najcesce vraca niz rastojanja d (d[u] = najkrace rastojanja izmedu cvora starti cvora u) i niz prethodnika parent (parent[u] = prethodnik na najkracem putu od cvora start docvora u). Slicnom analizom kao i kod DFS-a, ispostavlja se da je vremenska slozenost algoritmaO(|V |+ |E|) a memorijska O(|V |) ukoliko ne racunamo memoriju za cuvanje samog grafa.

Topolosko sortiranje

Topolosko sortiranje usmerenog grafa predstavlja linearno uredenje njegovih cvorova (tj. neki niza1, a2, . . . , a|V | ciji su elementi cvorovi grafa) tako da za svaku usmerenu granu u→ v vazi da je cvoru ispred cvora v u linearnom uredenju (tj. vazi da je cvor u ispred cvora v u nizu a). Ispostavljase da usmeren graf ima topolosko sortiranje ako i samo ako ne sadrzi usmereni ciklus.

Jedan od jednostavnijih algoritama za topolosko sortiranje usmerenog grafa dat je sledecimpseudo-kodom:

TopSort()

(* racunamo ulazni stepen svakog cvora *)

inDeg[] ← 0

for u ← 1 to |V | dofor each v ∈ N(u) do

inDeg[v] ← inDeg[v] + 1

(* ubacujemo u queue sve cvorove sa ulaznim stepenom 0 *)

queue.clear()

for u ← 1 to |V | doif (inDeg[u] = 0)

queue.push_back(u)

count ← 0

while (not queue.empty()) do

u ← queue.pop_front()

a[++count] ← u (* ubacujemo cvorove redom u trazeni niz a *)

for each v ∈ N(u) do

inDeg[v] ← inDeg[v] - 1 (* svim susedima smanjujemo ulazni stepen *)

if (inDeg[u] = 0)

queue.push_back(u)

if (count = |V |) (* ukoliko su svi cvorovi ubaceni, postoji topolosko sortiranje *)

return a

else

return NULL (* Postoji usmereni ciklus *)

Ovaj algoritam vraca topoloski sortiran niz cvorova grafa G (niz a) ili prijavljuje da graf sadrziusmereni ciklus (tj. da ga je nemoguce topoloski sortirati). Slicnom analizom kao i kod BFS-a,ispostavlja se da je vremenska slozenost algoritma O(|V | + |E|) a memorijska O(|V |) ukoliko neracunamo memoriju za cuvanje samog grafa.

Page 49: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 48

4.2 Zadaci

Zadatak 1. Programer Pera tvrdi da mozemo dizajnirati strukturu za cuvanje grafa G sa n cvorovai m grana pomocu koje se a) za proizvoljan cvor u svi susedi cvora u obilaze u slozenosti O(d(u));i b) za proizvoljna dva cvora u i v proverava da li su susedni u slozenosti O(log minn,m). Da lije Programer Pera u pravu?

Zadatak 2. Na sahovskoj tabli dimenzija n × n nalazi se skakac na poziciji (xS , yS). Neka poljatable su ostecena (oznacena sa X) i skakac ne moze stati na njih. Da li on moze doci do polja(xE , yE)? Ukoliko moze, stampati najkraci put. Trazi se resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 4

. E . .

. . X .

. . . X

. S . .

DA

3

(2, 1) (3, 3) (1, 2)

Zadatak 3. Data je tabla dimenzija n ×m na kojoj su neka polja uklonjena. Odrediti na kolikose delova raspala tabla (uklonjena polja su oznacena sa ’X’ a ostala sa ’O’) i velicinu najveceg dela.Dva polja pridaju istom delu ukoliko je moguce stici od jednog do drugog standardnim kretanjemgore-dole-levo-desno. Trazi se resenje vremenske slozenosti O(nm).

Ulaz Izlazn = 4 m = 5

XOOOO

OXOXO

OXXOX

OXXOO

3 dela

najveci deo - 6 polja

Zadatak 4. Ispitati da li u datom neusmerenom grafu sa n cvorova i m grana postoji ciklus iukoliko postoji - ispisati ga. Trazi se resenje vremenske slozenosti O(n+m).

Ulaz Izlazn = 5 m = 5

1 4

3 5

5 1

2 4

1 3

DA

1 - 3 - 5 - 1

Zadatak 5. Posmatrajmo prethodni zadatak uz izmenu da se radi u usmerenom grafu i da jepotrebno proveriti da li postoji usmereni ciklus u njemu. Programer Pera tvrdi da algoritam kojije opisan u resenju prethodnog zadatka resava i ovaj zadatak. Da li je Programer Pera u pravu?Ukoliko nije, pronaci algoritam slozenosti O(n+m) koji resava ovaj problem.

Zadatak 6. Dat je prirodan broj n. U jednom potezu je dozvoljeno trenutni broj smanjiti za 1,povecati za 1 ili podeliti sa 2 (samo ako je paran). Koliko je najmanje poteza potrebno da bismodobili broj 0? Trazi se resenje vremenske slozenosti O(n). [Programer Pera tvrdi da je ovo moguceuraditi i u boljoj slozenosti, da li je u pravu?]

Page 50: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 49

Ulaz Izlazn = 30 7

30→ 15→ 16→ 8→ 4→ 2→ 1→ 0

Zadatak 7. Dat je neusmeren graf G sa n cvorova i m grana i u njemu su posebno oznacenicvorovi a i b. Cvor zovemo dobar ukoliko pripada bar jednom najkracem putu od cvora a do cvorab. Ispisati koliko dobrih cvorova sadrzi graf G. Trazi se resenje vremenske slozenosti O(n+m).

Ulaz Izlazn = 5, m = 5, a = 1, b = 51 2

2 5

1 3

3 5

3 4

4

(to su cvorovi 1, 2, 3 i 5)

Zadatak 8. Imamo 3 kofe zapremine A, B i C litara (u pitanju su celi brojevi) koje su na pocetkuprazne. U jednom potezu mozemo iz jezera bilo koju kofu dopuniti do vrha, bilo koju kofu ispraznitiu jezero ili presipati vodu iz neke kofe u drugu pri cemo presipanje traje sve dok se jedna kofa neisprazni ili druga ne napuni, sta god se prvo desi (ne mozemo da biramo kada prestajemo sa pre-sipanjem). Da li je moguce posle nekoliko poteza u nekoj kofi dobiti tacno X litara vode? Ako jemoguce, koliko nam je najmanje poteza potrebno? Trazi se resenje vremenske slozenosti O(A·B ·C).

Ulaz IzlazA = 3, B = 8, C = 4, X = 5 DA, 2 poteza

Zadatak 9. Dato je n racunara i neki od njih su povezani kablovima (ukupno m kablova). Hakerzeli da od stigne od racunara 1 do racunara n. Odrediti najveci broj k tako da na svakom kablumozemo postaviti jednu od k razlicitih sifri (svaka sifra mora biti upotrebljena bar jednom) takoda vazi: ma kako haker izabrao put od racunara 1 do n on ce naici na svih k sifara. Trazi se resenjevremenske slozenosti O(n+m).

Ulaz Izlazn = 4 m = 4

1 2

1 3

2 4

3 4

2

Npr. sifra 1 na 1-2 i 1-3, sifra 2 na

2-4 i 3-4

Zadatak 10. Neka polja table n×m su zahvacena vatrom (oznacena su slovom ’V’). Svake sekunde,vatra se sa polja u plamenu siri na sva polja koja sa njim dele stranicu i koja vec nisu zahvacenavatrom. Odrediti posle koliko sekundi ce cela tabla biti u plamenu. Trazi se resenje vremenskeslozenosti O(nm).

Ulaz Izlazn = 4 m = 7

.......

.V.V...

.V.....

......V

3

Page 51: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 50

Zadatak 11. Dato je n poslova numerisanih brojevima od 1 do n i m uslova oblika ”ai bi” kojioznacavaju da se posao broj ai mora obaviti pre posla bi. Ispisati bilo koji korektan redosled obavl-janja svih n poslova ili -1 ako je nemoguce obaviti sve poslove uz date uslove. Trazi se resenjevremenske slozenosti O(n+m).

Ulaz Izlazn = 6 m = 4

2 1

3 1

5 3

4 6

2 5 3 1 4 6

Zadatak 12. Dato je n kuglica numerisanih brojevima od 1 do n i sve su razlicite tezine (ali mine znamo te tezine). Izvrseno je ukupno k merenja na vagi sa dva tasa i u svakom merenju je najednom tasu postavljena po jedna kuglica. Opis merenja ”(x y)” znaci da su merene kuglica broj xi kuglica broj y i da kuglica broj x teza od kuglice broj y. Na osnovu ovih merenja ispisati kuglicepo tezinama (od najmanje do najvece, ako ima vise resenja - bilo koje) ili -1 ako merenja nisu biladobra. Trazi se resenje vremenske slozenosti O(n+ k).

Ulaz Izlazn = 6 k = 3

(4, 3), (4, 5), (2, 6)

6 1 5 3 2 4

Page 52: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 51

4.3 Resenja

1. Programer Pera je u pravu. Za pocetak, dovoljno je koristiti obicne liste susedstva pri cemuje lista susedstva svakog cvora sortirana (na osnovu indeksa cvorova). Jasno je da se svi susediproizvoljnog cvora u obilaze u slozenosti O(d(u)) ali sada umesto klasicne provere svih susedai trazenja cvora v medu njima (u pomenutoj slozenosti), mozemo primeniti binarnu pretragu itraziti v u listi N(u) u slozenosti O(log d(u)) sto je svakako O(log n).

Dodatno, ukoliko je m < n, mozemo na pocetku sortirati sve grane (npr. predstaviti ih kaouredeni par (manji indeks cvora, veci indeks cvora)) a zatim datu granu u− v pretraziti binarnompretragom u nizu grana u slozenosti O(logm). Dakle, slozenost provere susednosti zaista moze bitiodradena u slozenosti O(log minn,m).

2. Iako formulacija nije takva, ovo je (jasno) problem iz teorije grafova. Posmatrajmo graf komeje skup cvorova zapravo skup svih neostec enih polja table i dva cvora su povezana granom akkoje moguce doci od jednog do drugog potezom skakaca u sahu. Sada se problem svodi na: za datadva cvora s i e u grafu, odrediti najkraci put izmedu njih ili konstatovati da put ne postoji.

Ovo resavamo jednostavnim BFS obilaskom grafa iz cvora s i stampamo vrednost d[e] ukoliko jed[e] 6=∞ a zatim na osnovu niza parent rekonstruisemo put. Broj cvorova je ocigledno |V | = O(n2)a kako iz svakog cvora polazi najvise 8 grana (skakac moze skociti na najvise 8 drugih polja), sledida je i broj grana |E| = O(n2). Kako koristimo BFS, sledi da je i vremenska i memorijska slozenostO(|V |+ |E|) = O(n2).

Vredi pomenuti da, kada nemamo eksplicitno zadat graf (kao u ovom slucvaju), problem mozemoresavati na 2 nacina:

• Eksplcitno napraviti graf tj. indeksirane cvorove od 1 do |V | i liste susedstva N(u) – ovo senajcesce moze uraditi pravolinijski u slozenosti O(|V | + |E|) i ovu slozenost treba racunatikada se racuna ukupna slozenost algoritma4

• Koristiti implicitni graf i modifikovati algoritme (BFS, DFS, ...) da rade sa njim. Npr. uovom slucaju je moguce posmatrati cvor kao uredeni par koordinata (x, y) na tabli i umestooznaka tipa mark[u] koristiti oznake tipa mark[(x, y)] ili mark[x][y] kao i modifikovati linijepseudo-koda poput ”for each v ∈ N(u) do” sa konkretnijim vrednostima (npr. jedan odpotencijalnih suseda cvora (x, y) je (x+ 1, y − 2)).

Da bismo maksimalno uprostili pseudo-kod, najcesce cemo koristiti prvi pristup (jer tada ne moramomenjati strukturu pseudo-kodova za BFS, DFS, ...) ili mesavinu oba pristupa kada nam je tozgodnije. Npr. u zadacima poput ovog mozemo zamislti da svaki cvor u ima dodatne parametreu.x i u.y (pozicija na tabli) pa npr. mozemo koristiti i oznaku d[u] i oznaku d[(x, y)] ako je izkonteksta jasno o cemu se radi.

Solve(n, m[][])

(* pomocni nizovi za pracenje poteza skakaca *)

dx[] = (-2, -2, -1, -1, 1, 1, 2, 2)

dy[] = (-1, 1, -2, 2, -2, 2, -1, 1)

(* kreiramo graf *)

for i ← 1 to n do

for j ← 1 to n do

if (m[i][j] 6= ′X ′)

N((i, j))← ∅ (* pravimo listu susedstva za cvor u = (i,j) *)

for k ← 1 to 8 do

(x, y) ← (i + dx[k], j + dy[k])

4Medutim, kako je vecina algoritama na grafovima slozenosti Ω(|V |+ |E|), ova konstrukcija prakticno ne utice naslozenost takvih algoritama.

Page 53: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 52

if ((x, y) inside board and m[x][y] 6= ′X ′)

N((i, j))← N((i, j)) ∪ (x, y)

(* sada pozivamo BFS iz pocetnog cvora *)

(d, p) ← BFS((xS , yS))

if (d[(xE , yE)] = ∞)

return "Ne postoji put"

(* inace, stampamo duzinu puta i sam put (unazad jer je tako lakse) *)

u ← (xE , yE)print d[u]

while (u 6= 0) do

print u

u ← parent[u]

3. Zadatak je ekvivalentan sledecem: posmatrajmo graf kome su cvorovi polja koja nisu uklonjena(oznacena sa ’O’) a dva cvora su povezana granom ukoliko su odgavarajuca polja susedna na tabli.Potrebno je odrediti broj povezanih komponenti u ovom grafu i broj cvorova u najvecoj komponenti.

Trazeni problem se jednostavno resava malom modifikacijom DFS algoritma. U glavnom pro-gramu prolazimo kroz sve cvorove; ukoliko cvor nije posecen, povecavamo broj povezanih kompo-nenti za 1, resetujemo brojac cvorova u trenutnoj komponenti na 0 i pustamo DFS iz tog cvora.Ukoliko cvro nije posecen, ne radimo nista jer je on vec uracunat u nekoj komponenti. Potrebno jesamo na pocetku DFS-a povecavati brojac cvorova u trenutnoj komponenti za 1.

Slicno prethodnom zadatku, graf ima O(nm) cvorova i O(nm) grana pa je vremenska i memo-rijska slozenost algoritma (ukljucujuci konstrukciju grafa) jednaka O(nm).

DFS(u)

currCompSize ← currCompSize + 1 (* brojimo cvorove u komponenti *)

mark[u] ← true

for each v ∈ N(u) do

if (not mark[v])

DFS(v)

Solve(n, m, a[][])

(* pomocni nizovi kao u prethodnom zadatku *)

dx[] = (-1, 1, 0, 0)

dy[] = (0, 0, 1, -1)

(* kreiramo graf *)

for i ← 1 to n do

for j ← 1 to m do

if (a[i][j] 6= ′X ′)

N((i, j))← ∅ (* pravimo listu susedstva za cvor u = (i,j) *)

for k ← 1 to 4 do

(x, y) ← (i + dx[k], j + dy[k])

if ((x, y) inside board and a[x][y] 6= ′X ′)

N((i, j))← N((i, j)) ∪ (x, y)

compNum ← 0 (* ukupan broj komponenti *)

maxCompSize ← 0 (* velicina najvece komponente *)

mark[] ← false

for u ← 1 to |V | doif (not mark[u])

compNum ← compNum + 1 (* povecaj broj komponenti *)

Page 54: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 53

currCompSize ← 0 (* restartuj broj cvorova u trenutnoj komponenti *)

DFS(u)

maxCompSize ← max(maxCompSize, currCompSize) (* update maxCompSize *)

return compNum, maxCompSize

4. Graf nema ciklusa ako i samo ako je suma tj. ako mu je svaka povezana komponenta stablo.Jos jedna karakterizacija je: graf G sadrzi ciklus ako i samo ako postoji grana uv takva da u grafuG − uv postoji put od u do v (jer taj put zajedno sa granom uv cini ciklus). Sada se namecejedan od trivijalnijih nacina za detekciju ciklusa: za svaku granu uv, izbaciti je iz grafa a zatimproveriti da li u novom grafu (G− uv) postoji put izmedu cvorova u i v (obicnim DFS-om). Kakograna ima m, a slozenost DFS-a je O(n+m) (izbacili smo samo jednu granu), ukupna slozenost jeO(m(n+m)) sto nije dovoljno dobro.

Kljucna stvar je primetiti da nam obican DFS daje dovoljno informacija za detekciju ciklusa.Zaista, posmatrajmo situcaciju kada prilikom poziva ”DFS(u)”, linija ”if (not mark[v])” vrati false,tj. kada je sused v vec markiran. To se jedino moze desiti u slucaju kada je cvor v parent cvora u(parent[u] = v, tj. do cvora u smo dosli iz cvora v) ili kada postoji grana izmedu trenutnog cvorau i nekog ranije obidenog cvora v. Medutim, drugi slucaj garantuje da postoji ciklus jer postojiput od v do u i povratna grana od u do v koja nije deo tog puta.

Dakle, za detekciju ciklusa je dovoljan samo jedan DFS pa je vremenska slozenost algoritmaO(n + m) a memorijska O(n). Za rekonstrukciju je dovoljno stampati cvorove u, parent[u],parent[parent[u]], . . ., sve do cvora v; radi jednostavnosti, u pseudo-kodu ne rekonstruisemo samciklus.

DFS(u)

mark[u] ← true

for each v ∈ N(u) do

if (not mark[v])

parent[v] ← u

DFS(v)

else

if (v 6= parent[u])

cycleFound ← true

Solve()

mark[] ← false

cycleFound ← false

for u ← 1 to n do

if (not mark[u] and not cycleFound)

DFS(u)

return cycleFound

5. Programer Pera nije u pravu! Na primer, posmatrajmo usmereni graf G sa 3 cvora i granama1 → 2, 2 → 3 i 1 → 3. Ovaj graf nema usmerenih ciklusa ali ce DFS prijaviti da ima - npr. akokrenemo iz cvora 1 i prvo obidemo cvor 2 (a zatim iz njega cvor 3), svi cvorovi ce biti markirani;kada se vratimo u 1 i kada probamo sledeceg njegovog suseda (cvor 3), on je markiran i DFS mislida smo upali u ciklus. Dakle, prethodni algoritam nije dobar za usmerene grafove.

Prethodni algoritam se moze modifikovati da radi i za usmerene grafove ali je mnogo jednos-tavnije resenje je – pozvati algoritam za topolosko soritranje grafa! Ukoliko TopSort() vrati NULL,nema usmerenog ciklusa a inace usmereni ciklus postoji. Od ranije znamo da ovaj algoritam radi

Page 55: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 54

u trazenoj slozenosti.

6. Primetimo da je ponekad optimalno dobiti i brojeve vece od n pre nego sto dodemo do nule.Medutim, nije tesko videti da ni u jednom trenutku necemo dobiti broj koji je manji od 0 ili veciod 2n5

Posmatrajmo grafG ciji su cvorovi brojevi 0, 1, 2, . . . , 2n i postoji usmerena grana od cvora/brojai do cvora/broja j akko je moguce u jednom potezu dobiti od broja i broj j. Jasno je da svaki cvorima najvise 3 suseda – jedini potencijalni susedi cvora i su i − 1, i + 1 i i/2 (ukoliko je i paran).Zadatak se svodi na: u grafu G naci duzinu najkraceg puta od cvora n do cvora 0 sto mozemoodraditi obicnim BFS-om. Kako graf G ima O(n) cvorova i O(n) grana, vremenska i memorijskaslozenost algoritma su O(n).

Solve()

Napravi graf G sa cvorovima 0, 1, 2, . . . , 2nfor i ← 0 to 2n do

N(i)← ∅if (i > 0) N(i)← N(i) ∪ i− 1if (i < 2n) N(i)← N(i) ∪ i+ 1if (i mod 2 = 0) N(i)← N(i) ∪ i/2

(d, p) ← BFS(n)

return d[0]

Inace ovaj zadatak se zaista moze uraditi u slozenosti boljoj od Θ(n) - savetuje se zaintresovanimcitaocima da razmisle kako.

7. Oznacimo sa d(u, v) najkrace rastojanje izmedu cvorova u i v u grafu G. Ocigledno, cvor upripada (nekom) najkracem putu izmedu a i b ako i samo ako vazi d(a, b) = d(a, u) + d(u, b).

Ovo mozemo proveriti tako sto na pocetku izracunamo (jednim BFS-om) vrednost d(a, b) azatim za svaki cvor u pustimo BFS, izracunamo vrednosti d(u, a), d(u, b) i proverimo uslov. Ovozahteva n BFS-ova pa je slozenost ovog pristupa O(n(n+m)).

Mozemo i bolje. Kada bolje pogledamo formulu, vidmo da u svim rastojanjima ucestvuje barjedan od cvorova a i b. Dakle, dovoljno je pustiti samo dva BFS-a, jedan iz cvora a a drugi iz cvorab. Ukoliko dobijene nizove najkracih rastojanja oznacimo sa da[] i db[], redom, tada je za svakicvor dovoljno proveriti da li vazi da[b] = da[u] + db[u]. Kako je ova provera O(1) po cvoru, ukupnavremenska slozenost algoritma je dominirana slozenoscu BFS-a – O(n + m), dok je memorijskaslozenost O(n) zbog nekoliko pomocnih nizova duzine n.

Solve()

(da, p) ← BFS(a)

(db, p) ← BFS(b)

sol ← 0

for u ← 1 to n do

if (da[b] = da[u] + db[u])sol ← sol + 1

return sol

8. Posmatrajmo graf kome su cvorovi uredene trojke celih brojeva (x, y, z) gde je 0 ≤ x ≤ A,0 ≤ y ≤ B i 0 ≤ z ≤ C. Cvor (x, y, z) predstavlja stanje kada u prvoj kofi imamo x litara vode, u

5Zaista, najmanji broj poteza da bismo dosli do 2n je n ali sa tim brojem poteza mozemo doci do nule i zavrsiti.

Page 56: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 55

drugoj y litara vode i u trecoj z litara vode. U ovom grafu postoji usmerena grana od (x1, y1, z1)do (x2, y2, z2) ako i samo ako se od prvog stanja moze doci do drugog preko jednog presipanja; npr.za dati primer, ukoliko smo u stanju (1, 4, 2), mozemo preci u stanje (3, 2, 2) (presipanje iz drugekofe u prvu) ili u stanje (1, 6, 0) (presipanje iz trece kofe u drugu), ili u stanje (1, 8, 2) (punjenjedruge kofe iz jezera do vrha) itd.

Dakle, dovoljno je pustiti BFS iz stanja (0, 0, 0) i proveriti da li se moze dostici bilo koje stanje(x, y, z) u kome je bar jedan od x, y, z jedank X – od svih takvih stanja/cvorova, uzecemo onajnajblizi i trazeno rastojanje je najmanji broj presipanja.

Broj cvorova ovog grafa je O(A ·B ·C) (tacnije (A+ 1)(B + 1)(C + 1)) a kako iz svakog cvoravodi najvise 12 grana (iz svake od 3 kofa mozemo presipati vodu u neku od preostale dve, u jezeroili je napuniti iz jezera), sledi i da je ukupan broj grana ovog grafa O(A ·B ·C). Dakle, vremenskai memorijska slozenost za konstrukciju ovog grafa kao i za BFS je O(A ·B · C).

9. TODO

10. TODO

11. Posmatrajmo graf ciji su cvorovi poslovi i za svaki od uslova ”ai bi” dodajmo usmerenu granuod cvora ai do cvora bi u ovom grafu (dakle, ovaj graf ima n cvorova i m grana). Jasno je daje problem ekvivalentan nalazenju topoloskog sorta ovog grafa (ukoliko obavljamo poslove u tomredosledu nece biti konflikta; jedini slucaj kada se poslovi ne mogu obaviti je kada postoji ciklicnazavisnost medu njima, tj. usmereni ciklus u konstruisanom grafu). Kako je ovo direktna primenapoznatog algoritma, vremenska slozenost je O(n + m) a memorijska O(n + m) zbog konstrukcijegrafa.

Solve()

Napravi prazan graf G sa n cvorova

for i ← 1 to m do

dodaj usmerenu granu ai → bi grafu G

a ← TopSort()

if (a 6= NULL)

return a

else

return -1

12. Primeniti algoritam topoloskog soritranja...

Page 57: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 5

Grafovski algoritmi II (Tezinskigrafovi)

5.1 Teorija

U ovom poglavlju se bavimo tezinskim grafovima.

Definicija 5.1 Tezinski graf (eng. weighted graph) je uredena trojka (V,E,w), gde su V i E,redom, skup cvorova i skup grana dok je w : E → R funkcija tezine.

Dakle, svakoj grani grafa dodeljujemo neki realan broj koji predstavlja tezinu ili, u nekimsituacijama prirodniji termin, duzinu grane. Duzina nekog puta u tezinskom grafu je zbir duzinasvih grana na tom putu. Tezinu/duzinu grane uv cemo najcesce oznacavati sa w(u, v).

Sa implementacione tacke gledista vaze svi detalji kao i za netezinske grafove osim sto, dodatno,u listi susedstva N(u) cvora u ne cuvamo samo njegove susede vec uredene parove (v, w) kojioznacavaju da je cvor u povezan sa cvorom v granom tezine w.

Najkraca rastojanja

Kao i u proslom poglavlju, zanima nas sledeci klasican problem: Za dati graf G i cvor u ∈ V (G),odrediti najkraca rastojanja cvora u do svih ostalih cvorova. Za razliku od netezinskih grafova,ovde nas ne interesuje samo broj grana i zbog toga algoritmi poput BFS-a ne rade na ovakvimgrafovima. Za tezinske grafove koristimo Dijkstrin algoritam. Ovaj algoritam radi samo kadasu tezine grana nenegativni brojevi!

DijkstraApstract(start)

d[] ← ∞parent[start] ← 0

d[start] ← 0

Q ← V (* smesti sve cvorove u skup Q *)

while (not Q.empty())

u ← cvor iz Q sa minimalnom vrednoscu d[u]

izbaci u iz Q

for each v in N(u) do

if (d[u] + w(u, v) < d[v])

d[v] ← d[u] + w(u, v)

parent[v] ← u

return d, parent

56

Page 58: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 57

Da bi ovaj algoritam bio efikasan potrebno je efikasno implementirati operacije

(1) Pronalazenje i izbacivanje elementa sa najmanjom vrednoscu d[u] iz skupa Q – ovo se desavatacno |V | puta;

(2) Update vrednosti d[v] (deo koda ”d[v] ← d[u] + w(u, v)”) jer to utice na poredak u skupu Q– ovo se u najgorem slucaju desava |E| puta.

Ove operacije se najcesce implementiraju na 2 nacina:

I nacin: ukoliko za trazenje minimuma jednostavno proveravamo sve elemente skupa Q tadaoperacija (1) radi u slozenosti O(|V |) a operacija (2) u slozenosti O(1) pa je ukupna slozenostalgoritma O(|V |2 + |E|) = O(|V |2).1.

Dijkstra1(start) (* slozenost O(|V |2) *)

d[] ← ∞parent[start] ← 0

d[start] ← 0

mark[] ← true (* ako je mark[u] = true, tada u ∈ Q *)

while (postoji bar jedan markiran cvor)

u ← -1

for v ← 1 to |V| do

if (u = -1 or d[v] < d[u])

u ← v

mark[u] ← false

for each v in N(u) do

if (d[u] + w(u, v) < d[v])

d[v] ← d[u] + w(u, v)

parent[v] ← u

return d, parent

II nacin: ukoliko koristimo MinHeap, tada i izbacivanje elemenata i update vrednosti radi uslozenosti O(log |V |) pa je ukupna slozenost algoritma O((|V |+ |E|) log |V |).

Dijkstra2(start) (* slozenost O((|V |+ |E|) log |V |) *)

d[] ← ∞parent[start] ← 0

d[start] ← 0

MinHeap ← (V, d[]) (* smesti sve cvorove u MinHeap na osnovu vrenosti d[u] *)

while (not MinHeap.empty())

u ← MinHeap.extractMin()

for each v in N(u) do

if (d[u] + w(u, v) < d[v])

d[v] ← d[u] + w(u, v)

minHeap.updateValue(v, d[v])

parent[v] ← u

return d, parent

1Kako radimo sa prostim grafovima, uvek je |E| = O(|V |2).

Page 59: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 58

Izbor implementacije Dijkstrinog algoritma zavisi od ”gustine” grafa: ako graf ima puno grana,npr. |E| = Θ(|V |2), bolje je koristiti I nacin; ako graf ima malo grana, npr. |E| = Θ(|V |), bolje jekoristiti II nacin.2

Memorijska slozenost (ne racunajuci sam graf) je uvek O(|V |).

Ukoliko zelimo da radimo sa grafovima u kojima tezine grana mogu biti i negativni brojevi,koristimo Belman–Ford algoritam. Za dati graf (koji moze sadrzati i grane negativne tezine) icvor u ∈ V (G), ovaj algoritam odreduje najkraci put od cvora u do svih ostalih cvorova ili detektujeda postoji negativan ciklus (ciklus kome je suma tezina grana manja od nule) dostizan iz cvora u.3

Ideja algoritma je jednostavna: |V | − 1 puta proci kroz sve grane (x, y) grafa (zamisljamo daje (x, y) usmerena grana od x ka y; ako nije, razmatramo i (x, y) i (y, x)) i proverimo da li je(trenutno) najkrace rastojanje od u do y optimalno ili je bolje ici preko cvora x (d[x] + w(x, y)).Moze se pokazati da je, ukoliko ne postojoje negativni ciklusi dostizni iz u, |V | − 1 prolaz dovoljanza racunanje niza d[] i parent[]; zato na kraju odradimo jos jedan prolaz i, ukoliko se ispostavi danismo zavrsili, sledi da postoji negativan ciklus.

Belman-Ford(start)

d[] ← ∞parent[start] ← 0

d[start] ← 0

for i ← 1 to |V| - 1

for each edge (u, v) in E(G)if (d[v] > d[u] + w(u, v)) (* ukoliko je bolje preko cvora u *)

d[v] = d[u] + w(u, v)

parent[v] = u

for each edge (u, v) in E(G)if (d[v] > d[u] + w(u, v))

return -1 (* postoji negativan ciklus *)

return d, parent

Slozenost ovog algoritma je (ocigledno) O(|V | · |E|).

Razapinjuca stabla

Definicija 5.2 Razapinjuce stablo grafa G je podgraf grafa G koji sadzi sve njegove cvorove i kojije stablo.

Definicija 5.3 Minimalno razapinjuce stablo (eng. minimum spanning tree (MST) ili minimumcost spanning tree (MCST)) neusmerenog tezinskog grafa G je razapinjuce stablo grafa G cija jesuma tezina grana najmanja moguca.

Jedan od klasicnih problema teorije grafova je: Za dati neusmereni tezinski graf G, odradititezinu njegovog minimalnog razapinjuceg stabla i/ili samo stablo. Jasno je da graf ima bar jednorazapinjuce stablo ako i samo ako je povezan – zbog ovoga nije lose prvo proveriti povezanost nekimstandardnim algoritmom oblisaka. Mi cemo nadalje podrazumevati da algoritme za trazenje MCSTpokrecemo iskljucivo na povezanim grafovima.

2Uporediti slozenost ova dva nacina u zavisnosti od |E| i uveriti se u tacnost ovih tvrdenja. Pokazati da je zapravobolje koristiti I nacin akko je |E| = Ω(|V |2/ log |V |).

3U tom slucaju nema smisla racunati najkraca rastojanja jer ”vrteci se” kroz taj ciklus mozemo proizvoljno mnogosmanjiti rastojanje.

Page 60: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 59

Jedan od nacina na koji se moze resiti ovaj problem je pomocu Primovog algoritma.

Ovaj algoritam je zapravo modifikacija Dijkstrinog algoritma i radi skoro isto kao i on; jedinarazlika je sto ne gledamo najkrace puteve od pocetnog cvora (svejedno je koji je to cvor za Primovalgoritam) do odgovarajuceg cvora vec puteve kojima je najduza grana – najkraca moguca.

PrimApstract()

d[] ← ∞parent[1] ← 0

d[1] ← 0

mcstWeight ← 0

Q ← V (* smesti sve cvorove u skup Q *)

while (not Q.empty())

u ← cvor iz Q sa minimalnom vrednoscu d[u]

izbaci u iz Q

if (u 6= 1)

mcstWeight ← mcstWeight + w(parent[u], u)

for each v in N(u) do

if (w(u, v) < d[v]) (* ovo je razlika u odnosu na Dijkstru *)

d[v] ← w(u, v)

parent[v] ← u

return mcstWeight, parent

Za samu rekonstrukciju MCST -a se moze iskoristiti niz parent[]: grane tog stabla su upravograne (parent[u], u) za svako u = 2, |V |. Kao i kod Dijkstrinog algoritma, i ovaj se moze imple-menitrati (potpuno analogno) na pomenuta dva nacina i tada mu je slozenost O(|V |2), odnosnoO((|V |+ |E|) log |V |).

Drugi nacin za resavanje MCST problema je pomocu Kruskalovog algoritma.

Radi efikasne implementacije ovog algoritma, koristi se takozvana Disjoint-Set struktura. Ovastruktura omogucava da se nad elemetima 1, 2, . . . , n rade sledece dve operacije od kojih svaka radiu slozenosti O(log n)4:

• check(x, y) – proveri da li su elementi x i y u istom skupu;

• union(x, y) – spoji skup u kome je element x sa skupom u kome je element y.

Podrazumeva se da na pocetku imamo n skupova velicine 1 tj. svi elementi su u razlicitom (svom)skupu. Ideja je da svaki skup organizujemo kao korensko stablo tj. da za svaki element u pamtimop[u] – njegovog oca u tom stablu. Element u za koji vazi p[u] = u ce biti koren; na pcetku za svakielement vazi p[u] = u. Za svaki koren cemo pamtiti i rank[u] – broj elemenata u stablu ciji je onkoren.5

U implementaciji koristimo pomocnu funkciju find(u) koja vraca predstavnika (koren) skoupau kome se element u nalazi. Provera check(x, y) je ekvivalentna sa pitanjem find(u) = find(v)dok se operacija union(x, y) obavlja spajanjem dva stabala pri cemu koren veceg stabla postajeotac korenu manjeg stabla.

find(x)

while (p[x] 6= x)

x ← p[x]

return x

4Ovo se moze raditi i u boljoj (amortizovanoj) slozenosti ali nam je ovo dovoljno zbog jednostavne implementacije5Umesto broja cvorova moze se pamtiti i visina stabla.

Page 61: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 60

check(x, y)

if (find(x) = find(y))

return true

else

return false

union(x, y)

if (not check(x, y))

u = find(x)

v = find(y)

if (rank[u] > rank[v])

p[v] = u

rank[u] = rank[u] + rank[v]

else

p[u] = v

rank[v] = rank[u] + rank[v]

Moze se pokazati da svako ovako dobijeno stablo/skup nikada nece imati visinu vecu od O(log n) paoperaciaj find radi u slozenosti O(log n) i, prema tome, i ostale dve operacije rade u toj slozenosti.

Kruskalov algoritam radi tako sto sortira sve grane rastuce po tezini a zatim formira MCSTtako sto ih redom dodaje – ukoliko bi dodavanjem neka grana napravila ciklus, ona se preskace.Dodavanje i provera postojanja ciklusa je ekvivalentno spajanju i proveri pripadnosti elemenataskupova.

Kruskal()

Sortiraj niz grana e[] rastuce po tezini

T ← ∅ (* na pocetku je MCST prazno stablo *)

mcstWeight ← 0

for u ← 1 to |V | dop[u] ← u

rank[u] ← 1

for i ← 1 to |E| do(u, v, w) ← (e[i].u, e[i].v, e[i].weight)

if (not check(u, v))

union(u, v)

T ← T ∪ uv

mcstWeight ← mcstWeight + w

return T, mcstWeight

Slozenost sortiranja grana (u opstem slucaju) je O(|E| log |E|) dok je dodavanje grane/proveraciklsua O(log |V |) po grani pa je ukupna vremenska slozenost Kruskalovog algoritma O(|E| log |E|+|E| log |V |). Memorijska slozenost je O(|V |), ne racunajuci sam graf.

Page 62: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 61

5.2 Zadaci

Zadatak 1. Dat je neusmeren tezinski graf G sa n cvorova i m grana, kao i prirodan broj k ≤ n.Odrediti k-to po duzini rastojanje od cvora 1 do svih ostalih cvorova. Trazi se resenje vremenskeslozenosti O((m+ n) log n).

Ulaz Izlazn = 4 m = 5 k = 3

1 2 5

1 3 10

2 4 3

3 4 1

2 3 20

8

(rastojanja cvora 1 do cvorova 1, 2, 3

i 4 su, redom, 0, 5, 9 i 8. Trece po

velicini rastojanje je 8)

Zadatak 2. Programer Pera zeli bolje da razume kako radi Dijkstrin algoritam – za svako njegovotvrdenje odredite (uz obrazlozenje) da li je tacno ili ne.

a) Dijkstra radi i za usmerene i za neusmerene tezinske grafove (sa nenegativnim tezinama);

b) U Dijkstrinom algoritmu je neophodno liniju koda ”for each v in N(u)” zameniti sa ”for eachv in N(u) ∩Q” jer treba update-ovati samo one susede cvora u koji jos nisu obradeni.

c) Ukoliko je G usmeren tezinski graf koji ima negativne grane ali ne sadzi usmerene ciklusenegativne tezine i ukoliko je v ∈ V (G) neki njegov cvor, tada pokretanjem Dijkstre iz startnogcvora v uvek dobijamo korektna najkraca rastojanja do svih ostalih cvorova.

d) Pretpostavimo da tezinu puta definisemo kao proizvod tezina grana na njemu (a ne kao zbirtezina). Tada Dijkstra i u ovom slucaju radi ispravno za svaki graf sa pozitivnim tezinamauz modfikaciju da je pocetno rastojanje 1 umesto 0 i koriscenjem ”d[u] · w(u,v)” umesto ”d[u]+ w(u, v)”.

Zadatak 3. Data je mapa od n raskrsnica od kojih su neke od njih povezane dvosmernim ulicama.Ukupno ima m ulica i za svaku od njih je poznata njena duzina. Ulicu zovemo lepom ukoliko ona pri-pada nekom najkracem putu izmedu raskrsnica 1 i n i prolaskom kroz nju se prolazi tacka na sredinitog najkraceg puta. Ispisati broj lepih ulica. Trazi se resenje vremenske slozenosti O((n+m) log n).

Ulaz Izlazn = 4 m = 5

1 2 10

2 4 12

1 4 22

1 3 20

3 4 3

2

(2-4 i 1-4)

Zadatak 4. Dat je tezinski neusmereni graf sa n cvorova i m grana. Odrediti minimalno razap-injuce stablo ovog grafa ukoliko je za svaku granu dodatno poznato da li mora pripadati minimalnomrazapinjajucem stablu, ne sme pripadati minimalnom razapinjajucem stablu ili je svejedno. Ispisatisamo tezinu minimalnog razapinjajuceg stabla (pretpostaviti da resenje postoji). Trazi se resenjevremenske slozenosti O(m logm+m log n).

Page 63: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 62

Ulaz Izlazn = 4 m = 5

1-2, w = 3, svejedno

2-3, w = 2, svejedno

3-4, w = 1, ne sme

4-1, w = 2 svejedno

1-3, w = 4, mora

8

w(1, 4) + w(1, 3) + w(3, 2)

Zadatak 5. Data je mapa od n gradova od kojih i izmedu svaka dva od njih postoji dvosmerniput. Programer Pera je malo hakovao racunare u gradu 1 i sada hoce da iz grada 1 stigne u gradn na najsigurniji nacin. Za svaki od puteva je poznata verovatnoca pi (0 < pi ≤ 1) da Peru necezaustaviti policija na tom putu. Ukupna verovatnoca da Pera bezbedno stigne u grad n jednakaje proizvodu svih verovatnoca na putevima kroz koje je prosao. Ispisati marsutu koja maksimizujeovu verovatnocu. Trazi se resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 5 m = 7

0.00 0.50 0.70 0.85 0.01

0.50 0.00 0.70 0.20 0.15

0.70 0.70 0.00 0.90 0.80

0.85 0.20 0.90 0.00 0.05

0.01 0.15 0.80 0.05 0.00

1 - 4 - 3 - 5

(verovatnoca je 0.612)

Zadatak 6. Dat je tezinski graf G sa n cvorova i m grana pri cemu je tezina svake grane prirodanbroj. U ovom grafu su uoceni cvorovi a i b. Potrebno je odrediti najkraci put izmedu cvorova a ib ali u slucaju da ima vise najkracih puteva, potrebno je ispisati onaj sa najmanjimbrojem grana (ukoliko i tada ima vise resenja, stampati bilo koje). Trazi se resenje vremenskeslozenosti O((n+m) log n).

Ulaz Izlazn = 5 m = 5 a = 1 b = 5

1 2 7

2 3 8

3 5 10

1 4 12

4 5 13

1 - 4 - 5

(put 1 - 2 - 3 - 5 je iste duzine ali

ima vise grana)

Zadatak 7. U jednoj zemlji postoji n gradova i za svaki od njih je poznata cena ci potrebna da seu tom gradu iskopa bunar. Osim kopanja bunara, gradovi se mogu snabdevati vodom i medusobno– data je lista od m vodovodnih cevi koje je moguce izgraditi izmedu neka dva grada kao i cenaizgradnje za svaku od njih. Potrebno je iskopati neke bunare i izgraditi neke vodovodne cevi takoda vazi: svaki grad ima pristup vodi ili direktno iz bunara iskopanog u tom gradu ili postoji putod izgradenih vodovodnih cevi od tog grada do nekog grada u kome je iskopan bunar. Ispisatiminimalnu cenu za ovakav poduhvat (racunamo i cene bunara i cene vodovodnih cevi). Trazi seresenje vremenske slozenosti O(n+m) log n) ili O(m logm+m log n).

Page 64: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 63

Ulaz Izlazn = 4 m = 4

c = (10, 30, 12, 20)

1 2 25

2 3 20

3 4 5

4 2 18

45

(iskopati bunare u gradovima 1 i 3 i

sagraditi cevi 3-4 i 4-2)

Zadatak 8. Programer Pera zeli da dizajnira algoritam koji proverava da li dati usmereni grafG sa n cvorova i m grana sadrzi negativan ciklus. On misli da je dovoljno pustiti Belman-Fordovalgoritam iz cvora 1 i proveriti da li je kao rezultat vratio -1 ili ne.

a) Pokazati (kontraprimerom) da pustanje algoritma iz jednog cvora ne mora otkriti negativanciklus (jer je moguce da taj ciklus nije dostican iz tog cvora).

b) Nova ideja je pozvati Belman-Fordov algoritam iz svakog cvora i proveriti da li je bar jedanod njih vratio -1. Da li je ovaj algoritam tacan i kolika je njegova slozenost?

c) Dizajnirati algoritam slov zenosti O(n(n+m)) koji radi ono sto Pera zeli.

Zadatak 9. Na svakom polju sahovske table n × n nalazi se jedan prirodan broj. Figura top senalazi na polju (a, b) i mi zeli da je prebacimo na polje (c, d) koristeci standarna pravila za kretanjetopa. Caka je sto nakon svakog poteza topa mi moramo da platimo onoliko dinara koliko iznosibroj na polju u kome je top zavrsio taj potez (gleda se samo krajnje polje u potezu a ne poljapreko kojih je top presao u tom potezu). Ukoliko se u cenu racuna i pocetno polje, koliko najmanjemoramo platiti da bismo ostvarili cilj? Trazi se resenje vremenske slozenosti O(n3 log n).

Ulaz Izlazn = 4 (a, b) = (1, 2) (c, d) = (3, 3)

10 80 40 14

35 22 18 20

25 31 50 16

10 90 12 20

160

Zadatak 10. [TODO]

Ulaz Izlaz

Page 65: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 64

5.3 Resenja

1. Resenje je pravolinijsko – dovoljno je pustiti Dijkstru iz cvora broj 1 a zatim sortirati dobijeniniz rastojanja d[] i vratiti k-ti element tog niza. Ukoliko koristimo Dijkstru sa heap-om, slozenostje O((n + m) log n) dok je slozenost sorta O(n log n) pa je ukupna slozenost O((n + m) log n).Memorijska slozenost je O(n), ne racunajuci sam graf.

Solve()

(d, p) ← Dijkstra2(1)

Sortiraj neopadajuce niz rastojanja d[]

return d[k]

Alternativno resenje je modifikovati Dijkstru tako da se prekine cim se k-ti cvor izbaci iz skupa Q- njegova d-vrednost je trazeno revsenje (dokazati!).

2. Programer Pera je dao 3 pogresna tvrdenja:

a) Ovo je tacno – sve dok su tezine grana nenegativni realni brojevi, Dijkstrin algoritam dajekorektne rezultate i kod usmerenih i kod neusmernih grafova. Zaista, ovaj algoritam samokoristi liste N(u) a ne i informaciju da li iz v ∈ N(u) sledi u ∈ N(v).

b) Nije neophodno ovo uraditi. Istina je da treba update-ovati vrednosti d[v] samo za susedecvora u koji su jos uvek u Q (tj. koji su neobradeni) i da predlozena promena ne ”kvari”algoritam. Medutim, kako su tezine grana negativne, na osnovu opisa algoritma (videtipredavanja/prezentacije) sledi da iskaz ”d[u] + w(u,v) < d[v]” nikada nece biti tacan za v ∈ Qjer su grane nenegativne a ranije obradeni cvorovi imaju ne manju d-vrednost (rastojanje) odonih kasnije obradenih.

c) Nije tacno. Jedan od kontraprimera je graf sa 3 cvora i granama 1→ 2 tezine 2, 1→ 3 tezine1 i 2→ 3 tezine -2. Neka je startni cvor v = 1. Tada ce algoritam prvo zavrsiti sa cvorom 1(d[1] = 0), zatim sa cvorom 3 (d[3] = 1) jer mu je on blizi i na kraju sa cvorom 2 (d[2] = 2).Medutim, ocigledno je da je korektan rezultat d[1] = 0, d[2] = 2 i d[3] = 0 (preko cvora 2).

d) Nije tacno. Kontraprimer je slican prethodnom: posmatrajmo graf sa 3 cvora i granama1→ 2 tezine 2, 1→ 3 tezine 1 i 2→ 3 tezine 1

4 . Neka je startni cvor v = 1. Tada ce algoritamprvo zavrsiti sa cvorom 1 (d[1] = 1), zatim sa cvorom 3 (d[3] = 1) jer mu je on blizi i nakraju sa cvorom 2 (d[2] = 2). Medutim, ocigledno je da je korektan rezultat d[1] = 1, d[2] =2 i d[3] = 2 · 14 = 1

2 (preko cvora 2).6

3. Raskrsnice i ulice posmatramo kao neusmereni tezinski graf G; sa d(u, v) cemo oznacavatinajkrace rastojanje izmedu cvorova u i v u grafu G.

Za pocetak, kako za datu granu uv odrediti da li pripada nekom najkracem putu od cvora1 do cvora n? Slicno kao i u 7. zadatku iz prethodnog poglavlja: grana uv pripada nekomnajkracem putu od cvora 1 do cvora n ako i samo ako je d(1, n) = d(1, u) + w(u, v) + d(v, n) ilid(1, n) = d(1, v) + w(v, u) + d(u, n) (moramo razmotriti oba slucaja jer ne znamo u kom smeru seobilazi grana uv na putu od 1 do n). Dakle, uz dve Dijkstre (iz cvora 1 i iz cvora n) mozemo zasvaku granu u slozenosti O(1) odrediti da li poseduje gornju osobinu.

Dodatno se trazi da takve grane sadrze i centar puta ali to je samo jedan dodatni uslov:grana/ulica uv je lepa ukoliko vazi d(1, n) = d(1, u) + w(u, v) + d(v, n) i d(1, u) ≤ d(1, n)/2 ≤d(1, u) + w(u, v) ili odgovarajuci uslov za drugaciji poredak cvorova.

Ukupna vremenska slozenost ovog pristupa je O((n+m) log n) zbog Dijkstre, dok je memorijskaslozenost O(n) ne racunajuci sam graf.

6Inace, tvrdenje je tacno ako su tezine svih grana vece ili jednake od 1 (dokazati!).

Page 66: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 65

Solve()

(d1, p) ← Dijkstra2(1)

(dn, p) ← Dijkstra2(n)

dist ← d1[n] (* najkrace rastojanje izmedju 1 i n *)

sol ← 0

for each edge uv ∈ E do

if (dist = d1[u] + w(u, v) + dn[v] and d1[u] ≤ dist/2 ≤ d1[u] + w(u, v)) or

(dist = d1[v] + w(u, v) + dn[u] and d1[v] ≤ dist/2 ≤ d1[v] + w(u, v))

sol ← sol + 1

return sol

4. Ovaj problem je skoro ekvivalentan osnovnom problemu trazenja MCST-a uz malo modifikaciju.Kako resenje postoji, to znaci da ”obavezne” grane ne obrazuju nijedan ciklus i da je skup granabez ”zabranjenih” dovoljan da se formira neko razapinjuce stablo.

Jedina modifikacija koju je ptorebno napraviti u Kruskalovom algoritmu je sort grana na pocetku– umesto klasicnog neopadajuceg sorta, grane treba sortirati na sledeci nacin: na pocetku idu sveobavezne grane (u bilo kom redosledu), zatim sve ”svejedno” grane sortirane u neopadajuci poredaki na kraju ”zabranjene” grane (u bilo kom redosledu). Sa ovakvim sortom, Kruskalov algoritamgarantovano uzima sve ”obavezne” grane (nema ciklusa), zatim ih dopunjuje do MCST-a (jer su”svejedno” grane sortirane neopadajuce) a ne uzima nijednu ”zabranjenu” granu jer su prethodnebile dovoljne za MCST.

Kako se slozenost sorta ne menja a ostatak koda je isti kao kod Kruskala, vremenska slozenostalgoritma je O(m logm+m log n) a memorijska O(n).

KruskalModifikaija()

Sortiraj niz grana e[] kako je gore opisano

mcstWeight ← 0

...

isti ostatak koda kao kod Kruskala

....

return mcstWeight

5. Imamo tezinski graf (cije su tezine realni brojevi iz (0, 1]) i potrebno je naci put od cvora 1 docvora n tako da je proizvod grana na tom putu maksimalan. Kako Dijkstra u opstem slucaju nemoze resiti direktno ovakav problem7, primenicemo poznati trik.

Kako je funkcija log(x) strogo rastuca na (0,∞), maksimizacija izraza pi1 · pi2 · . . . · pik ekviva-lentna je maksimizaciji izraza log(pi1 ·pi2 · . . . ·pik) = log pi1 +log pi2 + . . .+log pik .8 Za druge strane,maksimizacija prethodnog izraza jednaka je minimizaciji izraza −(log pi1 + log pi2 + . . .+ log pik) =(− log pi1) + (− log pi2) + . . .+ (− log pik).

Prema tome, ukoliko postavimo da je tezina grane sa verovatnocom pi jednaka − log pi, zadatakse svodi na pronalazenje najkraceg puta u ovom grafu. Kako je 0 < pi ≤ 1, sledi da je log pi ≤ 0 (akose za osnovu logaritma uzme broj > 1) odnosno da je − log pi ≥ 0. Dakle, sve grane u novom grafusu nenegativne tezine pa mozemo pustiti Dijkstring algoritam. Marshuta se rekonstruise na osnovu

7Svejedno da li se trazi minimum ili maksimum, videti npr. 2. zadatak pod d).8Izabrana je bas funkcija log zbog pretvaranja zbira u proizvod; osnova logaritma moze biti bilo koji realan broj

> 1, npr 2 ili e.

Page 67: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 66

niza parent dok je tazena verovanoca jedanaka e−d(1,n) (ukoliko je koriscen prirodni logaritam tj.lnx).9

Kako je graf kompletan, imamo O(n2) grana pa se vise isplati da koristimo I verziju Dijkstrinogalgorima. Prema tome, vremenska slozenost algoritma je O(n2) kao i memorijska jer koristimonovu tezinu za svaku granu.

Solve()

for i ← 1 to |E| dopostavi tezinu i-te grane na − ln pi

(d, p) ← Dijkstra1(1)

list ← ∅u ← n

while (u 6= 0) do

list ← u ∪ list

u ← p[u]

return list (* trazeni niz cvorova na optimalnom putu od 1 do n *)

6. Ne mozemo samo pustiti Dijkstrin algoritam jer u slucaju da postoji vise resenja, ovaj algori-tam moze vratiti prakticno bilo koji najkraci put od a do b. Ovde dajemo 2 nacina za nalazenjenajkraceg puta sa (dodatno) najmanjim brojem grana.

Prvi nacin je da svakoj grani dodamo neku tezinu ε > 0. Pretpostavimo da postoje dva najkracaputa od a do b sa razlicitim brojem grana - neka su to putevi tezina W = w1 + w2 + . . . +wk = w′1 + w′2 + . . . + w′l koji imaju, redom, k i l grana. U novom grafu prvi put bi imao tezinu(w1 + ε) + (w2 + ε) + . . .+ (wk + ε) = W + k · ε dok bi, analogno, drugi put imao tezinu W + l · ε.Jasno, manje od ove dve vrednosti pripada putu sa manje grana pa ce Dijkstrin algoritam na ovomnovom grafu svakako od svih najkracih puteva vratiti onaj sa najmanjim brojem grana.

Medutim, treba se obezbediti da najkraci put u novom grafu bude ujedno i najkraci put ustarom, tj. broj ε treba biti dovoljno mali.10 Ispostavlja se da je dovoljno uzeti ε = 1

n . Zaista,najkraci put od a do b sadrzi najvise n−1 granu pa se u novom grafu tezina najkraceg puta povecavanajvise za n−1

n < 1 pa nikako ne moze premasiti drugi po vrednosti najkraci put u pocetnom grafukoji je bar za 1 duzi (jer su sve tezine prirodni brojevi).

Vremenska slozenost algoritma je O((n + m) log n) (Dijkstra sa heap-om) a memorijska O(n)ukoliko direktno menjamo duzinu grana.

Solve()

for each edge e ∈ E do

w(e)← w(e) + 1|V |

(d, p) ← Dijkstra2(1)

return trazeni put na osnovu niza p kao u prethodnom zadatku

Zadatak se moze uraditi i bez pretpostavke da su tezine grana prirodni brojevi (vec samo da sunenegativni realni brojevi) na sledeci nacin. Na pocetku pustimo po jednu Dijkstru iz cvora a icvora b i, kao ranije, odredimo koje sve grane pripadaju nekom od najkracih puteva izmedu a i b

9Kod vracanja tacne verovatnoce moze doci do problema preciznosti/memorije (u odnosu na model koji koristimo)jer ta verovatnoca moze biti reda velicine cn za neko c ∈ (0, 1). No, ovde se trazi samo put.

10Posmatrajmo graf sa 3 cvora i granama 1-2 tezine 2, 2-3 tezine 2 i 1-3 tezine 5. Ovde je jasno d(1, 3) = 4 prekocvora 2. Medutim, ukoliko bismo povecali svaku granu za npr. ε = 3, novi najkraci put od 1 do 3 bi bio direktnagrana 1-3 a ne vise 1-2-3. Dakle, Dijkstra bi u ovom slucaju vratio pogresan put.

Page 68: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 67

(videti Zadatak 3). Zatim izbacimo sve ostale grane i pustimo obican BFS nad preostalim grafomiz cvora a. Najkraci put do cvora b u ovom BFS-u je zaista trazeni put jer ovaj BFS u obzir uzimasamo grane koje mogu pripadati nekom od najkracih puteva u originalnom grafu a ujedno daje putsa najmanjim brojem grana. Slozenost algoritma je ista kao i u prethodnom slucaju.

Solve2()

(da, p) ← Dijkstra2(a)

(db, p) ← Dijkstra2(b)

dist ← da[b] (* najkrace rastojanje izmedju a i b *)

for each edge uv ∈ E do

if (not ((dist = da[u] + w(u, v) + db[v]) or (dist = da[v] + w(u, v) + db[u])))izbaci granu uv iz E

(d, p) ← BFS(a)

return trazeni put na osnovu niza p kao u prethodnom zadatku

7. Zadatak je ekvivalentan sledecem: u neusmerenom tezinskom grafu treba izabrati neke grane(sagraditi vodovode) i markirati neke cvorove (sagraditi bunare) tako da u svakoj povezanoj kom-ponenti novog grafa bude bar jedan markiran cvor (jasno je da je zapravo optimalno da bude tacnojedan markiran cvor) i da je ukupna cena minimalna. Ukoliko bi bilo dovoljno izgraditi samo jedanbunar, resenje bi bilo cena najjeftinijeg bunara + tezina MCST-a za dati graf; medutim, vodovodnecevi ne moraju da obrazuju stablo vec mogu i sumu.

Ovaj problem resavamo na sledeci nacin: dodajmo pocetnom grafu novi cvor v0 i povezimo gasa svim ostalim cvorovima – grana izmedu cvora v0 i i-tog cvora imace tezinu ci. Ovaj cvor mozemozamisliti kao izvor – izgradnja bunara u i-tom cvoru je sada ekvivalentna izborom grane/vodovodnecevi (tezine ci) koja spaja i-ti cvor i v0. Sada se problem svodi na odredivanje MCST-a u novoggrafu (kao da smo sve markirane cvorove iz originalnog grafa povezali sa v0) sto radimo Primovimili Kruskalovim algoritmom.

Vremenska slozenost algoritma je O((n+m) log n) (Prim2) ili O(m logm+m log n) (Kruskal)a memorijska O(n).

Solve()

for i ← 1 to |V | dododaj granu izmedju cvora vi i v0 tezine ci

V (G)← V (G) ∪ v0

(T, w) ← Prim2()

return w

8. Jedan od kontraprimera za deo a) je graf sa 4 cvora i granama 2 → 3, 3 → 4, 4 → 2 i 4 → 1od kojih svaka ima tezinu -1. Ovde zaista postoji negativan ciklus (2 → 3 → 4 → 2) ali kada sepozove Belman-Ford iz cvora 1, on nece biti dosegnut (ostalim cvorovima ce biti d[i] =∞) pa necebiti detektovan.

Algoritam iz dela b) je korektan: ukoliko postoji negativan ciklus, on ce biti dostizan bar izjednog cvora (npr. iz cvora na ciklusu) pa ce svakako biti pronaden ukoliko postoji. Kako pustamon Belman-Ford algoritama a slozenost svakog je O(nm), ukupna slozenost je O(n2m).

Za deo c), jednostavno napravimo novi ”vestacki” cvor 0, dodamo usmerene grane od njegado svih ostalih cvorva (npr. tezine grana su 0) i pustimo Belman-Ford iz tog cvora (kao i kod b),svakako ce negativan ciklus, ukoliko postoji, biti dostizan iz ovog novog cvora). Novi graf ima n+1cvor i m+ n grana pa je slozenost ovog algoritma O((n+ 1)(m+ n)) = O(n(m+ n)).

Page 69: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 68

9. TODO

10. TODO

Page 70: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 6

Greedy algoritmi

6.1 Teorija

TODO

U zadacima ovog tipa, cesto je lako/intuitivno pronaci algoritam trazene slozenosti ali je tezedokazati njegovu korektnost.

69

Page 71: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 70

6.2 Zadaci

Zadatak 1. U Nisu ima n mlekara pri cemu i-ta mlekara ima li litara mleka i prodaje ga po cenici dinara po litru. Koliko nam je najmanje para potrebno ako zelimo kupiti tacno X litara mleka?Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 5 X = 100

l = (20, 40, 10, 80 30)

c = (5, 9, 3, 8, 6)

630

Zadatak 2. Dato je n tacaka na realnoj pravoj svojim realnim koordinatama x1, x2, . . . , xn. Odred-iti koliko nam je najmanje zatvorenih jedinicnih intervala potrebno tako da njima mozemo pokritisve tacke. Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 6

1.0 2.0 2.5 2.6 3.0 5.0

3

(npr. [1, 2], [2.2, 3.2] i [4.5, 5.5])

Zadatak 3. Dato je n otvorenih intervala (ai, bi) na brojevnoj pravoj. Koliko najvise inter-vala mozemo izabrati tako da nikoja dva nemaju zajednickih tacaka? Trazi se resenje vremenskeslozenosti O(n log n).

Ulaz Izlazn = 5

(1, 3)

(9, 11)

(7, 10)

(2, 7)

(5, 7)

3

npr. (1, 3), (5, 7) i (7, 10)

Zadatak 4. Programer Pera je radio n testova i za svaki dobio ocenu izmedu 1 i 5. Zakljucna ocenaje prirodan broj najblizi aritmetickoj sredini svih ocena (ako je aritmeticka sredina na polovini,bira se veci broj). Pera moze da popravi neke testove (ocena za taj test se brise i upisuje se 5).Koliko najmanje testova mora popraviti tako da na kraju ima zakljucnu ocenu 5? Trazi se resenjevremenske slozenosti O(n).

Ulaz Izlazn = 4

5 3 3 5

1

Zadatak 5. Dato je n predmeta sa svojim tezinama w[i] i cenama c[i]. Lopov ima ranac koji mozeda ponese tezinu W i zeli da ga popuni predmetima tako da ima najvecu mogucu vrednost. Kojaje trazena najveca vrednost ako se predmeti mogu deliti na manje proprocionalne delove?Trazi se resenje vremenske slozenosti O(n log n). [Programer Pera tvrdi da se greedy resenje zaovaj zadatak moze primeniti i ukoliko se predmeti ne mogu deliti. Da li je Programer Pera u pravu?]

Ulaz Izlazn = 3 W = 50

w = (10, 30, 20)

c = (60, 120, 100)

240

(predmeti tezine 10 i 20 i 23 predmeta

tezine 30)

Page 72: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 71

Zadatak 6. Programer Pera tvrdi da se prethodni zadatak moze uraditi koristeci greedy pristupcak i ukoliko se predmeti NE MOGU deliti (tj. svaki predmet se mora ili uzeti ceo ili ne uzetiuopste). On predlaze sledeca tri algoritma:

a) Sortirati predmete neopadajuce po tezini i u svakom koraku uzimati trenutni predmet ukolikomoze da stane u ranac sa trenutno uzetim predmetima.

b) Sortirati predmete nerastuce po ceni i u svakom koraku uzimati trenutni predmet ukolikomoze da stane u ranac sa trenutno uzetim predmetima.

c) Sortirati predmete nerastuce po odnosu ’cena / tezina’ i u svakom koraku uzimati trenutnipredmet ukoliko moze da stane u ranac sa trenutno uzetim predmetima.

Pokazati da nijedan od ovih algoritama nije tacan navodenjem odgovarajucih kontraprimera.Da li mozete smisliti kontraprimer za koje ne radi nijedno od ponudenih resenja?

Zadatak 7. Dat je niz od n casa od kojih su neke okrenute nagore (predstavljene jedinicama) aneke nadole (predstavljene nulama). U jednom potezu dozvoljeno je promeniti stanje k uzastop-nih casa (one okrenute nagore postaju okrenute nadole i obratno). Naci najmanji potreban brojpoteza tako da sve case na kraju budu okrenute nagore ili ispisati ’-1’ ako je to nemoguce uraditi.Trazi se resenje vremenske slozenosti O(nk). [Programer Pera tvrdi da ume da uradi zadatak uslozenosti O(n), da li mu verujete?]

Ulaz Izlazn = 7 k = 3

0 0 1 0 1 0 0

3

Zadatak 8. Dat je niz a duzine n ciji su svi elementi nule. U jednom potezu mozemo izabratibilo koji indeks 1 ≤ i ≤ n u nizu a i sve elemente ai, ai+1, . . . , an ili povecati za 1 ili smanjiti za 1.Koliko je najmanje poteza potrebno da bismo od niza a dobili dati niz celih brojeva b? Trazi seresenje vremenske slozenosti O(n).

Ulaz Izlazn = 5

1 2 4 0 3

11

Zadatak 9. Dati su prirodni brojevi n i c. Na raspolaganju imamo beskonacno mnogo novcanicau iznosu od 1, c, c2, c3, . . . dinara i potrebno je isplatiti iznos od n dinara. Odrediti koliko najmanjenovcanica moramo iskoristiti za ovu isplatu. Trazi se resenje vremenske slozenosti O(log n). [Pro-gramer Pera tvrdi da se greedy resenje za ovaj zadatak moze primeniti za bilo koji sistem novcanica.Da li je Programer Pera u pravu?]

Ulaz Izlazn = 107 c = 5 7

Zadatak 10. Na jednoj obali reke nalazi se n osoba i za svaku je poznata tezina wi. Potrebno jesve osobe smestiti u camce pri cemu je poznato da ni u jednom camcu ne sme biti vise od 2 osobekao i da ukupna tezina osoba u camcu ne sme preci dati broj W . Koliko nam je najmanje camacapotrebno za ovaj poduhvat? Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 9 W = 100

90 20 20 30 50 60 70 90 80

6

Page 73: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 72

Zadatak 11. Ispred kase se sakupilo n ljudi i za svakog je poznato vreme ti koje je potrebno dabude usluzen. Osoba je razocarana ako je vreme koje provede cekajuci u redu (to vreme je jed-nako ukupnom vremenu potrebnom za usluzivanje svih ljudi ispred njega u redu) vece od vremenapotrebno za njeno usluzivanje. Rasporediti ove ljude u red tako da broj razocaranih osoba budeminimalan. Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 6

15 2 1 5 3 9

1 razocarana osoba

1 2 3 9 15 5

Zadatak 12. Niz brojeva je palindromski ako se cita isto i sa leve i sa desne strane. Na primer,niz (10, 9, 9, 10) je palindromski dok (1, 2, 3, 1) nije. Na pocetku je dat niz prirodnih brojeva aduzine n. U jednom koraku je dozvoljeno zameniti dva susedna broja njihovom sumom. Odreditinajvecu mogucu duzinu palindromskog niza koji se moze dobiti od niza a primenom ove operacijeproizvoljan broj puta. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 6

20 10 40 20 20 30

4

20 10 40 20 20 30 → 30 40 20 20 30 →30 40 40 30

Zadatak 13. Programer Pera ucestvuje na takmicenju iz programiranja i ima x poena. Porednjega, na takmicenju ucestvuje jos n programera ciji su trenutni brojevi poena a1, a2, . . . , an i ko-jima je ostala jos jedna runda takmicenja u kojoj ce im biti podeljeno p1, p2, . . . , pn poena (svakompo neki od ovih brojeva poena, na osnovu plasmana u toj rundi). Pera zeli da namesti plasmanu poslednjoj rundi tako da na kraju (posle sabiranja poena) broj takmicara koji imaju vise poenaod njega bude najmanji moguc. Stampati taj broj. Trazi se resenje vremenske slozenosti O(n log n).

Ulaz Izlazn = 3 x = 35

a = (50, 10, 30)

p = (3, 10, 7)

1

(npr. 50+7, 10+10, 30+3)

Page 74: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 73

6.3 Resenja

1. Intuitivno je prilicno jasno da se najvise isplati da kupimo sto vise mleka u mlekari koja gaprodaje najjeftinije, zatim, ukoliko nam je potreno jos, da dopunimo iz druge najjeftinije mlekareitd. dok ne sakupimo tacno X litara. Ukoliko sortiramo mlekare (li, ci) nepodajuce po ceni ci, op-timalno resenje ce uvek biti da ispraznimo prvih k mlekara (za neko k) i eventualno da dopunimodo X litara iz (k + 1)-ve mlekare. Zaista, ukoliko smo preskocili da ispraznimo pocetnih nekolikomlekara u sortiranom nizu, jednostavno mozemo oduzeti ”skuplje” mleko i dodati istu kolicinu”jeftinijeg” mleka i dobiti bolje (ili jednako dobro) resenje.

Vremenska slozenost ovog algortma je O(n log n) zbog sortiranja dok je memorijska O(1).

Solve(n, l[], c[], X)

sortirati parove (l[i], c[i]) neopadajuce po vrednosti c[i]

sol ← 0

for i ← 1 to n do

sol ← sol + c[i] * min(l[i], X) (* ili svih l[i] litara ili dopuna do X *)

X ← X - min(l[i], X)

return sol

2. Sortirajmo tacke tako da vazi x1 ≤ x2 ≤ . . . ≤ xn. Posmatrajmo sledeci greedy algoritam:prvi zatvoreni jedinicni interval postavimo tako da mu je levi kraj upravo x1. Levi kraj narednogintervala postavljamo u prvoj tacki xi koja nije pokrivena prvim intervalom itd. Dakle, levi krajk-tog intervala postavljamo u tacki xi gde je i najmanji indeks koji nije obuhvacen (k − 1)-vimintervalom (tj. najmanje i za koje je xi > x + 1 gde je x levi kraj (k − 1)-og intervala). Ovoponavljamo sve dok ima nepokrivenih tacaka.

Dokazimo tacnost ovog algoritma. Posmatrajmo raspored intervala u proizvoljnom optimalnomresenju i uocimo najlevlji interval – neka je to [x, x+ 1], za neko x. Ocigledno mora biti x ≤ x1 jerbi u suprotnom tacka x1 ostala nepokrivena. Ukoliko je x < x1 mozemo interval [x, x+ 1] pomeritiudesno do pozicije [x1, x1 + 1] – time ne kvarimo nista jer levo od x1 nema tacaka. Posmatrajmosada naredni interval i najmanje i za koje je xi > x1 + 1, tj. prvu tacku koja nije pokrivena prvimintervalom. Ponovo mora vaziti da je levi kraj drugog intervala manji ili jednak od xi pa ga mozemoudesno pomeriti (bez otkrivanja tacaka) tako da mu se levi kraj poklopisa xi.

Ovo mozemo ponavljati za svaki interval i ovim smo od proizvoljnog optimalnog resenja dobiliresenje koje daje nas algoritam tj. pokazali smo da postoji optimalno resenje cija je struktura istakao gore opisana tj. algoritam je tacan.

Vremenska slozenost ovog algortma je O(n log n) zbog sortiranja dok je memorijska O(1).

Solve(n, x[])

sortirati niz x[] neopadajuce

sol ← 1

leftEnd ← x[1]

for i ← 2 to n do

if (x[i] > leftEnd + 1)

sol ← sol + 1

leftEnd ← x[i]

return sol

Page 75: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 74

3. Sortirajmo intervale nepadajuce po njihovom desnom kraju. Posmatrajmo sledeci greedy algo-ritam: uzmemo prvi interval (u sortiranom nizu intervala), zatim prvi naredni koji nema presek saprvim, zatim prvi naredni koji nema presek sa drugim uzetim intervalom, itd. u svakom korakuuzimamo ”najlevlji” interval (gledano po desnom kraju) koji nema preseka sa prethodno uzetimintervalom. Ovo ponavljamo sve dok je moguce.

Dokazimo da ovaj algoritam zaista daje najveci moguci broj nepresecajucih intervala. Posma-trajmo intervale u proizvoljnom optimalnom resenju. Ukoliko najlevlji (po desnom kraju) nije prviinterval (u sortiranom nizu intervala), mozemo ga zameniti prvim intervalom – jasno je da ni tadanece postojati preseci. Naredni izabrani interval (po desnom kraju) u optimalnom resenju mozemopomeriti ulevo do ”naseg” drugog izabranog intervala – jasno je da se ni tada nece pojaviti novipreseci. Kako ovo mozemo ponavljati do kraja, zakljucujemo da se svako optimalno resenje moze”transformisati” u nase pa je i nase resenje optimalno.

Vremenska slozenost ovog algoritma O(n log n) zbog sortiranja dok je memorijska O(1).

Solve(n, intervals[])

sortirati niz intervals[] nepodajuce po desno kraju tj. po intervals[].b

sol ← 1

rightEnd ← intervals[1].b

for i ← 2 to n do

if (rightEnd ≤ intervals[i].a) (* ako i-ti interval ne sece prethodno izabrani *)

sol ← sol + 1

rightEnd ← intervals[i].b

return sol

4. TODO

5. Kako se predmeti mogu deliti na manje proporcionalne delove, mozemo zamisliti da je jedinicnacena i-tog predmeta jednaka ci

wii da mozemo uzeti bilo koju kolicinu i-tog predmeta iz segmenta

[0, wi]. Ovim zadatak postaje ekvivalentan 1. zadatku u sledecem obliku: imamo n mlekara, i-tamlekara ima wi litara mleka i prodaje ga poceni ci

wipo litru; mi zeli da kupimo W litara ali tako

da potrosimo najvise para.

Dakle, treba sortirati predmete nerastuce po vrednosti ciwi

i redom u dobijenom nizu uzimatipredmete/delove predmeta dok se ne napuni ranac. Analiza korektnosti i slozenost su iste kao u 1.zadatku.

Solve(n, w[], c[], W)

sortirati predmete (w[i], c[i]) nerastuce po vrednosti c[i]/w[i]

sol ← 0

for i ← 1 to n do

sol ← sol + c[i]/w[i] * min(w[i], W) (* ili ceo predme ili dopuna do W *)

W ← W - min(w[i], X)

return sol

6. TODO

7. Nazovimo segmentom bilo koji uzastopni podniz od tacno k casa. Pod okretanjem segementa

Page 76: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 75

mislimo na promenu stanja svih casa iz tog segmenta.

Izvrsimo par kljucnih zapazanja. (1) U optimalnom resenju, nije bitno kojim redosledomokrecemo segmente vec samo koji su segmenti izabrani za okretanje. Zaista, stanje neke case cese promeniti ako i samo ako pripada neparnom broju segmenata koje okrecemo, bez obzira ko-jim ih redosledom okrecemo. (2) U optimalnom resenju, svaki segment ce biti okrenut ili jednomili nijednom. Zaista, na osnovu prethodnog zapazanja, ako smo neki segment okrenuli paran brojputa efekat je isti kao da ga nismo okrenuli nijednom; slicno i za neparan broj puta i jedno okretanja.

Posmatrajmo 1. casu. Na nju utice jedino segment [1, k]. Na osnovu (2) sledi da ukolikoje 1. casa okrenuta nagore, segment [1, k] necemo okrenuti; u suprtonom ga moramo okrenuti.Posmatrajmo sada 2. casu (koja je promenila stanje ako smo okrenuli prvi segment). Na nju uticejedino segment [2, k + 1] jer smo vec jednoznacno odredili da li okrecemo segment [1, k] i on je vecizvrsio uticaj na stanje 2. case (na osnovu (1) mozemo bez umanjenja opstosti ”odmah” okrenutitaj segment). Sada ponovo na osnovu trenutnog stanja 2. case jednoznacno odredujemo da liokrecemo segment [2, k + 1] ili ne.

Ovaj postupak ponavljamo za sve case 1, 2, 3, . . . , n−k+1, redom. Na kraju ostaje da proverimoda li su poslednjih k − 1 casa okrenutih licem nagore – ako jesu, resenje zaista postoji i stampamobroj okretanja; u suprotnom, resenje ne postoji. Zakljucak je zaista tacan jer je na osnovu prethodnediskusije jasno da su sva okretanja forsirana – ukoliko postoji neko resenje, ono je jedinstveno(posmatrajuci resenje kao skup okrenutih segmenata).

Vremenska slozenost ovog algoritma je O((n− k + 1)k) = O(nk) jer za svako od potencijalnihO(n) okretanja treba promeniti stanje k uzastopnih casa pocevsi od trenutne pozicije. Memorijskaslozenost je O(n) ako direktno menjamo pocetni niz.

Solve(n, a[])

sol ← 0

for i ← 1 to n - k + 1 do

if (a[i] = 0) (* ako je i-ta casa okrenuta nadole *)

sol ← sol + 1

for j ← i to i + k - 1 do (* promena stanja narednih k casa *)

a[i] ← (a[i] + 1) mod 2

for i ← n - k + 2 to n do

if (a[i] = 0) (* ako je bar jedna casa iz [n - k + 2, n] okrenuta nadole *)

return -1 (* tada nema resenja *)

return sol

Zadatak se moze uraditi i u slozenosti O(n) tako sto se uz par trikova izbegne direktna simulacijaokretanja trenutnih k uzastopnih casa u svakom koraku.

8. Izvedimo par slicnih zapazanja kao u prethodnom zadatku. Prvo, redosled poteza nije bitan– za element na i-toj poziciji je bitno samo koliko je ukupno bilo povecavanja i smanjivanja naindeksima manjim ili jednakim od i. Zato mozemo pretpostaviti da se svi potezi desavaju s levaudesno. Drugo, za svaki indeks i, ili cemo izvrsiti nekoliko povecanja ili nekoliko smanjivanja ilinecemo raditi nista (nikada i povecanja i smanjivanja) jer zelimo da minimizujemo broj poteza.

Ova dva zapazanja prakticno forsiraju poteze: za i = 1, jasno je da cemo odraditi |b1−0| potezada bismo dobili a1 = b1. Sada je na drugoj poziciji broj b1 a treba nam broj b2. Prema tome, sadaje neophodno odraditi |b2 − b1| poteza itd. Dakle, posle prvih i− 1 poteza na i-tom mestu je brojbi−1 (i na svim ostalim mestima desno jer je na pocetku a nula niz) pa je za i-tu poziciju potrebnoodraditi |bi−1− bi| poteza; ovo se radi do kraja niza pa je ovo algoritam vremenske slozenosti O(n)i memorijske O(1).

Solve (n, a[], b[])

Page 77: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 76

sol ← 0

b[0] ← 0

for i ← 1 to n do

sol ← sol + |b[i-1] - b[i]|

return sol

9. Posmatrajmo sledeci greedy algoritam: u svakom trenutku biramo najvecu mogucu vrednost ck

koja je manja ili jednaka od trenutne vrednosti broja n a zatim od broja n oduzimamo tu vrednost(ck). Ovo radimo sve dok broj n ne postane 0. Pokazimo da ovaj algoritam zaista daje minimalanbroj nocanica.

Posmatrajmo bilo koje optimalno resenje i neka je ck najveca novcvanica u njemu. Ukoliko jen ≥ ck+1 (tj. nas algoritam bi iskoristio nocanicu vecu od ck) to znaci da u optimalnom resenjupostoji nekoliko novcanica koje u zbiru daju ck+1. Zaista, sve novcanice su delioci broja ck+1

i najveca medu njima je ck pa kada ih npr. sabiramo jednu po jednu, nikada nece ”preskociti”vrednost ck+1 (a doci ce do te vrednosti jer im je ukupna suma n ≥ ck+1). Medutim, to znaci dasve te novcanice mozemo zameniti jednom novcanicom ck+1 i poboljsati optimalno resenje sto jekontradikcija. Dakle, nase resenje je zaista optimalno (cak i jedinstveno).

Najvece k za koje je ck ≤ n je blogc nc = Θ(log n). Takvih novcanica mozemo uzeti najvisebn/ckc a zatim ponavljamo postupak opisan u algoritmu. Vremenska slozenost ovog postupka jeO(log n) a memorijska O(1).1

Programer Pera nije u pravu za dodatno tvrdenje – ostavlje se citaocu da smisli kontraprimer.

Solve(n, c)

x ← 1

while (x · c ≤ n) do

x ← x · c

sol ← 0

while (n > 0) do

sol ← sol + (n div x)

n ← n mod x

x ← x div c

return sol

10. Pretpostavljamo da je maxwi ≤ W jer inace problem nema resenja. Sortirajmo osobe potezini i posmatrajmo sledeci greedy algoritam: ukoliko je zbir trenutno najteze i trenutno najlakseosobe manji ili jedank od W , smestimo ih zajedno u camac i nastavimo postupak za ostatak niza; uusprotnom, smestimo samo najtezu osobu u camac i nastavimo postupak za ostatak niza. Pokazimoda je algoritam zaista optimalan.

Posmatrajmo bilo koji optimalni raspored osoba u camce. Izbacimo one camce koji su u skladusa nasim algoritmom i pretpostavimo da smo dosli u situaciju da trenutno najteza osoba (npr.tezine d) nije smestena sa trenutno najlaksom osobom (npr. tezine a) vec je smestena sa nekomdrugom osobom npr. tezine c dok je osoba a u camcu sa osobom tezine b (ili je sama, tj. mozdaje b = 0). Dakle, vazi a + b ≤ W i c + d ≤ W . Medutim, tada mozemo izvrsiti premestanje irasporediti osobe a i d u jedan camac a osobe b i c u drugi. Zaista, koristeci cinjenicu da su ai d, redom, najlakse i najteze osobe, imamo da vazi a + d ≤ c + d ≤ W i b + c ≤ d + c ≤ W .Ponavljanjem postupka, dobijamo da se svako optimalno resenje moze transformisati u nase pa jei nase resenje optimalno.

1Postoji i jednostavniji algoritam – resenje je zapravo suma cifara broja n zapisanog u sistemu sa osnovom c.

Page 78: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 77

Vremenska slozenost pomenutog greedy algoritma je O(n log n) zbog sortiranja dok je memori-jska O(1).

Solve(n, W, w[])

sortirati niz w[] neopadajuce

i ← 1

j ← n

sol ← 0

while (i ≤ j)

if (w[i] + w[j] ≤ W)

i ← i + 1

j ← j - 1

sol ← sol + 1

return sol

11. TODO

12. TODO

13. TODO

Page 79: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 7

Dinamicko programiranje

7.1 Teorija

TODO

Sustina ove tehnike je ”resavati problem preko manjih potproblema”. Ovo se radi tako stose precizno definisu sva stanja (potproblemi), odredi se optimalno resenje onih najmanjih stanja(najcesce direktno) a zatim se uspostave rekurentne veze izmedu stanja i na osnovu njih se racunajuoptimalne vrednosti svih stanja (u redosledu zavisnosti).

78

Page 80: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 79

7.2 Zadaci

Zadatak 1. Dat je niz a celih brojeva duzine n. Potrebno je izabrati neke elemente ovog nizatako da suma izabranih elemenata bude maksimalna ali tako da nikoja dva izabrana elementa nisususedna. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 8

4 -1 3 8 7 -1 -5 6

20

(4 3 7 6)

Zadatak 2. U svakom polju matrice dimenzija n ×m nalazi se odredeni broj cokoladica. Mi senalazimo u gornjem-levom polju matrice i zelimo da odemo do donjeg-desnog polja pri cemu jedozvoljeno kretanje za jedno polje nadole ili jedno polje udesno. Koliko najvise cokoladica mozemoda sakupimo na ovaj nacin? Trazi se resenje vremenske slozenosti O(nm).

Ulaz Izlazn = 5 m = 5

2 2 5 6 2

5 1 2 2 3

7 6 7 8 7

1 6 4 2 3

3 4 0 3 5

50

(dole-dole-desno-desno-desno-desno

-dole-dole)

Zadatak 3. Dat je niz realnih brojeva a duzine n. Odrediti najduzi rastuci podniz ovog niza (pod-niz se ne mora sastojati od uzastopnih elemenata). Trazi se resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 7

3 1 5 12 6 10 8

4

1 5 6 10

Zadatak 4. Na x-osi se nalazi n hotela svojim realnim koordinatama x1 < x2 < . . . < xn. Mise nalazimo u prvom hotelu i zelimo da odemo u poslednji. Preko dana putujemo a kada usputnaidemo na neki hotel mozemo ili da prespavamo u tom hotelu i nastavimo putovanje sutra ilijednostavno da nastavimo putovanje odmah. Idealno zelimo da dnevno (tj. izmedu spavanja uuzastopnim hotelima) prelazimo k kilometara; ako umesto toga predemo x kilometara moramoplatiti (x−k)2 dinara. Koliko najmanje moramo platiti da bismo dosli do poslednjeg hotela? Trazise resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 6 k = 5

1 3 5 10 12 20

19

(1→ 5→ 10→ 12→ 20)

Zadatak 5. Imamo niz od n kuca i svaku od njih je potrebno ofarbati u crveno, plavo ili belopri cemu nikoje dve susedne kuce ne smeju biti ofarbane istom bojom. Za svaku kucu su poznatatri broja ci, pi i bi koja predstavljaju cene da se i-ta kuca ofarba odgovarajucom bojom. Odreditinajmanju mogucu cenu korektnog bojenja kuca. Trazi se resenje vremenske slozenosti O(n).

Ulaz Izlazn = 5

c = (3 4 1 5 8)

p = (3 5 7 2 9)

b = (7 1 2 3 2)

9

(bojenje pbcpb)

Page 81: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 80

Zadatak 6. U prodavnici ima n vrsta predmeta (od svake vrste beskonacno primeraka). Za svakuvrstu je poznata tezina w[i] i cena c[i] jednog predmeta te vrste. Lopov ima ranac koji moze daponese tezinu W i zeli da ga popuni predmetima tako da je ukupna vrednost predmeta u rancunajveca moguca. Koja je trazena najveca vrednost? Trazi se resenje vremenske slozenosti O(nW ).

Ulaz Izlazn = 3 W = 50

10 45

30 120

20 100

245

2 predmeta cene 100 i predmet cene 45

Zadatak 7. U prodavnici ima n predmeta i za svaki je poznata tezina w[i] i cena c[i]. Lopov imaranac koji moze da ponese tezinu W i zeli da ga popuni predmetima tako da je ukupna vrednostpredmeta u rancu najveca moguca (za razliku od prethodnog zadatka, svaki predmet mozemo uzetinajvise jednom). Koja je trazena najveca vrednost? Trazi se resenje vremenske slozenosti O(nW ).

Ulaz Izlazn = 3 W = 50

10 45

45 120

20 100

145

predmet cene 100 i predmet cene 45

Zadatak 8. Programer Pera ima n dasaka celobrojnih duzina i to duzine a1, a2, . . . , an. Ispisatikoliko mu je najmanje dasaka potrebno da bi sastavio veliku dasku duzine m ili prijaviti da je tonemoguce uraditi. Trazi se resenje vremenske slozenosti O(mn).

Ulaz Izlazn = 5 m = 22

2 14 10 30 10

3

(2 + 10 + 10)

Zadatak 9. Dat je prirodan broj n. Prikazati dati broj kao sumu kvadrata (ne nuzno razlicitih)prirodnih brojeva, tako da je broj sabiraka u toj sumi minimalan. Trazi se resenje vremenskeslozenosti O(n

√n).

Ulaz Izlazn = 22 3 (22 + 32 + 32)

Zadatak 10. Data je tabla dimenzije 2 × n i na raspolaganju su vam 2 figurice: ”L figurica”sastavljena od 3 polja (tj. kvadratic 2× 2 bez jednog polja) i ”domina” 2× 1. Odrediti na kolikonacina je moguce prekriti tablu pomocu ove dve figurice (figurice je dozvoljeno rotirati) ukoliko

a) je dozvoljeno koristiti samo ”L figurice” (npr. za n = 3, resenje je 2);

b) je dozvoljeno koristiti samo ”domine” (npr. za n = 3, resenje je 3);

c) je dozvoljeno koristiti obe vrste figurica (npr. za n = 4, resenje je 11).

U sva tri slucaja trazi se resenje vremenske slozenosti O(n).

Zadatak 11. Na stolu se nalazi n brojeva poredanih u niz. Pera i Mika igraju sledecu igru: prvoPera uzme jedan broj sa levog ili desnog kraja niza (po svom izboru); zatim Mika uzme jedan broj

Page 82: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 81

sa levog ili desnog kraja preostalog niza (po svom izboru) i tako naizmenicno dok ne pokupe svebrojeve sa stola. Cilj je imati sto veci zbir sakupljenih brojeva. Ako obojica igraju optimalno, nacizbir brojeva koje je Pera sakupio. Trazi se resenje vremenske slozenosti O(n2).

Ulaz Izlazn = 4

10 20 1 5

25

Zadatak 12. Dat je niz od n celobrojnih matrica M1,M2, . . . ,Mn, i-ta matrica je dimenzija ai×bii za svako i = 1, n− 1 vazi bi = ai+1. Potrebno je u proizvodu M1 ·M2 · . . . ·Mn postaviti za-grade, tako da se rezultujuca matrica izracuna u sto manje mnozenja brojeva (stampati taj brojmnozenja). Podsetimo se da je za racunanje proizvoda matrica dimenzija a× b i b× c potrebno abcmnozenja brojeva. Trazi se resenje vremenske slozenosti O(n3).

Ulaz Izlazn = 3

3 4

4 5

5 2

64

M1 · (M2 ·M3)

Zadatak 13. Programer Pera zeli da se uvezba iz dinamickog programiranja; pomozite mu takosto cete, zarad boljeg razumevanja, za zadatke 2, 5 i 11 iz ove oblasti (moze i za ostale):

a) Izracunati i ispisati vrednosti SVIH stanja d[i][j] iz opisa njihovih revsenja (ili drugacijihstanja dobijenih nekim slicnim dinamickim programiranjem) za date primere iz njihovg teksta;

b) Smisliti nekoliko greedy ”resenja” za ove zadatke i pokazati (kontraprimerima) zasto ta resenjanisu dobra.

Zadatak 14. U jednom malom mestu sve kuce se nalaze u istoj ulici. Momci stanuju u kucamanumerisanih (redom) brojevima od 1 do n sa leve strane ulice, a devojke u kucama numerisanih(redom) brojevima od 1 do n sa desne strane ulice. Svih n momaka se zaljubilo (svaki u razlicitudevojku), ali oni su vrlo stidljivi i ne zele da se sretnu sa nekim od svojih drugova kada krenudevojci. Svaki od njih vam je poverio problem i rekao svoju adresu i adresu svoje devojke. Naditenajveci moguci broj parova, za koje se putevi momaka ne ukrstaju (tj. odrediti najveci broj duzikoje mozemo povuci izmedu datih parova momak-devojka tako da se one ne seku). Trazi se resenjevremenske slozenosti O(n2).

Ulaz Izlazn = 4

1 3

2 1

3 2

4 4

3

(2-1, 3-2, 4-4)

Zadatak 15. Prodavnica ima n bombona od kojih se svaka nalazi u jednoj od k ≤ n kutija. i-tabombona kosta ai evra i nalazi se u kutiji ci. Ukoliko se iz j-te kutije uzima bar jedna bombona,potrebno je platiti bj evra za otvaranje te kutije. Koliko najvise bombona mozemo kupiti akoimamo P evra? Trazi se resenje vremenske slozenosti O(n2). (Hint: ”Obrnuti” problem i za datoi izracunati koliko je najmanje para potrebno da bismo kupili i bombona.)

Page 83: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 82

Ulaz Izlazn = 4 k = 2 P = 10a = (3, 1, 5, 3)

b = (1, 2)

c = (1, 2, 2, 2)

3

(Bombona cene 3 iz kutije 1 i bombone

cene 1 i 3 iz kutije 2)

Page 84: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 83

7.3 Resenja

1. Oznacimo sa d[i] – optimalno resenje problema za prvih i elemenata niza a tj. za podniz a[1..i].Vrednost koja nam je potrebna je d[n]. Odredimo kako vrednost d[i] zavisi od prethodnih vrednosti.

Posmatrajmo podniz a[1..i]. Ukoliko smo izabrali element a[i], tada ne smemo izabrati elementa[i−1] pa preostale elemente moramo izabrati iz podniza a[1..i−2]. Jasno je da nam se najvise isplatida te elemente izaberemo na optimalan nacin (da bi ukupna suma bila najveca) a ta optimalnasuma je, po definiciji, upravo d[i− 2]. Dakle, ako izaberemo element a[i], tada je optimalno resenjejedanko a[i] + d[i − 2]. Ukoliko ne izaberemo element a[i], tada smo slobodni da biramo bilo kojeelemente iz podniza a[1..i− 1] pa je u tom slucaju resenje d[i− 1] jer ponovo biramo na optimalannacin. Mi cemo, naravno, izabrati bolji od ova dva nacina – dakle, vazi sledeca rekurentna formula

d[i] = maxa[i] + d[i− 2], d[i− 1].

Ostaje samo izracunati pocetne vrednosti; iz formule vidimo da su nam potrebne bar dve pocetnevrednosti jer za racunanje vrednosti d[i] koristimo i d[i−1] i d[i−2]. Najjednostavnije je dodefinisatiniz d i za prazan niz, tj. d[0] = 0 (sa smislom da je za prazan niz optimalno resnje 0). Jasno je ida vazi d[1] = maxa[1], 0, tj. d[1] = a[1] ukoliko je a[1] > 0 a inace necemo uzeti taj element.

Ovim je resenje preko dinamickog programiranja kompletirano; vremenska i memorijska slozenostalgoritma je O(n) jer na osnovu formule sledi da imamo O(n) stanja i O(1) operacija po stanju.

Solve(n, a[])

d[0] ← 0

d[1] ← max(a[1], 0)

for i ← 2 to n do

d[i] = max(a[i] + d[i - 2], d[i - 1])

return d[n]

2. Zadatak resavamo dinamickim programiranjem a stanja definisemo na sledeci nacin: za sve1 ≤ i ≤ n i 1 ≤ j ≤ m neka je d[i][j] = najveci broj cokoladica koje mozemo sakupiti tako dakretanje zavrsimo u polju (i, j). Primetimo da je d[i][j] optimalno resenje za podmatricu od prvihi vrsta i prvih j kolona; nas zanima vrednost d[n][m].

Kako izracunati d[i][j]? Ukoliko je i > 1 i j > 1, postoje 2 nacina na koji smo mogli doci dopolja (i, j): ili preko polja (i− 1, j) poslednjim potezom nadole ili preko polja (i, j − 1) poslednjimpotezom udesno. Jasno, kako zelimo da sakupimo sto vise cokoladica, sigurno cemo se obezbeditida smo sakupili najvise moguce (do tog trenutka) i kada/ako se nalazimo na nekom od ova dvapolja. Prema tome, ukoliko dolazimo preko polja (i−1, j), vazice d[i][j] = d[i−1][j]+a[i][j] a inaced[i][j] = d[i][j − 1] + a[i][j]. Od ove dve vrednosti biramo maksimalnu pa vazi rekurentna formula

d[i][j] = a[i][j] +max(d[i− 1][j], d[i][j − 1]).

Ovu formulu treba malo modifikovati kada je i = 1 ili j = 1 (tj. kada smo u prvoj vrsti ili koloni) jerje tada pretposlednje polje jedinstveno odredeno. Medutim, kako bismo olaksali implementaciju,mozemo zamisliti da smo dodali vestacki (nulti) red i kolonu i da vazi d[i][0] = d[0][j] = 0 za svei i j; ovo ce biti pocetne vrednosti u dinamickom programiranju i sada se ne moramo brinuti okospecijalnih slucajeva.

Kako imamo O(nm) stanja a za racunanje jednog stanja je potrebno O(1) operacija, vremenskai memorijska slozenost algoritma su O(nm). Ovde je bitno napomenuti da treba analizirati vezu urekurentnoj formuli i odrediti koja stanja prvo resiti da ne bi doslo do ”preskakanja”; iz rekurentneformule se vidi da je dovoljno ici red po red s leva udesno (klasican obilazak matrice) jer ce takouvek biti izracunate vrednosti za element levo i iznad.

Page 85: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 84

Na osnovu formule sledi da se problem moze resiti i sa svega O(m) dodatne memorije: dovoljnoje u svakom trenutku pamtiti samo dva poslednja reda matrice d jer vrednost d[i][j] zavisi samo odtrenutnog i prethodnog reda.

Solve(n, m, a[][])

for i ← 1 to n do

d[i][0] ← 0

for j ← 1 to m do

d[0][j] ← 0

for i ← 1 to n do

for j ← 1 to m do

d[i][j] ← a[i][j] + max(d[i - 1][j], d[i][j - 1])

return d[n][m]

3. U ovom slucaju nije idealno definisati d[i] kao optimalno resenje (duzina najduzeg rastucegpodniza) za niz a1, a2, . . . , ai jer nije lako doci do veze izmedu potproblema (ne znamo gde se tajpodniz zavrsava da bismo trazili kandidata za prethodni element). Zato cemo definisati d[i] kaoduzina najduzeg rastuceg podniza koji se zavrsava bas u elementu ai. U ovom slucaju je lako uocitirekurentnu vezu izmedu stanja - dovoljno je posmatrati sve indekse j < i za koje je a[j] < a[i] (tosu kandidati za pretposlednji element) i za koje je 1 +d[j] najvece moguce. Dakle, za i > 1 formulaglasi

d[i] = 1 + max1≤j<ia[j]<a[i]

d[j]

dok za i = 1 ocigledno vazi d[1] = 1. Trazeno resenje je maxd[1], d[2], . . . , d[n]. Na osnovuformule, vremenska slozenost algoritma je O(n2) a memorijska O(n).

Ukoliko zelimo da rekonstruisemo najduzi rastuci podniz (a ne samo da vratimo njegvu duzinu),mozemo dodatno definisati niz p kao p[i] = indeks prethodnog elementa u najduzem rastucempodnizu koji se zavrsava u elementu a[i], ukoliko je d[i] > 1; inace p[i] = 0. Ukoliko se optimalnoresenje zavrsava u elementu a[i], trazeni podniz je a[i], a[p[i]], a[p[p[i]]], . . . (gledano unazad).

Solve(n, a[])

d[1] ← 1

p ← 0

for i ← 2 to n do

d[i] ← 1

for j ← 1 to i - 1 do

if (a[j] < a[i] and d[i] < 1 + d[j])

d[i] ← 1 + d[j]

p[i] ← j

sol = max(d[1], d[2], ..., d[n])

return (sol, p)

4. Slicno kao i u prethodnom zadatku, definisimo d[i] kao optimalnu cenu da bismo dosli do i-toghotela. Jasno, d[1] = 0 a za svako i > 1 dovoljno je proveriti sve kandidate j za poslednje stajanjepre hotela i – u tom slucaju placamo cenu d[j] (optimalan put do j-tog hotela) + (x[i]− x[j]− k)2

(placanje zbog odstupanja duzine x[i]− x[j] od k). Dakle, rekurentna formula je

d[i] = min1≤j<i

(d[j] + (x[i]− x[j]− k)2),

Page 86: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 85

pa je vremenska slozenost algoritma O(n2) a memorijska O(n).

Solve(n, a[])

d[1] ← 0

for i ← 2 to n do

d[i] ← ∞for j ← 1 to i - 1 do

d[i] ← min(d[i], d[j] + (x[i] - x[j] - k)2)

return d[n]

5. TODO

6. Ovo je poznati problem ranca (knapsack problem) u varijanti sa beskonacno pred-meta svake vrste. Bitno je uociti da ovde ne prolaze greedy strategije (npr. uzimanje najskupljihpredmeta, uzimanje najlaksih predmeta, uzimanje predmeta po odnosu cena/tezina i sl.).

Oznacimo sa d[i] optimalno resenje za ranac nosivosti i. Posmatrajmo neko optimalno popun-javanje takvog ranca. Ukoliko je u popunjavanju ucestvovao bar jedan predmet vrste j, to znaci daje w[j] ≤ i i ostali predmeti ne smeju da predu nosivost i− w[j]. Medutim, jasno je da ce taj deoranca biti takode optimalno popunjen (jer je i ranac nosivosti i optimalno popunjen) pa vazi da jed[i] = d[i−w[j]] (optimalno popunjavanje ranca nosivosti i−w[j]) + c[j] (cena predmeta vrste j).Mi ne znamo koji predmeti su zastupljeni u optimalnom popunjavanju d[i] ali mozemo probati zasvaki i uzeti masksimum; rekurentna formula glasi:

d[i] = max1≤j≤nw[j]≤i

(d[i− w[j]] + c[j]).

gde se podrazumeva da je d[i] = 0 ukoliko nijedan predmet ne moze stati u ranac nosivosti i(tj. na pocetku treba popuniti niz d nulama). Konacno resenje je d[W ] a sadrzaj ranca se mozerekonstruisati ako se dodatno pamti niz p gde je p[i] = vrsta poslednjeg ubacenog predmeta uoptimalnom popunjavanju ranca nosivosti i. Vremenska slozensot algoritma je O(nW ) a memorijskaO(W ).

Solve(W, n, w[], c[])

d ← 0

for i ← 1 to W do

for j ← 1 to n do

if (w[j] ≤ i)

d[i] ← max(d[i], d[i - w[j]] + c[j])

return d[W]

7. Ovaj problem je slican prethodnom i predstavlja problem ranca (knapsack problem) u var-ijanti sa tacno jednim predmetom svake vrste. Naravno, ni ovde ne prolaze greedy strategije.

Oznacimo sa d[i][j] najvecu mogucu vrednost koja moze stati u ranac nosivosi i koristeci samoprvih j predmeta. Druga koordinata je iz razloga sto sada moramo paziti da ne uzmemo vise putaisti predmet (jer to sada nije dozvoljeno) i ne mozemo svaki put proveravati sve predmete. Ovogputa logika je sledeca: ukoliko smo za optimalno popunjavanje d[i][j] koristili j-ti predmet, tada

Page 87: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 86

vazi d[i][j] = d[i−w[j]][j−1] + c[j] sto odgovara optimalnom popunjavanju ranca nosivosti i−w[j]koristeci prvih j−1 predmeta + cena j-tog predmeta; u suprotnom (nismo iskoristili j-ti predmet)vazi d[i][j] = d[i][j − 1], tj. nismo potrosili nosivost ranca i prelazimo na prvih j − 1 predmeta.Dakle, vazi

d[i][j] = max(d[i− w[j]][j − 1] + c[j], d[i][j − 1])

pri cemu treba proveriti da li je w[j] ≤ i (ili postaviti d[i][j] = −∞ za i < 0).

Ovoga puta, i vremenska i memorijska slozenost algoritma je O(nW ) jer imamo O(nW ) stanjai za racunanje svakog od njih je potrebno O(1) operacija.1

Solve(W, n, w[], c[])

for i ← 1 to W do

d[i][0] ← 0

for i ← 1 to W do

for j ← 1 to n do

d[i][j] ← d[i][j - 1]

if (w[j] ≤ i)

d[i][j] ← max(d[i][j], d[i - w[j]][j-1] + c[j])

return d[W][n]

8. Ovaj problem se moze svesti na modifikovani problem ranca – zamislimo da imamo n predmetacije tezine w[i] odgovaraju duzinama dasaka (cene nam nisu bitne) i ranac nosivosti m. Zelimo dapotpuno popunimo ranac (iskoristimo svu nosivost) koristeci sto manje predmeta – oznacimo sad[i][j] najmanji broj predmeta medu prvih j kojima se moze popuniti ranac nosivosti i, odnosno∞ ukoliko je to nemoguce uraditi. Slicno kao u prethodnom zadatku, nije tesko zakljuciti da vazi

d[i][j] = min(d[i− w[j]][j − 1] + 1, d[i][j − 1])

zavisno od toga da li koristimo ili ne koristimo j-ti predmet pri cemu treba uzeti u obzir da li jew[j] ≤ i i definisati na pocetku d[i][0] =∞ za sve i > 0 i d[0][0] = 0. Konacno resenje je d[m][n].

Kao i u prethodnom zadatku, vremenska i memorijska slozenost algoritma je O(nm).

Solve(n, m, a[])

for i ← 1 to n do

w[i] ← a[i] (* moze se koristiti i niz a[], ovako samo zbog notacije *)

d[0][0] ← 0

for i ← 1 to m do

d[i][0] ← ∞

for i ← 1 to m do

for j ← 1 to n do

d[i][j] ← d[i][j-1]

if (w[j] ≤ i and d[i - w[j]][j - 1] 6= ∞)

d[i][j] ← min(d[i][j], d[i - w[j]][j - 1] + 1)

if (d[m][n] = ∞)

return nemoguce

else

return d[m][n]

1Zadatak se moze uraditi i koriscenjem svega O(W ) memorije, slicno prethodnoj verziji problema ranca. Ipak,ukoliko se trazi i rekonstrukcija pakovanja (a ne samo optimalna vrednost), memorijska slozenost se ne moze svestina O(W ).

Page 88: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 87

9. Ovaj zadatak je skoro identican prethodom – jedina razlika je u tome sto se problem svodi naproblem ranca u kome je dozvoljeno ponavljanje predmeta. Zadatak je ekvivalentan sledecem: dat jeranac nosivosti n i b

√nc predmeta tezina 12, 22, 32, . . . , b

√nc2; potrebno je potpuno popuniti ranac

(iskoristiti svu nosivost) koristeci sto manje predmeta. Kako je ovog puta dozvoljeno ponavljanje(npr. mozemo vise puta iskoristiti broj 32 kao u primeru) definisemo d[i] kao najmanji moguci brojpredmeta potreban da bi se ranac nosivosti i potpuno popunio. Formula je

d[i] = min1≤j≤b

√ic

(1 + d[i− j2])

Bazni slucaj moze biti d[0] = 0 ili d[1] = 1 a resenje uvek postoji (jer se svaki broj moze napisati kaozbir jedinica). Vremenska slozensot je O(n

√n) (nosivost puta broj vrsta predmeta) a memorijska

O(n).

Solve(n)

d[0] ← 0

for i ← 1 to n do

d[i] ← i

for j ← 1 to b√ic do

d[i] ← min(d[i], 1 + d[i - j2])

return d[n]

10. Oznacimo sa d[i] broj nacina da se tabla 2 × i prekrije pomocu datih figurica. Specijalno,definisimo d[0] = 1.

a) Jasno je da je d[1] = d[2] = 0. Za i ≥ 3 za poslednji deo dimenzija 2 × 3 imamo samo dvemogucnosti – ”ukrstiti” 2 L figurice na 2 nacina. Prema tome, za i ≥ 3 vazi d[i] = 2 · d[i − 3] uzdefiniciju d[0] = 1. Direktna primena ove formule daje algoritam linearne slozenosti.

b) Jasno je da je d[1] = 1. Za i ≥ 2 imamo 2 mogucnosti za poslednju vertikalu 2×1 u tabli 2×i:postavimo jednu vertikalnu dominu (ostaje nam tabla 2 × (i − 1)) ili postavimo dve horizontalnedomine (ostaje nam tabla 2 × (i − 2)). Prema tome, vazi d[i] = d[i − 1] + d[i − 2], pa ovo dajealgoritam linearne slozenosti.

c) Definisimo pomocni niz a[i] kao broj nacina da se tabla 2×i bez gornjeg-desnog ugaonog poljaprekrije pomocu datih figurica. Kao i u prethonim slucajevima, trivijalno je izracunati vrednostid[1] i a[1]. Razmatranjem poslednje 2 kolone tablica 2 × i nije tesko doci do sledecih formula:d[i] = d[i−1]+d[i−2]+2 ·a[i−1] (domina vertikalno, 2 horizontalne domine, 2 nacina za trominu)i a[i] = a[i− 1] + d[i− 2] (horizontalna domina, tromina).

Paralelnim izracunavanjem nizova d i a dolazimo do konacnog resenja (d[n]). Vremenskaslozenost algoritma je linearna a memorijska se sa linearne moze svesti na konstantnu (kao i uprethodnim slucajevima) tako sto se pamti samo nekoliko poslednjih elemenata nizova.

Solve(n) (* samo za deo c) *)

d[0] ← 1, d[1] ← 1

a[0] ← 0, a[1] ← 0

for i ← 2 to n do

d[i] ← d[i - 1] + d[i - 2] + 2 · a[i - 1]

a[i] ← a[i - 1] + d[i - 2]

return d[n]

Page 89: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 88

11. Neka su na stolu brojevi a1, a2, . . . , an. Oznacimo sa d[i][j] maksimalan zbir brojeva koje mozesakupiti igrac koji igra prvi pri optimalnoj igri ako su na stolu brojevi ai, ai+1, . . . , aj . Oznacimosa s[i][j] sumu ai + ai+1 + . . .+ aj . Resenje zadatka je vrednost d[1][n].

Kako izracunati d[i][j]? Ukoliko je i = j, ocigledno je d[i][i] = a[i]; inace (i < j), igrac napotezu u tom trenutku ima samo dve mogucnosti: uzeti element ai ili uzeti element aj . Ukolikouzme elemet ai, tada drugi igrac igra prvi na podnizu od (i+ 1)-og do j-tog elementa pa ce osvojiti(po definicij) vrednost d[i + 1][j] dok ce prvom igracu ostati ai (element kojeg je prvo uzeo) +s[i+ 1][j]− d[i+ 1][j] (ono sto ostane posle drugog igraca). Analogna formula se dobija i u slucajuuzimanja elementa aj . Kako igrac koji je tada na potezu moze da bira, on ce izabrati onu opcijukoja mu donosi najvecu vrednost pa vazi

d[i][j] = max(a[i] + s[i+ 1][j]− d[i+ 1][j], a[j] + s[i][j − 1]− d[i][j − 1]).

Broj stanja je O(n2) a kako trosimo O(1) operacija po stanju, ukupna vremenska i memorijskaslozenost algoritma je O(n2). Ovde treba obratiti paznju da su za racunanje stanja d[i][j] potrebnasva stanja d[x][y] za i ≤ x ≤ y ≤ j. Prema tome matricu d treba racunati ”dijagonalno” – prvoglavnu dijagonalu (d[i][i]) zatim redom ostale dijgonale gore–desno (d[i][i+ 1], d[i][i+ 2], ...).

Solve(n, a)

napraviti matricu s[][] (* ili niz prefiksnih suma *)

for i ← 1 to n do

d[i][i] ← a[i]

for k ← 1 to n - 1 do

for i ← 1 to n - k do

j ← i + k

d[i][j] ← max(a[i] + s[i+1][j] - d[i+1][j], a[j] + s[i][j-1] - d[i][j-1])

return d[1][n]

12. TODO

13. TODO

14. TODO

15. TODO

Page 90: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Glava 8

Backtracking

8.1 Teorija

Backtracking je algoritamska tehnika za resavanje siroke klase problema koja se intuitivno mozeopisati kao isprobavanje svih mogucih slucaja. Preciznije, generisu se sva potencijalna resenja(uglavnom rekurzijom) i za svako od njih se proveri da li je trazeno resenje (tj. da li zadovoljavasve zadate uslove).

Iako se ova tehnika moze primeniti na siroku klasu problema, ocigledna mana je njena neefikas-nost – vremenska slozenost zavisi od broja potencijalnih resenja sto je skoro uvek eksponencijalnopo parametrima problema. Zbog toga ovu tehniku treba primenjivati samo kada ne umemo pronacialgoritam polinomijalne slozenosti za dati problem.

Primeri primene backtracking tehinke:

• Imamo konacan skup tegova datih masa i potrebno je odrediti da li se nekom njihovomkombinacijom moze dobiti ukupna masa od W kilograma; jedan pristup je generisati svemoguce podskupove ovih tegova, izracunati za svaki od njih ukupnu tezinu i ukoliko barjedan podskup daje u zbiru W , odgovor je potvrdan.1

• Resavanje date Sudoku table; jednostavno probamo sva moguca popunjavanja (ciframa 0-9)nepopunjenih polja i proverimo da li neko od njih zadovoljava uslove o zbirovima.

• Provera da li u datom grafu postoji (prost put) koji sadrzi sve cvorove (Hamiltonov put);generisemo sve moguce rasporede (svih) cvorova i za svaki raspored proverimo da li su svakadva uzastopna cvora u njemu povezana granom.

• Sortiranje niza; jedno moguce resenje je generisati sve moguce rasporede (permutacije) ele-menata ovog niza i za svaki od njih proveriti da li je sortiran.2

Prilikom resavanja problema backtracking-om, generisanje svih potencijalnih resenja se uglavnomsvodi na generisanje svih podskupova ili generisanje svih permutacija nekog skupa (ili varijacije natemu).

Generisanje podskupova

Problem 8.1 Dat je skup S = 1, 2, . . . , n. Ispisati sve podskupove skupa S.

1Ovo se moze uraditi koristeci dinamicko programiranje ali tada slozenost zavisi i od vrednosti W sto moze bitiproblem ako je W veliko ili iracionalan broj.

2Naravno, ovo je jako neefikasno resenje slozenosti Ω(n!) gde je n duzina niza; od ranije znamo da sortiramo ovajniz u slozenosti O(n logn).

89

Page 91: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 90

Poznato je da skup od n elemenata ima 2n podskupova. Ideja algoritma je sledeca: krenucemood broja 1, razlikovati 2 slucaja (uzimamo ga u podskup ili ne) i za svaki od slucajeva se rekurzivnogranati (sledi broj 2, pa broj 3 itd. do n). Za ovo cemo koristiti pomocnu rekurzivu funkciju F kojapamti na kom smo trenutno elementu (argument k) a u globalnom nizu mark pamtimo da li smouzeli odgovarajuce elemente ili ne (na kraju se generisani podskup sastoji samo od onih elemenatai za koje je mark[i] = true).

F(k, n) (* pomocna f-ja, trenutno smo na elementu k *)

if (k > n) (* uslov za kraj, generisan je jedan podskup; *)

for i ← 1 to n do

if (mark[i] = true)

print i

print new line

mark[k] ← false

F(k + 1, n) (* nastavi generisanje podskupova koji ne sadrze k *)

mark[k] ← true

F(k + 1, n) (* nastavi generisanje podskupova koji sadrze k *)

Solve(n)

mark ← false (* nije neophodno ali je dobra praksa *)

F(1, n)

Slozenost generisanja svih podskupova je O(1 + 2 + 22 + . . . + 2n) = Θ(2n) a ukoliko za svakigenerisani skup (u delu ”if (k > n)”) radimo dodatnih O(f(n)) posla, ukupna slozenost algoritma jeO(f(n) · 2n); u prethodnom slucaju je f(n) = O(n) jer prolazimo kroz sve elemente pa je slozenostO(n · 2n).

Prethodni pseudo-kod predstavlja genericku implementaciju generisanja svih podskupova; uvecini slucajeva, dovoljno je samo promeniti deo ”if (k > n)” (tj. ubaciti proveru resenja/podskupaumesto, u ovom slucaju, ispis podskupa).

Generisanje permutacija

Problem 8.2 Dat je skup S = 1, 2, . . . , n. Ispisati sve permutacije skupa S.

Poznato je da postoji tacno n! permutacija skupa od n elemenata. Ideja algoritma je sledeca:krenucemo od permutacije p = (1, 2, . . . , n) a zatim, redom (od prve pozicije), probacemo davrednost na k-toj poziciji u nizu p razmenimo sa svim mogucim vrednostima na pozicijama k, k +1, . . . , n. Za svaku takvu razmenu odradicemo rekurzivni poziv za k+1 a na kraju tog poziva cemo”ponistiti razmenu” kako bismo dobili nove permutacije. Koristimo pomocnu rekurzivnu funkciju Pkoja pamti na kojoj smo trenutno poziciji i koristi globalni niz p (na kraju je generisana permutacijaba s ona koja se nalazi u nizu p).

P(k, n) (* pomocna f-ja, trenutno smo na k-toj poziciji *)

if (k > n) (* uslov za kraj, generisana je jedna permutacija *)

for i ← 1 to n do

print p[i]

print new line

for i ← k to n do

swap(p[k], p[i])

P(k + 1, n) (* generisanje permutacija koje na k-tom mestu sadrze vrednost p[i] *)

swap(p[k], p[i]) (* obavezno vratiti nazad *)

Solve(n)

for i ← 1 to n do

Page 92: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 91

p[i] ← i

P(1, n)

Slozenost generisanja svih permutacija je O(n+ n(n− 1) + n(n− 1)(n− 2) + . . .+ n!) = Θ(n!)a ukoliko za svaku generisanu permutaciju (u delu ”if (k > n)”) radimo dodatnih O(f(n)) posla,ukupna slozenost algoritma je O(f(n) · n!); u prethodnom slucaju je f(n) = O(n) jer prolazimokroz sve elemente pa je slozenost O(n · n!).

Prethodni pseudo-kod predstavlja genericku implementaciju generisanja svih permutacija; uvecini slucajeva, dovoljno je samo promeniti deo ”if (k > n)” (tj. ubaciti proveru resenja/permutacijeumesto, u ovom slucaju, ispis permutacije).

Branch and bound

Branch and bound (optimizacija pretrage odsecanjem) je algoritamska tehnika koja se koristi pri-likom backtracking-a i sastoji se u tome da prilikom svake (rekurzivne) nadogradnje trenutnogresenja (uglavnom podskupa ili permutacije) proverimo da li ima smisla nastaviti generisanje ilivec u ovom trenutku resenje ne zadovoljava odredene parametre; ukoliko je ovo drugo slucaj, ne nas-tavljamo generisanje (”secemo” odgovarajucu granu rekurzije) i, samim tim, stedimo na slozenosti.

Ova tehnika se najcesce implementira dodavanjem par ”if”-ova u delu neposredno pre rekurzivnogpoziva.

Na primer, ukoliko hocemo da neefikasno neopadajuce soritramo niz generisanjem svih per-mutacija njegovih elemenata, umesto da samo na kraju proveravamo da li je svaka permutacijasoritrana, mozemo u svakom koraku proveriti da li je trenutni element na k-toj poziciji veci ilijednak od onog na (k − 1)-oj i ne nastavljati rekurziju ako to nije slucaj. Npr. ako smo pocelida generisemo permutaciju u kojoj za prva dva elementa vazi da je prvi veci od drugog, jasno jeda nema smisla nastavljati sa daljim generisanjem permutacije i mozemo ustedeti ogroman brojrekurzivnih poziva.

Iako u praksi branch and bound tehnika moze znacajno da ubrza backtracking, slozenost skorouvek ostaje kao i pre (uglavnom eksponencijalna).

Page 93: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 92

8.2 Zadaci

Zadatak 1. Na gomili se nalazi n kamena; i-ti kamen je tezak wi grama. Rasporediti kamenje udve grupe (svaki kamen mora pripadati nekoj grupi) tako da je razlika tezina izmedu grupa mini-malna (stampati samo razliku). Trazi se resenje vremenske slozenosti O(n · 2n).

Ulaz Izlazn = 5

5 8 13 27 14

3

(Npr. 8 i 27 u jednoj grupi, 5, 13 i

14 u drugoj.)

Zadatak 2. Dat je celobrojni niz a duzine n i prirodan broj k. Odrediti na koliko nacina mozemoispremestati elemente niza a tako da novodobijeni niz ima tacno tacno k ”vrhova”. Element nizaje ”vrh” ako je strogo veci od svojih suseda (svaki element niza ima dva ili jednog suseda). Trazise resenje vremenske slozenosti O(n · n!).

Ulaz Izlazn = 4 k = 2

10 20 55

2

(20, 10, 55) i (55, 10, 20)

Zadatak 3. Dat je skup od n prirodnih brojeva. Koliko najvise elemenata ovog skupa mozemoizabrati tako niko od izabranih elemenata ne deli neki drugi izabrani element? Trazi se resenje vre-menske slozenosti O(n2 · 2n). Programer Pera tvrdi da se ovo moze uraditi i u slozenosti O(n · 2n),da li mu verujete?

Ulaz Izlazn = 6

5 1 4 22 6 18

4

(npr. 6, 22, 5 i 4)

Zadatak 4. Na koliko nacina se n dama moze postaviti na sahovsku tablu dimenzija n × n takoda se nikoje dve ne tuku? Trazi se resenje vremenske slozenosti O(n2 · n!).

Ulaz Izlazn = 8 92

Zadatak 5. Dat je skup od n prirodnih brojeva ai. Potrebno je odrediti da li je moguce odabratineki podskup ovog skupa tako da je suma izabranih brojeva jednaka m.

a) Kako mozemo resiti ovaj problem dinamickim programiranjem i u kojoj slozenosti?

b) Resiti ovaj problem klasicnim backtracking-om u O(2n) ali dodati sto vise uslova tako da seizbegnu nepotrebni rekurzivni pozivi.

c) Smisliti algoritam koji resava ovaj problem u slozenosti O(n·2n2 ) tako sto sve elemente podeli u

dva podskupa velicine n2 , za svaki od njih generise sve moguce zbirove i na kraju iskombinuje.

Zadatak 6. Srecan broj je onaj broj koji u svom dekadnom zapisu sadrzi samo cifre 4 i 7(npr. brojevi 747, 44, 7 su srecni dok brojevi 174, 42, 23 nisu). Za date prirodne brojeve A iB (A ≤ B), ispisati koliko ima srecnih brojeva u segmentu [A,B]. Trazi se resenje vremenskeslozenosti O(Blog10 2)3.

3Podsetimo se da je Blog10 2 = 2log10 B

Page 94: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 93

Ulaz IzlazA = 100 B = 500 4

Zadatak 7. Dat je graf sa n cvorova i m grana. Odrediti da li u ovom grafu postoji prost ciklusvelicine n (tj. da li je moguce obici svaki cvor tacno jednom i vratiti se u pocetni). Trazi se resenjevremenske slozenosti O(m+ n · n!).

Ulaz Izlazn = 4 m = 5

1 3

3 4

4 1

2 1

2 4

DA

(1 - 3 - 4 - 2 - 1)

Zadatak 8. Programer Pera zeli da ispise sve podskupove datog skupa S = 1, 2, . . . , n kojiimaju tacno m elemenata. Jedan od nacina da to uradi je da generise sve podskupove i da na krajuproveri da li je dati podskup velicine m; slozenost ovog pristupa je O(n ·2n). Medutim Pera zna dam-to elementnih podskupova skupa od n elemenata ima

(nm

)i zeli algoritam slozenosti O(n ·

(nm

))

tj. da generise iskljucivo podskupove velicine m a ne sve njih. Mozete li mu pomoci?

Zadatak 9. Dato je n prirodnih brojeva ai i prirodan broj x. Proveriti da li je moguce poredatiove brojeve u niz i ubaciti izmednju njih n− 1 racunskih operacija +, −, ∗, / tako da taj izraz imavrednost x. Radi jednostavnosti, pretpostaviti da se operacije uvek izvrsavaju s leva na desno bezprioriteta (npr. 1 + 2 ∗ 3 je 9 a ne 7) i smatrati da je ”/” - celobrojno deljenje. [ Razmisliti kakobismo pronasli resenje u pravoj igri Moj Broj. ]

Ulaz Izlazn = 5 x = 8

2 9 4 5 6

5 - 2 * 6 / 9 * 4

Zadatak 10. Implementirati sto efikasniji backatracking algoritam koji resava Sudoku i procenitimu slozenost. Kao ulaz je zadata matrica 9 × 9 u kojoj su neka polja popunjena dok nule pred-stavljaju prazna polja. Kao izlaz, vratiti ispravno popunjenu Sudoku slagalicu (ukoliko ima viseresenja, stampati bilo koje).

Ulaz Izlaz5 3 0 0 7 0 0 0 0

6 0 0 1 9 5 0 0 0

0 9 8 0 0 0 0 6 0

8 0 0 0 6 0 0 0 3

4 0 0 8 0 3 0 0 1

7 0 0 0 2 0 0 0 6

0 6 0 0 0 0 2 8 0

0 0 0 4 1 9 0 0 5

0 0 0 0 8 0 0 7 9

5 3 4 6 7 8 9 1 2

6 7 2 1 9 5 3 4 8

1 9 8 3 4 2 5 6 7

8 5 9 7 6 1 4 2 3

4 2 6 8 5 3 7 9 1

7 1 3 9 2 4 8 5 6

9 6 1 5 3 7 2 8 4

2 8 7 4 1 9 6 3 5

3 4 5 2 8 6 1 7 9

Page 95: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 94

8.3 Resenja

1. Probacemo sve moguce podele kamenja na dve grupe i izabrati onu sa minimalnom razlikomtezina. Dovoljno je generisati sve moguce podskupove skupa kamenja jer svaki od njih odredujepodelu: u jednu grupu ide kamenje iz generisanog podskupa a u drugu preostalo kamenje. Vremen-ska slozenost ovog pristupa je O(n · 2n) jer za svaki od 2n podskupova racunamo razliku u podelitako sto prodemo kroz svaki kamen; memorijska slozenost je O(n).

F(k, n) (* pomocna f-ja za generisanje podskuova *)

if (k > n) (* generisan je jedan podskup *)

diff ← 0 (* sadrzace razliku tezina izmedju prve i druge grupe *)

for i ← 1 to n do

if (mark[i] = true)

diff ← diff + w[i]

else

diff ← diff - w[i]

sol ← min(sol, |diff|) (* globalna promenljiva, trenutno najbolje resenje *)

mark[k] ← false

F(k + 1, n) (* nastavi generisanje podskupova koji ne sadrze k *)

mark[k] ← true

F(k + 1, n) (* nastavi generisanje podskupova koji sadrze k *)

Solve(n)

sol ← ∞mark[] ← false

F(1, n)

return sol

Zadatak je moguce uraditi i u slozenosti O(2n) tako sto ”usput” pamtimo trenutnu vrednostpromenljive ”diff” tj. trenutnu razliku izmedu grupa umesto da na kraju uvek prolazimo krozceo niz.

F2(k, n, diff) (* diff je trenutna vrednost razlike izmedju grupa *)

if (k > n) (* generisan je jedan podskup *)

sol ← min(sol, |diff|) (* globalna promenljiva, trenutno najbolje resenje *)

F(k + 1, n, diff - w[k]) (* w[k] ide u drugu grupu, razlika se smanjuje za w[k] *)

F(k + 1, n, diff + w[k]) (* w[k] ide u prvu grupu, razlika se povecava za w[k] *)

Solve2(n)

sol ← ∞F2(1, n, 0)

return sol

2. Generisemo sve moguce permutacije niza a i jednostavno prodemo kroz svaku od njih i prebro-jimo vrhove. Vremenska slozenost ovog algoritma je O(n · n!) a memorijska O(n).

Prilikom generisanja permutacije mozemo direktno menjati niz a (umesto niza p) a mozemo idalje koristiti niz p ali onda niz a na kraju zapravo izgleda a[p1], a[p2], . . ., a[pn]. Ovde koristimoprvi pristup.

P(k, n) (* pomocna f-ja *)

if (k > n) (* uslov za kraj, generisana je jedna permutacija *)

vrhCount ← 0 (* brojimo vrhove u trenutnoj permutaciji niza a *)

for i ← 1 to n do

if (a[i] > a[i - 1] and a[i] > a[i + 1])

Page 96: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 95

vrhCount ← vrhCount + 1

if (vrhCount = k)

sol ← sol + 1

for i ← k to n do

swap(a[k], a[i])

P(k + 1, n) (* generisanje permutacija koje na k-tom mestu sadrze vrednost a[i] *)

swap(a[k], a[i]) (* obavezno vratiti nazad *)

Solve(n, k, a[])

sol ← 0

a[0] ← -∞ (* za laksu proveru vrha *)

a[n + 1] ← -∞ (* za laksu proveru vrha *)

P(1, n)

return sol

3. Generisemo sve podskupove datog skupa, za svaki od njih proverimo da li zadovoljava uslovezadatka (proverimo deljivost svaka dva njegova elementa) i od svih podskupova koji zadovoljavajuuslove zadatka, uzimamo najveci. Vremenska slozenost je O(n2 ·2n) jer za svaki podskup prolazimokroz svaka dva njegova elementa a memorijska slozenost je O(n).

F(k, n) (* pomocna f-ja *)

if (k > n)

numElements → 0 (* brojimo elemente trenutnog podskupa *)

for i → 1 to n do

if (mark[i] = true)

numElements → numElements + 1

ok → true (* proveravamo da li zadovoljava uslov *)

for i ← 1 to n - 1 do

for j → i + 1 to n do

if (mark[i] and mark[j] and (a[i] | a[j] or a[j] | a[i]))

ok = false

if (ok = true)

sol ← max(sol, numElements) (* globalna promenljiva *)

mark[k] ← false

F(k + 1, n) (* nastavi generisanje podskupova koji ne sadrze k *)

mark[k] ← true

F(k + 1, n) (* nastavi generisanje podskupova koji sadrze k *)

Solve(n)

sol ← 0mark[] ← false

F(1, n)

return sol

Zaista je moguce uraditi ovaj zadatak i u slozenosti O(n ·2n); npr. pre drugog poziva F (k+1, n)(kada uzimamo k-ti element), mozemo odmah proci kroz sve trenutno uzete elemente (one za kojeje u tom trenutku mark[i] = true) i proveriti da li neki od njih deli trenutni (ili on njih) i samoukoliko to nije slucaj, pozvati F (k + 1, n). Na ovaj nacin, kada dodemo do kraja, ne moramoproveravati ovaj uslov deljivosti jer je on ”usput” proveren.

4. TODO

Page 97: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 96

5. Za deo a), ovaj problem mozemo resiti dinamickim programiranjem kao Zadatak 8 iz oblastiDinamickog programiranja. Nije nam neophodno da pamtimo najmanji broj sabiraka kao u tomzadatku (ali mozemo), dovoljno je i da rezultat stanja bude samo logicka promenljiva (moze ili nemoze). Slozenost takvog algoritma je O(nm).

Za deo b), neka od korisnih ubrzanja su:

1) Pamtimo trenutnu sumu s (slicno kao i u drugom resenju prvog zadatka) a ne racunamo jeispocetka svaki put kada generisemo podskup

2) Pre nego sto napravimo rekurzivni poziv sa izborom da ne uzmemo k-ti element proverimoda li je suma preostalih elemenata dovoljna da dodemo do vrednosti m i bez k-tog elementa(ako ne, ne granamo se tamo)

3) Pre nego sto napravimo rekurzivni poziv sa izborom da uzmemo k-ti element proverimo dali tada trenutna suma prelazi vrednost m (ako da, ne granamo se tamo jer su svi elementipozitivni)

4) Pamtimo globalnu promenljivu da li je resenje nadeno i, ukoliko jeste, odmah napustamorekurziju bez dodatnih grananja.

U pseudo-kodu, currSum je trenutna suma izabranih elemenata a remainSum je suma svih pre-ostalih elemenata u trenutku poziva (ak + ak+1 + . . . + an) tj. koliko najvise mozemo povecatitrenutnu sumu. Primetimo da nema potrebe za nizom mark niti proverom if k > n; zaista, kadase dode do kraja, uci ce se u bar jednu od poslednje 2 if naredbe.

F(k, currSum, remainSum)

if (currSum = m)

solFound ← true

if (solFound = true)

return (* ako smo vec nasli resenje, kraj *)

if (currSum > m)

return (* prekoracili smo sumu m, nema smisla ici dalje *)

if (currSum + remainSum < m)

return (* sa trenutnim izborom nikako ne mozemo dostici m, nema smisla ici dalje *)

F(k + 1, currSum, remainSum - a[k]) (* biramo da ne uzmemo k-ti element *)

F(k + 1, currSum + a[k], remainSum - a[k]) (* biramo da uzmemo k-ti element *)

Solve(n, m, a[])

solFound ← false

F(1, 0, a[1] + a[2] + ... + a[n])

return solFound

6. Trivijalno resenje: za svaki broj od A do B proverimo da li se sastoji samo od cifara 4 i 7 i,ukoliko da, povecamo odgovarajuci brojac. Slozenost ovog pristupa je O((B −A) logB) jer ispitu-jemo B−A brojeva i za svaki od njih prolazimo kroz sve njegove cifre a poznato je da je broj cifaraprirodnog broja n upravo Θ(log10 n).

Medutim, mozemo i bolje – intuitivno je jasno da srecnih brojeva ne vecih od B ima mnogomanje od B (mnogo je vise brojeva koji sadze i neke druge cifre a ne iskljucivo 4 i 7). Zato cemo

Page 98: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Nikola Milosavljevic - Skripta iz Dizajna i analize algoritama 97

generisati iskljucivo srecne brojeve ne vece od B, za svaki od njih proveriti da li je veci ili jednak Ai povecati brojac. Za ovo koristimo rekurzivnu funkciju F (x) – ukoliko znamo da je x srecan broj,naredne srecne brojeve dobijamo dodavanjem cifre 4 ili 7 na kraju broja x (tj. 10x+ 4 i 10x+ 7) ina taj nacin ne propustamo nijedan srecan broj.

F(x, A, B) (* pomocna f-ja *)

if (x > B) (* ako smo premasili broj B *)

return

if (x ≥ A) (* ako nismo, da li je x u [A, B]? *)

sol ← sol + 1

(* nastavi da generises srecne brojeve *)

F(10 * x + 4, A, B)

F(10 * x + 7, A, B)

Solve(A, B)

sol ← 0F(0, A, B)

return sol

Slozenost ovog algoritma je O(broj srecnih brojeva ne vecih od B). Kako ovi srecni brojevi moguimati najvise log10B cifara a za svaku cifru samo 2 mogucnosti (4 ili 7), njihov broj je 21 + 22 +. . . 2log10B = Θ(2log10B) = Θ(Blog10 2) sto je i slozenost algoritma.4

7. TODO

8. TODO

9. TODO

10. TODO

4Podsetimo se da za bilo koje konstantne osnove a i b vazi loga n = Θ(logb n) pa su log2B i log10B asimptotskiekvivalentni. Medutim to ne znaci da se ova ekvivalentnos odrzava i kada se ovi logaritmi nadu kao izlozioci nekogizraza; npr. cloga n 6= Θ(clogb n) i zato nam je u ovom slucaju bitno sta je osnova logaritma.

Page 99: Skripta iz Dizajna i analize algoritama (radna verzija)nasport.pmf.ni.ac.rs/materijali/2810/DAA_Skripta.pdfSkripta iz Dizajna i analize algoritama (radna verzija) Nikola Milosavljevi

Literatura

[1] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein, Introduction to Algorithms, Second Edi-tion, The MIT Press, 2001.

[2] Sedgewick R, Algorithms, Addison-Wesley, 1984.

[3] Zivkovic M, Algoritmi, Matematicki fakultet, Beograd, 2000

98