Laboratorul 10: Greedy și backtracking

1. Obiectivele laboratorului

  • Înțelegerea noțiunilor de bază legate de tehnica greedy
  • Însușirea abilităților de implementare a algoritmilor bazați pe greedy
  • Înțelegerea implementării algoritmilor greedy privind probleme de optimizare
  • Înțelegerea noțiunii de backtracking
  • Implementarea metodei backtracking în rezolvarea problemelor

2. Algoritmul Greedy

2.1 Prezentare generală

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.

Este in înțeles de ce un astfel de algoritm se numeste „lacom“ (greedy), deoarece la fiecare pas, funcția alege cel mai bun candidat la momentul respectiv, fără să-i pese de viitor și fără să revină asupra alegerii. Daca un candidat este inclus în soluție, el rămâne în soluție, iar dacă un candidat este exclus din soluție, el nu va mai fi niciodată reconsiderat.

2.2 Implementare

Descrierea formală a algoritmului este următoarea:

function Greedy (C)
     //C = mulțimea candidaților
     //în S construim soluția
     S = ∅;
     while( !solutie(C) && C != ∅)
          x = un element din C care miniminează/maximizează select(x);
          C = C\(x);
     if( fezabil(S∪(x))
          S = S∪(x);
     return S;

2.3 Probleme tip rezolvate cu acest algoritm

2.3.1 Problema spectacolelor

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 infinit (Spectacolul care se termină cel mai devreme va fi mereu selectat, având timp de start mai mare decât timpul inițial)

2.3.2 Problema cuielor

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].

Exemplu:

  • Intrare: N=5, intervalele:[0,2],[1,7],[2,6],[5,14],[8,16];
  • Ieșire M={2,14}
  • Explicație: punctul 2 se afla în primele 3 intervale, iar punctul 14 în ultimele 2
  • Soluție: Se observă 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, există o mulțime (M) de cardinal minim pentru care toate punctele x sunt capete dreapta.
2.3.3 Problema rucsacului

Un rucsac ca poate transporta o greutate G, trebuie încărcat cu obiecte alese dintre 'n' obiecte, fiecare având o anumită greutate (g) și un anumit profit (importanță)(p) sau câștig. Se cere să se determine obiectele ce trebuie încărcate în rucsac astfel încât profitul (caștigul) să fie maxim. Există posibilitatea ca obiectele să fie tăiate. În acest fel se poate obține o încărcare mai eficientă a rucsacului:

  • Se determină pentru fiecare obiect eficiența de transport rezultată prin împărțirea profitului la greutatea obiectului;
  • Se sortează obiectele în ordinea descrescătoare a eficienței de transport și se iau în calcul în această ordine;
  • Inițial profitul este 0, iar greutatea rămasă de încărcat este egală cu G;
  • Cât timp nu s-a ajuns la greutatea maximă (G) și nu au fost luate în considerare toate obiectele se va selecta obiectul cel mai eficient pentru care avem două variante:
    • Intră în întregime în rucsac și atunci se va scădea greutatea lui din cea rămasă de încărcat;
    • Nu intră în totalitate în rucsac și atunci se determină ce procent din obiectul respectiv va intra în rucsac; în acest caz se va cumula la câștigul total procentul de profit asociat părții din obiectul încărcat în rucsac, iar greutatea rămasă va fi zero.
2.3.4 Problema comisului voiajor (TSP)

Un comis-voiajor stă într-un oraş (X1) şi vrea să viziteze toate cele N oraşe dintr-o regiune (X1, X2, …, XN), plecând dimineaţa de acasă (X1) şi întorcandu-se (tot în X1) la finalul zilei.

În mod ideal, el îşi doreşte să viziteze fiecare oraş exact o singură dată (excepţie făcând numai oraşul X1 unde se întoarce seara), iar drumul găsit să fie cât mai scurt.

