Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
aa:lab:10 [2023/12/17 13:13] mihai.udubasa hide solutions |
aa:lab:10 [2025/12/15 14:30] (current) dmihai |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Recurențe ====== | + | ====== Probleme "dificile" ====== |
| - | /* | + | |
| - | <note important> | + | |
| - | Solutii: | + | |
| - | https://drive.google.com/file/d/11tR3YphFS73OF8QGvtorjf_dkRHPmo1y/view?usp=drivesdk | + | În acest laborator veți explora un graf realist cu date despre toate aeroporturile din lume și rutele dintre ele și veți aplica diverși algoritmi *eficienți* pe acesta. |
| + | Momentan, puteți considera termenul "eficient" să însemne "fără backtracking" (mai precis, ne referim la conceptul de polinomial, i.e. cu o complexitate descrisă de $ O(n^k)$, pentru un $ k$ natural; vom relua conceptul la curs). | ||
| + | |||
| + | Descărcați de aici arhiva cu datele de intrare: {{:aa:lab:lab.zip|}} | ||
| + | |||
| + | Aceasta conține în directorul ''res/'' trei fișiere cu date despre aeroporturi și rute: | ||
| + | |||
| + | - ''airroutes.in'' - din lume \\ | ||
| + | - ''eu-airroutes.in'' - din Europa \\ | ||
| + | - ''ro-airroutes.in'' - din România | ||
| + | |||
| + | Fișierele descriu grafuri orientate, ale căror noduri au ID-uri întregi începând de la 0; respectă următorul format: | ||
| + | |||
| + | - pe prima linia, numărul de noduri ''N'' și numărul de muchii din graf, separate de un spațiu. \\ | ||
| + | - pe următoarele ''N'' linii, informații despre un nod \\ | ||
| + | - pe linia ''i'' (probabil indexată de la 1 în editorul de text), găsiți informații despre nodul cu ID ''i - 2'': \\ | ||
| + | - [[https://www.iata.org/en/publications/directories/code-search/|codul IATA]] al aeroporturlui \\ | ||
| + | - toate rutele de la acel aeroport exprimate folosind trei numere: ID-ul aeroportului destinație, distanța zborului în kilometri, durata zborului în minute. | ||
| + | |||
| + | <note> | ||
| + | Fișierele sunt doar o versiune parser-friendly a datelor din acest JSON: https://github.com/Jonty/airline-route-data/blob/main/airline_routes.json | ||
| + | |||
| + | În ''tools/extract_c_friendly.py'' găsiți scriptul care a realizat extragerea. | ||
| </note> | </note> | ||
| - | */ | ||
| - | 1. Folosiți Teorema Master pentru a rezolva următoarele recurențe: | ||
| - | * $ T_1(n) = 4T_1(n/4) + 1$ | + | ==== Exerciții ==== |
| - | <hidden Exemplu de cod cu aceasta recurenta> | + | |
| - | <code c> | + | 1. Scrieți un program care parsează un fișier de intrare cu formatul descris și reține graful în memorie. Programul apoi primește un singur cod IATA al unui aeroport(de la ''stdin'' sau ca argument în linia de comandă), determină toți vecinii și printează codurile lor IATA pe o singură linie separate de câte un spațiu. |
| - | // O metoda destul de ineficienta de calcul al sumei elementelor unui vector | + | |
| - | int sum(int arr[], int lo, int hi) { | + | 2. Scrieți un program cu același input ca mai sus dar care scrie ''N'' linii într-un fișier: pentru fiecare aeroport, linia corespunzătoare ID-ului trebuie să conțină codul IATA urmat de numărul minim de noduri prin care se poate ajunge acolo (pentru aeroportul de referință primit ca input, printați "-" în loc de număr, iar pentru aeroporturile la care nu se poate ajunge printați "unreachable"). |
| - | if(lo == hi) | + | |
| - | return arr[lo]; | + | BONUS: folosiți [[https://web.stanford.edu/class/archive/cs/cs161/cs161.1182/Lectures/Lecture11/CS161Lecture11.pdf|algoritmul lui Djikstra]] pentru a calcula cea mai scurtă rută din punct de vedere al distanței și al timpului (scrieți rezultatele în fișiere diferite). |
| - | int x = (hi - lo) / 4; | + | |
| - | return sum(arr, lo, lo + x) + | + | 3. Care sunt cele mai îndepărtate aerporturi de OTP pentru fiecare metrică? Dar de LHR (London Heathrow)? |
| - | sum(arr, lo + x + 1, lo + 2 * x) + | + | Care e cea mai mare distanță posibilă între oricare două aeroporturi, pentru fiecare metrică? |
| - | sum(arr, lo + 2 * x + 1, lo + 3 * x) + | + | Care este cel mai izolat aeroport, pentru fiecare metrică? (aeroportul cu cea mai mare distanță medie către toate celelalte aeroporturi) |
| - | sum(arr, lo + 3 * x + 1, hi); | + | |
| - | } | + | |
| - | </code> | + | |
| - | </hidden> | + | |
| - | * $ T_3(n) = 4T_3(n/2) + n^2$ | + | |
| - | * $ T_2(n) = 8T_2(n/2) + 2n^2$ | + | |
| - | 2. Fie următorul algoritm de căutare a unei valori ''v'' într-un array sortat ''arr'': | + | 4. Determinați toate componentele conexe ale grafului folosind BFS sau DFS la alegere. |
| + | Scrieți componentele într-un alt fișier de output, câte una pe linie; fiecare componentă conexă e descrisă de codurile IATA a tuturor aeroporturilor din care e formată, separate de un spațiu. | ||
| - | <code c> | + | 5. Creați un graf neorientat pe baza grafului inițial. Vom crea muchii neorientate doar între acele aeroporturi între care există muchii în ambele sensuri (pentru weight, folosiți media celor două muchii orientate). |
| - | int search(int arr[], int lo, int hi, int v) | + | Determinați dacă există o clică de dimensiune 20 în graful rezultat. Dar de 30? |
| - | { | + | Folosiți o căutare exhaustivă de forma: |
| - | int mid = (lo + hi) / 2; | + | |
| - | if (arr[mid] == v) | + | |
| - | return mid; | + | |
| - | if (lo == hi) | + | |
| - | return -1; | + | |
| - | if (arr[mid] > v) | + | |
| - | return search(arr, lo, mid, v); | + | |
| - | else | + | |
| - | return search(arr, mid, hi, v); | + | |
| - | } | + | |
| - | </code> | + | - inițializați o mulțime goală \\ |
| + | - la fiecare pas: \\ | ||
| + | - adăugați un nod (e.g. următorul în ordinea ID) în mulțime; dacă nu mai sunt noduri, reveniți la pasul anterior \\ | ||
| + | - verificați dacă mulțimea e clică; dacă nu, înapoi la pasul anterior \\ | ||
| + | - verificați dacă sunt $ k$ elemente în mulțime; dacă nu, treceți la pasul următor; altfel printați clica | ||
| - | * Determinați relația de recurență a algoritmului de căutare prezentat. | + | Scrieți clica într-un fișier separat într-un format similar cu al fișierelor ''*.in''. |
| - | * Demonstrați recurența utilizând Teorema Master. | + | |
| - | * Demonstrați recurența utilizând Metoda Arborilor. | + | |
| - | * Demonstrați recurența utilizând Metoda Substituției. | + | |
| - | 3. Folosiți cele 3 metode (metoda arborilor, metoda substituției, teorema master) pentru a rezolva recurențele: | + | BONUS: încercați să implementați orice fel de euristică ce ar grăbi procesarea (în general, sau pe anumite tipuri de grafuri), **păstrând însă garanția că răspunsul întors este cel corect**. |
| - | * $ T_a(n) = 2T_a(n-1) + 1$ | + | 6. Scrieți un alt program care citește un graf neorientat complet dintr-un fișier (clica anterioară) și rezolvă problema comisului voiajor (Traveling Salesman Problem), prin căutare exhaustivă. |
| - | * $ T_b(n) = T_b(n-1) + 1$ | + | Încercați grafuri mici întâi și încercați să determinați cât timp durează rularea în funcție de numărul de noduri. |
| - | * $ T_c(n) = 2T_c(n/2) + \log(n)$ | + | |
| - | * $ T_d(n) = T_d(n/9) + T_d(8n/9) + n$ | + | |
| - | * $ T_e(n) = T_e(2n/3) + 1$ | + | |
| - | * $ T_f(n) = T_f(\sqrt{n}) + 1$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
| - | * $ T_g(n) = 2T_g(\sqrt{n}) + n$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
| - | * $ T_h(n) = \sqrt{n}T_h(\sqrt{n}) + n$ (hint: substituiți $ n$ cu $ 2^k$) | + | |
| - | 4. Rezolvați următoarea recurență folosind metoda substituției: $math[T(n) = 2 T(\frac{n}{2}) + 1]. | ||
| - | 5. Rezolvați următoarea recurență folosind metoda arborilor: $math[T(n) = T(] $math[n \over 4] $math[) + T(] $math[3n \over 4] $math[) + n]. | ||