pohlepni (greedy) algoritmi -...
TRANSCRIPT
Pohlepni
(greedy) algoritmi
Marko Mišić[email protected] Guberinić[email protected] Ivanović[email protected]
Elektrotehnički fakultet Univerziteta u BeograduOdsek za softversko inženjerstvoPraktikum iz programiranja 2
Tipovi problema
Problemi odlučivanja Utvrđivanje da li rešenje postoji ili ne Primer: da li postoji put
između dva čvora u zadatom grafu?
Problemi pretraživanja Pronalaženje rešenja ukoliko ono postoji Primer: odrediti put
između dva čvora u zadatom grafu
Problemi optimizacije Pronalaženje najboljeg rešenja
za dati skup rešenja za ulazne podatke Primer: odrediti najkraći put
između dva čvora u zadatom grafu
Tipovi algoritama
Rešavanje problema grubom silom (brute force)
Jednostavni rekurzivni algoritmi
Divide and conquer algoritmi
Backtracking algoritmi
Pohlepni (greedy) algoritmi
Dinamičko programiranje
Branch and bound algoritmi
Randomized / Monte Carlo algoritmi
Šta su pohlepni (greedy) algoritmi?
Pohlepni (greedy) algoritam je svaki algoritam koji rešava problem biranjem lokalno optimalnog rešenja u svakom koraku Nadajući se da će na taj način doći
do globalnog optimuma
Odluka se donosi inkrementalno u malim koracima, ali nema nikakvog backtracking-a Ne vodi se računa o posledicama ranijih loših izbora Odluka u svakom koraku vodi
ka popravljanju trenutnog stanju i pomeranju ka cilju
Odluka se najčešće donosi na osnovu fiksiranih i jednostavnih pravila koja su bazirana na prioritetima
Osobine pohlepnih algoritama (1)
Pohlepni algoritmi su pogodni za rešavanje određenih klasa optimizacionih problema
Problemi moraju imati optimalnu substrukturu Optimalno rešenje problema
se sastoji od optimalnih rešenja potproblema
Problemi moraju imati osobinu pohlepnosti (greedy property) Ako napravimo izbor koji nam se čini dobar u datom koraku,
a rešimo potproblem kasnije, uvek dolazimo do globalno optimalnog rešenja
Praktično, nikada ne razmatramo ponovo prethodne izbore
Svaki pohlepan algoritam zahteva dokaz korektnosti Ili postoji mogućnost da je rešenje suboptimalno Najčešće nije lako izvesti dokaz!
Osobine pohlepnih algoritama (2)
Prednosti:
Najčešće su jednostavni za dizajniranje
Jednostavni za implementaciju
Brzo se izvršavaju
Nedostaci:
Vrlo često pohlepni algoritmi ne funkcionišu ili dovode do suboptimalnog rešenja
Često mnogo načina da se reši jedan problem, ali ne postoji strukturiran način da se utvrdi koji je od njih je efikasan
Primene pohlepnih algoritama
Biranje aktivnosti i sl. Activity selection problem Interval covering Load Balancing
Grafovski algoritmi Prim, Kruskal, Dijkstra, Huffman-ovo kodiranje,
topološko sortiranje
Problem trgovačkog putnika Traveling salesman problem
Problem “razlomljenog” ranca Continuous knapsack problem Problem prebrojavanja novca
Problem prebrojavanja novca (1)
Pretpostavite da treba da izbrojite određenu sumu novca u dolarima korišćenjem najmanjeg mogućeg broja novčanica i novičića (apoena)
U ovom slučaju se može primeniti pohlepni algoritam koji u svakom koraku uzima najveći mogući apoen takav da ukupna do tada izbrojana suma ne prelazi zadatu
Primer: da bi izbrojali $6.39, možemo koristiti sledeće apoene: Novčanicu od $5 Novčanicu od $1, da bi izbrojali $6 Novčić od 25¢, da bi izbrojali $6.25 Novčić od 10¢, da bi izbrojali $6.35 Četiri novčića od 1¢, da bi izbrojali $6.39
Za dolarske novčanice, može se dokazati da pohlepni algoritam uvek daje optimalno rešenje Da li je tako i za dinare?
Problem prebrojavanja novca (2)
U nekom zamišljenom monetarnom sistemu, “perperi” se kuju u novčićima od 1p, 7p i 10p
Ako se koristi pohlepni algoritam za brojanje 15 perpera, dobija se sledeće rešenje: Jedan novčić od 10 perpera Pet novčića od 1 perpera, za ukupno 15 perpera Potrebno je 6 novčića
Bolje rešenje bi bilo da se koriste dva novčića od 7 perpera i jedan novčića od 1 perpera Potrebna su samo tri novčića
Pohlepni algoritam pronalazi rešenje, ali ono nije optimalno rešenje Mora se upotrebiti neki drugi algoritam
Biranje aktivnosti (1)
Problem biranja aktivnosti je problem raspoređivanja resursa između više konkurentnih aktivnosti koje se nadmeću za njega
Postavka problema:
Neka je dat skup od n aktivnosti sa startnim vremenom si i završnim vremenom fi za svaku od aktivnosti
Potrebno je pronaći skup aktivnosti maksimalne veličine takav da su aktivnosti međusobno kompatibilne
Aktivnosti su kompatibilne ukoliko se ne preklapaju
Biranje aktivnosti (2)
Kako izabrati aktivnosti?
Prema najranijem vremenu otpočinjanja
Prvo kraće aktivnosti
Prvo aktivnosti koje se najmanje preklapaju sa drugima
Algoritam optimalan ukoliko se aktivnosti biraju po rastućem vremenu završetka
Biranje aktivnosti (3)
Pohlepni algoritam za problem biranja aktivnosti
I Sort the input activities by increasing finishing timef1 ≤ f2 ≤ . . . ≤ fn
II Call GREEDY-ACTIVITY-SELECTOR (Sif)n = length [s]A={1}j = 1FOR i = 2 to n do
if si ≥ fjthen A= A U {i}
j = iReturn A
Postoji dokaz korektnosti:http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/Greedy/actSelectionGreedy.htm
https://www.topcoder.com/community/data-science/data-science-tutorials/greedy-is-good/
Analiza pohlepnih algoritama
Pohlepni algoritam tipično pravi približno n izbora za problem veličine n Prvi i poslednji izbor su možda nametnuti
Očekivano vreme izvršavanje je O(n*O(izbor(n))), gde je izbor(n) funkcija za izbor između n objekata
Brojanje novca: mora da pronađe najveći upotrebljivi apoen među K dostupnih apoena Za konstantno K, vreme pronalaženja je O(k) = O(1)
Biranje aktivnosti: mora da sortira n aktivnosti pre nego što napravi n izbora To zahteva O(nlogn) + O(n) = O(nlogn)
Optimizacija sortiranja
Pohlepni algoritmi često zahtevaju podatke sortirane po nekom kriterijumu tokom svog rada
Bitno je koristiti algoritam sa minimalnom vremenskom složenošću Poželjno O(nlogn) Quick sort ili merge sort ukoliko je
opseg podataka nepoznat ili se mora sortirati poređenjem
Counting sort ili radix sort ukoliko je opseg ulaznih podataka ograničen
Pogledati: http://rti.etf.bg.ac.rs/rti/ri3sp/materijali/IR2ASP_Predavanja_IV.pdf
Čamci – postavka (1)
Stanovnici jednog malog sela bave se ribarenjem i programiranjem. Nakon završenog ribolova, ribari svoje čamce ostavljaju duž jedne obale uskog kanala. Svaki ribar ima jedan čamac i sopstveni stubić negde duž kanala koji mu služi za privezivanje čamca, pri čemu sme da priveže svoj čamac isključivo za svoj stubić. Čamci moraju biti ostavljeni tako da svaki čamac bude tačno uz svoj stubić, što znači da stubić mora biti negde neposredno pored čamca, tj. između dva kraja čamca (dozvoljeno je i da stubić bude neposredno pored nekog kraja čamca).
Čamci – postavka (2)
Pošto je kanal uzan, najviše jedan čamac se može nalaziti na svakom poprečnom preseku kanala, odnosno svi čamci moraju biti privezani neposredno do obale. Čamci se mogu dodirivati svojim krajevima.
Zbog ovakvog vezivanja čamaca nije obavezno moguće da čamci svih ribara budu vezani istovremeno. Zato su ribari zamolili svoje prijatelje programere da im izračunaju koliko najviše čamaca može istovremeno biti vezano. Međutim, programerima je ovo bio pretežak zadatak, pa su i oni počeli da se bave ribarenjem, a zadatak su prepustili vama.
Čamci – postavka (3)
Dozvoljena vezivanja Nedozvoljeno vezivanje
Primer: {(5, 9), (2, 17), (6, 10), (3, 11),
(2, 16), (4, 13), (5, 6)} Prvi broj – dužina čamca,
drugi broj položaj stubića i-tog ribara
Rešenje: 5 Objašnjenje:
Najviše je moguće da 5 čamaca bude istovremenovezano, na primer čamci {1, 2, 4, 5, 7}.
Čamci - ideja
Postavimo čamac na najleviji stubić tako da mu je desna ivica na stubiću
Za svaki sledeći stubić proverimo da li možemo da postavimo čamac tako da se ne udari u prethodni?
Ako može: postavimo čamac
Ako ne može: pogledamo da li ako bi izbacili prethodni čamac novi čamac zauzimao manje mesta
Ako da: zamenimo stari čamac novim
Čamci – pseudokod (1)
Potrebne promenljive i strukture podataka:
niz l[i] - dužina i-tog čamca
niz p[i] - pozicija i-tog stubića
m - trenutni broj postavljenih čamaca
l - leva ivica poslednjeg postavljenog čamca
r - desna ivica poslednjeg postavljenog čamca
Čamci – pseudokod (2)
Sortirati niz parova (l[i], p[i]) tako da bude rastući po p[i]m = 1 r = p[1]for i = 2 to n
if p[i] ≥ rl = rr = max(p[i], r + l[i])inc(m)
else r = min(r, max(p[i], l + l[i])
m je traženi maksimalan broj čamaca
Pogledati: http://www.spoj.com/problems/QUEST5/http://staritakprog.dms.rs/takmicenja/2006.2.rep/5.camci/
task.html
Filmovi – postavka (1)
Maliom Dragančetu iz unutrašnjosti su roditelji smanjili džeparac. Kako je Draganče kompjuterski mag u svom mestu, on je rešio da iskoristi svoju veliku kolekciju DVD filmova i odlučio da prodaje filmove po niskim cenama. Svaki film se nalazi na jednom DVD-u, a na Dragančetovom hard disku može stati najviše k filmova.
Filmovi – postavka (2)
Procedura rezanja je sledeća: ukoliko se traženi film nalazi na hard disku, Draganče odmah počinje sa rezanjem; u suprotnom on mora da nađe odgovarajući DVD i presnimi ga na hard disk. Ako na disku nema slobodnog prostora, on mora da obriše neki film. Traženje DVD-a i presnimavanje iziskuje puno vremena, i zato Draganče želi da smanji taj broj. Na početku je njegov disk prazan.
On je napravio spisak poručenih filmova i zna tačno redosled n kupaca koji dolaze da nasnime omiljeni film. Draganče je uspeo da minimizira broj prebacivanja filmova na HDD (a samim tim i čekanje kupaca). Da li i vi možete da izračunate koliko će najmanje puta Draganče ipak morati da presnimi neki film na hard disk?
Filmovi – postavka (3)
N = 5, K = 2
N – broj naručenih filmova, K – kapacitet diska
Filmovi = {1, 2, 2, 4, 1}
Redni brojevi naručenih filmova
Rešenje: 3
N = 10, K = 3
Filmovi = {2, 3, 2, 1, 5, 2, 4, 5, 3, 2}
Rešenje: 6
Filmovi – ideja (1)
Dok imamo mesta na disku, svaki novi film koji već nije na disku dodajemo na disk
Kad ponestane mesta na disku, izbacujemo film koji nam NAJDUŽE neće trebati
Ovaj algoritam je poznat kao “Clairvoyant replacement algorithm” i ima primenu u pravljenju keš memorija
Filmovi – ideja (2)
Potrebne promenljive i strukture podataka:
a[i] – redni broj DVD-a koji se reže u trenutku i
next[i] - kada će sledeći put biti potrebnoponovo narezati DVD sa oznakom a[i]
last[i] - pomoćni niz - gde sam poslednji put video DVD sa oznakom i
cache[i] - DVD sa oznakom i se nalazi na diskui biće ponovo potreban u trenutku cache[i]. Polje ima vrednost -1 ako nam taj DVD nećebiti ponovo potreban ili 0 ukoliko se DVD ne nalazi na disku.
Filmovi - algoritam
Popuniti niz next
Za svaki film
Proveriti da li je trenutno na hard disku
Ako jeste: kraj
Ako nije: da li ima mesta da se snimi na disk?
Ako ne: naći DVD koji se briše
Snimi trenutni DVD na hard disk
Pogledati:
http://staritakprog.dms.rs/takmicenja/2007.1.okr/5.filmovi/task.html
Filmovi - pseudokod (1)
for i = 0 to n - 1
last[a[i]] = -1;
next[i] = N;
for i = 0 to n - 1
if (last[a[i]] <> -1) then
next[last[a[i]]] = i;
last[a[i]] = i;
Filmovi - pseudokod (2)
for i = 0 to n - 1
if (cache[a[i]])
cache[a[i]] = next[i]; continue;
if (brojSlobodnihMesta)
--brojSlobodnihMesta;
cache[a[i]] = next[i];
else
last = dvdKojiSeBriseSaDiska();
cache[last] = 0; cache[a[i]] = next[i];
++brojUpisaNaDisk
Filmovi - dodatna analiza
Kako odrediti koji DVD treba obrisati?
Optimalno rešenje
U max-heapu (prioritetnom redu) držati uređeni par (next[i], a[i])
O(log n)
Radi se na predmetu Algoritmi i strukture podataka
Pogledati: http://rti.etf.bg.ac.rs/rti/ri3sp/materijali/IR2ASP_Predavanja_I.pdfhttp://rti.etf.bg.ac.rs/rti/ri3sp/materijali/IR2ASP_Predavanja_IV.pdf
Suboptimalno rešenje
Proći kroz niz cache i naći najveći element
O(n)
Filmovi - pseudokod (3)
function dvdKojiSeBriseSaDiska()
begin
last = 0; lastN = 0;
for j = 0 to maxDvdId
if (cache[j] > lastN) then
lastN = cache[j];
last = j;
return last;
end
Filmovi – ukupna složenost
Spoljašnjoj petlji se pristupa N puta
Provera da li se DVD trenutno nalazina disku je O(1)
Nalaženje trenutnog elementa je ili O(maxDvdId) ili O(log(cacheSize))
Swap na disk je O(1)
Razumno je pretpostaviti da je maxDvdId ≤ N, kao i da je cacheSize ≤ N
Složenost ili O(N^2) ili O(N log N)
Katanci - postavka
Mali Acko je zaključan u sobi sa N vrata. Na svakim vratima postoji katanac koji se otključava pomoću šifre koja se sastoji od 10 cifara. Inicijalno su svi katanci postavljeni na kombinaciju 0000000000. Vrata se mogu otključavati u bilo kom poretku. Jedna operacija pri otključavanju vrata jeste ciklično inkrementiranje, odnosno dekrementiranje, neke cifre na nekom katancu.
Katanci – postavka (2)
Svaki od katanaca ima jedno specijalno dugme koje omogućava da se na njegovom ulazu postavi kombinacija kojom je otključan neki od prethodno otključanih katanaca. (Ovo se ne računa kao dodatna operacija)
Ako je poznat broj vrata 1 <= N <= 1.000 i ako je poznata kombinacija svakog katanca koliko je minimalno operacija potrebno da bi se sva vrata otključala?
Katanci – postavka (3)
Katanci – ideja
Zadatak se rešavajednostavnim pohlepnim algoritmom Pronađemo katanac koji zahteva
minimalan broj okretanjaod incijilanog stanja do otključavanja
Dodamo ga u skup otključanih katanaca Dodamo taj broj okretanja
na ukupan broj operacija Dok ne otključamo sve katance radimo sledeće:
Od svih katanaca koje nismo otključaliizaberemo onaj za koji nam trebanajmanje operacija da ga otključamo
Ažuriramo ukupan broj operacija iubacimo novootkjučani katanacu skup otključanih katanaca
Katanci – dokaz (1)
Da bi smo pokazalida je predloženo rešenje optimalno moramoposmatrati problem iz ugla teorije grafova: Neka su katanci čvorovi grafa
Neka grane grafa predstavljaju prelaze između stanja katanaca
Neka je težina svake grane (u, v) jednakabroju operacija da se otključa katanac v ukoliko je njegovo stanje postavljeno na u
Graf možemo proširiti sa dodatnim čvoromz(0000000000) da predstavimo osnovno stanje
Katanci – dokaz (2)
Primetimo da za svaki par (u, v) važi:
weight(u, v)=weight(v, u)
Graf predstavlja jedan kompletan neusmeren graf
Kada otključavamo katanac v možemo:
Da ga prvo postavimo na neko stanje prethodno otključanog katanca u
Da ga ostavimo u početnom stanju z i da onda otključamo katanac
Dakle, otključavanje katanca v će povećati ukupan broj operacija:
Za weight(z, v) ili za weight(u, v).
Katanci – dokaz (3)
Da bi smo pronašlinajmanji broj operacijapotrebno je pronaćiminimalno obuhvatno stablo grafa Opisani algoritam uključuje
samo grane sa minimalnom težinom
Predloženo rešenje predstavljaPrimov algoritam za nalaženjeminimalnog obuhvatnog stabla grafa Veoma lako se implementira
u vremenskoj složenosti O(N^2).
Katanci – (pseudo)kod
NZD – postavka (1)
Dat je niz od n prirodnih brojeva. U jednom potezu je dozvoljeno odabrati proizvoljna dva susedna broja u nizu i zameniti ih njihovim zbirom. Ovaj potez možemo ponavljati nad novodobijenim nizovima. Potrebno je primeniti određen broj poteza nad originalnim nizom kako bi se dobilo tačno k brojeva čiji je NZD najveći moguć. Na kraju treba ispisati dobijeni NZD, kao i niz a, nakon izvršenih operacija.
NZD – postavka (2)
Primer:n = 6, k = 3, a = {12, 7, 3, 2, 15, 15} n – broj elemenata u početnom nizu
k – broj elemenata koji treba da ostane na kraju
Rešenje:NZD = 6, a = {12, 12, 30}
Objašnjenje: Ukoliko izvršimo poteze:
{12, 7, 3, 2, 15, 15} -> {12, 10, 2, 15, 15} -> {12, 10, 2, 30} -> {12, 12, 30}
Dobijamo optimalno rešenje
NZD - ideja
Neka je X najveći mogući NZD svih potencijalnih nizova od K elemenata koje možemo dobiti “spajanjem” elemenata niza Kako X deli svaki od tih K članova,
on mora deliti i njihov zbir, a taj zbir upravo predstavnja sumu prvobitnog niza
Sada smo ograničili moguće kandidateza najveći mogući NZD na sve delioce sume niza, što je u najgorem slučaju ~40
Pogledati: http://en.wikipedia.org/wiki/Highly_composite_numberhttp://staritakprog.dms.rs/takmicenja/2012.1.okr/4.nzd/task.html
NZD – ideja (2)
Kako da proverimo za neki broj X da li možemo napraviti niz od tačno K elemenata čiji je NZD jednak X?
Pohlepno
Prolazimo redom po nizu i formiramo grupe uzastopnih elemenata koje su deljive sa X
Sabiramo brojeve redom
Čim dobijemo broj deljiv sa X, uvećamo broj grupa za jedan
Prelazimo na sledeću grupu
NZD – ideja (3)
Primetiti da ako X deli sumu niza, tada niz možemo podeliti na grupe bez ostatka
Ukoliko je broj grupa manji od K:
X ne može biti rešenje
Ukoliko je broj grupa veći ili jednak K:
X može biti rešenje
Dve susedne grupe uvek možemo spojiti u jednu veću, tako da ne narušimo svojstvo da je X NZD tog niza grupa
Postupak se može ponavljati sve dok ne dobijemo tačno K grupa
NZD – (pseudo)kod
Korisni linkovi (1)
Timus: http://acm.timus.ru/
TopCoder:http://www.topcoder.com/
USACO:http://train.usaco.org/
UVa online judge: http://uva.onlinejudge.org/
Sphere online judge: http://www.spoj.com/problems/classical/
Saratov State University: http://acm.sgu.ru
Korisni linkovi (2)
Takmičenja iz programiranja u Srbiji: http://takprog.dms.rs/
Takmičenja iz programiranja u Hrvatskoj: http://hsin.hr/
Codeforces: http://codeforces.com/
Codechef: http://www.codechef.com/
BubbleCup: http://bubblecup.org/
BubbleBee: http://bee.bubblecup.org/