Problema poate fi modelată cu grafuri (oraş = nod, drum între 2 oraşe = muchie) şi cerinţa devine găsirea unui Ciclu/Circuit Hamiltonian minim (un ciclu care conţine o singură dată fiecare nod, cu excepţia nodului de plecare care coincide doar cu nodul final, şi care este de cost minim).

Soluţia de cost minim pentru TSP nu poate fi garantată cu un algoritm de tip Greedy, dar un astfel de algoritm poate fi folosit pentru a găsi în timp util un drum.

Varianta Greedy (pură): parcurgem în adâncime (DFS) graful din nodul de plecare (X1), continuând mereu pe cea mai ieftină muchie. La prima fundătură (primul nod din care nu mai avem vecini nevizitaţi), algoritmul se opreşte:

  • dacă algoritmul s-a blocat după ce a vizitat N noduri şi ultimul nod găsit (nodul curent) este vecin cu nodul de plecare (X1), atunci: mesaj de reuşită + soluţia găsită.
  • altfel: mesaj de nereuşită (+ eventual soluţia parţială).

Varianta Greedy + revenire: la fel ca varianta Greedy (pură), dar permitem revenirea în cazul unui blocaj, respectând parcurgerea DFS (eliminăm nodul curent din soluţie, ne întoarcem la nodul găsit imediat înainte de nodul curent şi, din acel nod, alegem următoarea variantă).

Această variantă nu mai respectă principiul de bază al tehnicii Greedy, va avea nevoie de mai mult timp, dar va oferi un răspuns mai bun.

3. Backtracking

3.1 Definiție

Noțiunea de backtracking se referă la utilizarea unui algoritm recursiv pentru soluționarea unei probleme ce admite soluții parțiale. Se începe cu una din bucățile de soluție disponibile și se avansează până la construirea soluției complete. Dacă una din rutele de construcție disponibile nu duce nicăieri, se merge înapoi (backtrack) și se încearcă altă cale. Dacă niciuna din rute nu dă o soluție, atunci problema nu este rezolvabilă.

3.2 Algoritm

Algoritmul general este următorul:

  • Se alege un punct de start
  • Cât timp problema nu este rezolvată:
    • Pentru fiecare cale(parte din soluție disponibilă) de la punctul de start:
    • Se verifică dacă ruta aleasă este bună (nu invalidează condiția de rezolvare)
    • Daca da, se adaugă la soluția în construcție și se apelează recursiv algoritmul pentru restul problemei
    • Dacă apelul recursiv reușește să găsească o soluție completă,algoritmul se încheie. Dacă nu, ruta aleasă se elimină din soluție și se alege alta.
  • Daca niciuna din căile disponibile nu este bună, nu există soluție (pentru punctul de start ales).

4. Exerciții laborator

  1. Folosiţi un algoritm de tip Greedy pentru a găsi numărul minim de bancnote necesare pentru a da o anumită sumă de bani ca rest. Presupunem numai valori întregi pentru suma de bani şi următoarele bancnote: {1, 5, 10, 50, 100} (RON).
  2. Găsiţi un exemplu pentru care un algoritm de tip Greedy nu ar funcţiona pentru o problemă similară, dar care foloseşte următoarele bancnote: {1, 3, 5, 15, 30, 50, 150}. Încercaţi să explicaţi de ce, în acest caz, tehnica Greedy nu mai e optimă.
  3. Generarea produsului cartezian AN (interpretare: toate numerele de N cifre, dar cu cifrele alese numai din mulțimea A). Exemplu: A = {1,2,3}, N = 6;
  4. Generarea tuturor permutărilor de N;
  5. Generarea tuturor combinărilor/aranjamentelor de N luate câte k;
  6. Se dă puzzle-ul Sudoku de mai jos, scrieți un program care sa îl rezolve.

sda-aa/laboratoare/11.txt · Last modified: 2021/05/23 21:23 by cristian.rusu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0