This is an old revision of the document!
Responsabili:
Acestea apar incorporate si in textul laboratorului pentru a facilita parcurgerea cursiva a laboratorului.
În general tehnicile de tip Greedy sau Programare Dinamică (lab04) sunt folosite pentru rezolvarea problemelor de optimizare. Acestea pot adresa probleme în sine sau pot fi subprobleme dintr-un algoritm mai mare. De exemplu, algoritmul Dijkstra pentru determinarea drumului minim pe un graf alege la fiecare pas un nod nou urmărind algoritmul greedy.
Exista însă probleme care ne pot induce în eroare. Astfel, există probleme în care urmărind criteriul Greedy nu ajungem la soluția optimă. Este foarte important să identificăm cazurile când se poate aplica Greedy și cazurile când este nevoie de altceva. Alteori această soluție neoptimă este o aproximare suficientă pentru ce avem nevoie. Problemele NP-complete necesita multă putere de calcul pentru a găsi optimul absolut. Pentru a optimiza aceste calcule mulți algoritmi folosesc decizii Greedy și găsesc un optim foarte aproape de cel absolut.
“greedy” = “lacom”. Algoritmii de tip greedy vor să construiască într-un mod cât mai rapid soluția unei probleme. Ei se caracterizează prin luarea unor decizii rapide care duc la găsirea unei soluții potențiale a problemei. Nu întotdeauna asemenea decizii rapide duc la o soluție optimă; astfel ne vom concentra atenția pe identificarea acelor anumite tipuri de probleme pentru care se pot obține soluții optime. În general exista mai multe soluții posibile ale problemei. Dintre acestea se pot selecta doar anumite soluții optime, conform unor Algoritmii greedy se numără printre cei mai direcți algoritmi posibili. Ideea de bază este simplă: având o problema de optimizare, de calcul al unui cost minim sau maxim, se va alege la fiecare pas decizia cea mai favorabilă, fără a evalua global eficiența soluţiei. anumite criterii. Scopul este de a găsi una dintre acestea sau dacă nu este posibil, atunci o soluție cât mai apropiată, conform criteriului optimal impus.
Trebuie înțeles faptul ca rezultatul obținut este optim doar dacă un optim local conduce la un optim global. În cazul în care deciziile de la un pas influențează lista de decizii de la pasul următor, este posibila obținerea unei valori neoptimale. În astfel de cazuri, pentru găsirea unui optim absolut se ajunge la soluții supra-polinomiale. De aceea, dacă se optează pentru o astfel de soluție, algoritmul trebuie însoțit de o demonstrație de corectitudine. Descrierea formală a unui algoritm greedy este următoarea:
// C este mulțimea candidaților function greedy(C) { S ← Ø // în S construim soluția while !solutie(C) and C ≠ Ø x ← un element din C care minimizează/maximizează select(x) C ← C \ {x} if fezabil( S ∪ {x}) then S ← S∪{x} return S }
Este ușor de înțeles acum de ce acest algoritm se numește ”greedy”: la fiecare pas se alege cel mai bun candidat de la momentul respectiv, fără a studia alternativele disponibile în moment respectiv şi viabilitatea acestora în timp.
Dacă un candidat este inclus în soluție, rămâne acolo, fără a putea fi modificat, iar dacă este exclus din soluție, nu va mai putea fi niciodată selectat drept un potențial candidat.
Fie un șir de N numere pentru care se cere determinarea unui subșir de numere cu suma maximă. Un subșir al unui șir este format din elemente (nu neapărat consecutive) ale șirului respectiv, în ordinea în care acestea apar în șir.
Se observa ca tot ce avem de făcut este sa verificam fiecare număr dacă este pozitiv sau nu. În cazul pozitiv, îl introducem în subșirul soluție.
Daca toate numerele sunt negative, solutia este data de cel mai mare numar negativ (cel mai mic in modul).
Se dau mai multe spectacole, prin timpii de start și timpii de final. Se cere o planificare astfel încât o persoană să poată vedea cât mai multe spectacole.
Rezolvarea constă în sortarea spectacolelor crescător după timpii de final, apoi la fiecare pas se alege primul spectacol care are timpul de start mai mare decât ultimul timp de final. Timpul inițial de final este inițializat la $-\inf$ (spectacolul care se termină cel mai devreme va fi mereu selectat, având timp de start mai mare decât timpul inițial).
Solutia va avea urmatoarele complexitati:
Se da un grup de $k$ oameni care vor sa cumpere impreuna $n$ flori. Fiecare floare are un pret de baza, insa pretul cu care este cumparata variaza in functie de numarul de flori cumparate anterior de persoana respectiva. De exemplu daca George a cumparat $3$ flori (diferite) si vrea sa cumpere o floare cu pretul $2$, el va plati $(3 + 1) * 2 = 8$. Practic el va plati un pret proportional cu numarul flori cumparate pana atunci tot de el.
Cerinta: Se cere pentru un numar $k$ de oameni si $n$ flori se cere sa se deterimne care este costul minim cu care grupul poate sa achizitioneze toate cele $n$ flori o singura data.
Observatie: Un tip de floare se cumpara o singura data. O persoana poate cumpara mai multe tipuri de flori. In final in grup va exista un singur exemplar din fiecare tip de floare.
Formal avem $k$ numar de oameni, $n$ numar de flori, $c[i]$ = pretul florii de tip $i$, costul de cumparare $i$ va fi $(x + 1) * c[i]$, unde $x$ este numarul de flori cumparate anterior de persoana respectiva.
Se observa ca pretul efectiv de cumpare va fi mai mare cu cat cumparam acea floare mai tarziu. Daca consideram cazul in care avem o singura persoana in grup observam ca are sens sa cumparam obiectele in ordine descrescatoare(deoarece vrem sa minimizam costul fiecarui tip de flori si aceste creste cu cat cumparam floarea mai tarziu).
De aici, gandindu-ne la versiunea cu $k$ persoane, observam ca ar fi mai ieftin daca am repartiza urmatoarea cea mai scumpa floare la alt individ. Deci impartim florile sortate descrescator dupa pret in grupuri de cate $k$, fiecare individ luand o floare din acest grup si ne asiguram ca pretul va creste doar in functie de numarul de grupuri anterioare.
Solutia va avea urmatoarele complexitati:
Fie $N$ scânduri de lemn, descrise ca niște intervale închise cu capete reale. Găsiți o mulțime minimă de cuie astfel încât fiecare scândură să fie bătută de cel puțin un cui. Se cere poziția cuielor.
Formulat matematic: găsiți o mulțime de puncte de cardinal minim $M$ astfel încât pentru orice interval [ai, bi] din cele $N$, să existe un punct $x$ din $M$ care să aparțină intervalului [ai, bi].
Se observa că dacă $x$ este un punct din $M$ care nu este capăt dreapta al nici unui interval, o translație a lui $x$ la dreapta care îl duce în capătul dreapta cel mai apropiat nu va schimba intervalele care conțin punctul. Prin urmare, exista o mulțime de cardinal minim $M$ pentru care toate punctele $x$ sunt capete dreapta.
Astfel, vom crea mulțimea $M$ folosind numai capete dreapta în felul următor:
Soluția va avea următoarele complexități:
Aspectul cel mai important de reținut este că soluțiile găsite trebuie să reprezinte optimul global și nu doar local. Se pot confunda ușor problemele care se rezolvă cu Greedy cu cele care se rezolvă prin Programare Dinamică (vom vedea saptamana viitoare).
Fie un set cu $ n $ obiecte (care pot fi taiate - varianta continua a problemei). Fiecare obiect $i$ are asociata o pereche ($w_i, p_i$) cu semnificatia:
Gigel are la dispozitie un rucsac de volum infinit, dar care suporta o greutate maxima (notata cu $W$ - weight knapsack).
El vrea sa gaseasca o submultime de obiecte (nu neaparat intregi) pe care sa le bage in rucsac, astfel incat suma profiturilor sa fie maxima.
Daca Gigel baga in rucsac obiectul $i$, caracterizat de ($w_i, p_i$), atunci profitul adus de obiect este $p_i$ (presupunem ca il vinde cu cat valoareaza).
In aceasta varianta a problemei, Gigel poate taia oricare dintre obiecte, obtinand o proportie din acesta. Daca Gigel alege alege doar $x$ din greutatea $w_i$ a obiectului $i$, atunci el castiga doar $\frac{x}{w_i} * p_i$.
Task-uri:
Consideram 2 localitati $A$ si $B$ aflate la distanta $D$. Intre cele 2 localitati avem un numar de $n$ benzinarii, date prin distanta fata de localitatea $A$. Masina cu care se efectueaza deplasarea intre cele 2 localitati poate parcurge maxim $m$ kilometri avand rezervorul plin la inceput. Se doreste parcurgerea drumului cu un numar minim de opriri la benzinarii pentru realimentare (dupa fiecare oprire la o benzinarie, masina pleaca cu rezervorul plin).
Distantele catre benzinarii se reprezinta printr-o lista de forma $0 < d1 < d2 < ... < dn$, unde $di$ ($1 <= i <= n$) reprezinta distanta de la $A$ la benzinaria $i$. Pentru simplitate, se considera ca localitatea $A$ se afla la $0$, iar $dn = D$ (localitatea $B$ se afla in acelasi loc cu ultima benzinarie).
Se garanteaza ca exista o planificare valida a opririlor astfel incat sa se poata ajunge la localitatea $B$.
Pe parcursul unui semestru, un student are de rezolvat $n$ teme (nimic nou pana aici…). Se cunosc enunțurile tuturor celor $n$ teme de la începutul semestrului.
Timpul de rezolvare pentru oricare dintre teme este de o săptămână și nu se poate lucra la mai multe teme în același timp. Pentru fiecare tema se cunoaște un termen limita $d[i]$ (exprimat în săptămâni - deadline pentru tema $i$) și un punctaj $p[i]$.
Nicio fracțiune din punctaj nu se mai poate obține după expirarea termenului limită.
Task-uri:
Nu avem bonus la acest laborator.
[0] Capitolul Greedy Algorithms din Introductions to Algorithms de către T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein