This shows you the differences between two versions of the page.
sda-aa:laboratoare:12 [2021/02/28 23:31] 127.0.0.1 external edit |
sda-aa:laboratoare:12 [2021/05/26 11:58] (current) cristian.rusu [4. Exerciții laborator] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 11: Backtracking ===== | + | ===== Laboratorul 11: Divide et Impera și programare dinamică ===== |
+ | ==== 1. Obiectivele laboratorului ==== | ||
+ | * Înțelegerea noțiunilor de bază legate metoda de programare divide et impera | ||
+ | * Înțelegerea noțiunii de programare dinamică | ||
+ | |||
+ | |||
+ | ==== 2. Metoda Divide et Impera ==== | ||
+ | |||
+ | === 2.1 Prezentare generală === | ||
+ | |||
+ | Această metodă se poate aplica problemelor care permit descompunerea lor în subprograme independente (numele procedurii traducându-se prin împarte și stăpânește.) Așadar obținem 3 faze principale: | ||
+ | |||
+ | * Divide - împarte problema în una/mai multe probleme similare de dimensiuni mai mici. | ||
+ | * Stăpânește - rezolvă subproblemele recursiv (dacă dimensiunea subproblemelor este mică, se rezolvă iterativ). | ||
+ | * Combină - combină soluțiile sub-problemelor pentru a obține soluția problemei inițiale. | ||
+ | |||
+ | === 2.2 Implementare === | ||
+ | |||
+ | <code> | ||
+ | void divide_et_impera(int P[],int n,int S[]{ | ||
+ | if(n <= n0 ) | ||
+ | Determină S prin metode elementare; | ||
+ | else { | ||
+ | Împarte P in:P1,P2,...,Pa | ||
+ | divide_et_impera(P1,S1); | ||
+ | ................................................ | ||
+ | divide_et_impera(Pa,Sa); | ||
+ | Asamblează (S1,...,Sa,S);\ | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === 2.3 Probleme tip rezolvate cu acest algoritm === | ||
+ | |||
+ | == 2.3.1 Determinarea rădăcinilor unei ecuații == | ||
+ | |||
+ | Se dă o funcție care are semne contrare în cele doua capete ale intervalului [a,b],f(α) * f(β) < 0. | ||
+ | Determinați o rădăcină a lui f din intervalul [a,b] cu o eroare ε. | ||
+ | Pentru rezolvarea problemei folosim următoarea strategie: împărțirea repetată a intervalului inițial [α,β] în jumătăți ale acestuia și selectarea intervalului jumătății în care se află soluția (Metoda bisecției) | ||
+ | |||
+ | * Fie funcția f:[α,β] → R, continuă. Determinarea aproximației Δ', a rădăcinii exacte Δ, cu eroarea ε. | ||
+ | * Notăm cu m mijlocul intervalului ( m=(α+β)/2 ) | ||
+ | * Verificăm dacă f(m) * f(b) < 0, ceea ce înseamnă că soluția se află în a doua jumătate a intervalului și îi atribuim lui α valoarea lui m. | ||
+ | * Altfel daca f(m) * f(b) > 0, soluția se află în prima jumătate a intervalului și ii atribuim lui β valoarea lui m. | ||
+ | * Acest procedeu se aplică în mod repetat până când lungimea intervalului scade cu 2*ε(β - α < 2*ε) | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== 3. Programare dinamică ==== | ||
+ | |||
+ | === 3.1 Definiție === | ||
+ | |||
+ | Programarea dinamică presupune rezolvarea unei probleme prin descompunea ei în subprobleme și rezolvarea acestora. Spre deosebire de divide et impera, subprogramele nu sunt disjuncte, ci se suprapun. | ||
+ | |||
+ | Pentru a evita recalcularea porțiunilor care se suprapun, rezolvarea se face pornind de la cele mai mici subprograme și folosindu-ne de rezultatul acestora calculăm subproblema imediat mai mare. Cele mai mici subprobleme sunt numite subprobleme unitare, acestea putând fi rezolvate într-o complexitate constantă, ex:cea mai mare secvență dintr-o mulțime de un singur element. | ||
+ | |||
+ | === 3.2 Algoritm === | ||
+ | |||
+ | <note important>Pași ce trebuie urmați: | ||
+ | * Identificarea structurii și a matricilor utilizate în caracterizarea soluției optime | ||
+ | * Determinarea unei metode de calcul recursiv pentru a afla valoarea fiecărei subprobleme | ||
+ | * Calcularea „bottom-up“ a acestei valori (de la subprogramele cele mai mici la cele mai mari) | ||
+ | * Reconstrucția soluției optime pornind de la rezultatele obținute anterior | ||
+ | </note> | ||
+ | |||
+ | ==== 4. Exerciții laborator ==== | ||
+ | |||
+ | - Aproximaţi, printr-o abordare de tip Divide et Impera, cu o eroare (relativă) de maxim 1e-6, funcţia sqrt(n) (extragerea rădăcinii pătrate a unui număr). Nu aveţi voie să folosiţi nicio funcţie din „math.h“. Încercaţi să extindeţi exerciţiul pentru extragerea radicalului de ordin 3. | ||
+ | - Aproximaţi, printr-o abordare de tip Divide et Impera, cu o eroare (relativă) de maxim 1e-3, funcţia lg(n) (extragerea logaritmului în baza 10). Aveţi voie să vă folosiţi de funcţia pow(bază, exp) din „math.h“. | ||
+ | - Construiți o funcție care calculează f(n), unde f = șirul lui Fibonacci (cu și fără memoizare). Comparați timpii de rulare. n este numar intreg (pozitiv si negativ). | ||
+ | - Aveți la dispoziție monedele 25, 10, 5 și 1 RON. Calculați cu PD toate posibilitățile de rest (cu și fără memoizare). |