Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pa:laboratoare:laborator-02 [2026/03/09 23:50]
radu.nichita [Extra (studiu de caz pentru acasă)]
pa:laboratoare:laborator-02 [2026/03/15 19:10] (current)
aureliu.antonie [Gardurile lui Gigel]
Line 7: Line 7:
 ===== Precizări inițiale ===== ===== Precizări inițiale =====
 <​note>​ <​note>​
-Toate exemplele de cod se găsesc pe pagina [[https://​github.com/​acs-pa/​pa-lab/​tree/​main/​demo/lab04|pa-lab::demo/lab04]].+Toate exemplele de cod se găsesc pe pagina [[https://​github.com/​acs-pa/​pa-lab/​tree/​main/​algorithms/lab02|pa-lab/algorithms/​lab02]].
  
-Exemplele de cod apar încorporate și în textul laboratorului pentru a facilita parcurgerea cursivă a acestuia. ​**ATENȚIE!** Varianta actualizată a acestor exemple se găsește întotdeauna pe GitHub.+Exemplele de cod apar încorporate și în textul laboratorului pentru a facilita parcurgerea cursivă a acestuia. ATENȚIE! Varianta actualizată a acestor exemple se găsește întotdeauna pe GitHub.
 </​note>​ </​note>​
  
-  * Toate bucățile de cod prezentate în partea introductivă a laboratorului (înainte de exerciții) au fost testate. Cu toate acestea, este posibil cadin cauza mai multor factori (formatare, caractere invizibile puse de browseretc.)un simplu copy-paste să nu fie de ajuns pentru a compila codul.+  * Toate bucățile de cod prezentate în partea introductivă a laboratorului (înainte de exerciții) au fost testate. Cu toate acestea, este posibil ca din cauza mai multor factori (formatare, caractere invizibile puse de browser etc) un simplu copy-paste să nu fie de ajuns pentru a compila codul.
   * Vă rugăm să compilați **DOAR** codul de pe GitHub. Pentru raportarea problemelor,​ contactați unul dintre maintaineri. ​   * Vă rugăm să compilați **DOAR** codul de pe GitHub. Pentru raportarea problemelor,​ contactați unul dintre maintaineri. ​
   * Pentru orice problemă legată de conținutul acestei pagini, vă rugam să dați e-mail unuia dintre responsabili.   * Pentru orice problemă legată de conținutul acestei pagini, vă rugam să dați e-mail unuia dintre responsabili.
Line 23: Line 23:
 De asemenea, DP se poate folosi și pentru probleme în care nu căutam un optim, cum ar fi **problemele de numărare**. De asemenea, DP se poate folosi și pentru probleme în care nu căutam un optim, cum ar fi **problemele de numărare**.
  
-Pentru noțiunile prezentate până acum despre DP, vă rugăm să consultați pagina laboratorului ​3.+Pentru noțiunile prezentate până acum despre DP, vă rugăm să consultați pagina ​[[pa:​laboratoare:​laborator-01|laboratorului ​01]].
 ===== Exemple clasice ===== ===== Exemple clasice =====
  
Line 61: Line 61:
  
 == Enunț == == Enunț ==
-Fie un produs matriceal $M = M_1 M_2 ... M_n$. Putem pune paranteze în mai multe moduri și vom obține același rezultat (înmulțire asociativă),​ dar este posibil să obținem un număr diferit de **înmulțiri scalare**.+Fie un produs matriceal $M = M_1 M_2 ... M_n$. Putem pune paranteze în mai multe moduri și vom obține același rezultat (înmulțirea este asociativă),​ dar este posibil să obținem un număr diferit de **înmulțiri scalare**.
  
 Matricea $M_i$ are (prin convenție),​ dimensiunile $d_{i-1} d_{i}$. Matricea $M_i$ are (prin convenție),​ dimensiunile $d_{i-1} d_{i}$.
Line 359: Line 359:
     * $dp[i] = (dp[i-1] + dp[i-4]) \ \% \  MOD$      * $dp[i] = (dp[i-1] + dp[i-4]) \ \% \  MOD$ 
     *      * 
-<​note>​ Așa cum am zis în secțiunea de [[http://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​laborator-04?&#​sfaturireguli|sfaturi și reguli]] vrem să facem o **parționare** după un anumit **criteriu**:​ în cazul problemei de față, criteriul de parționare este dacă gardul se termină cu o scândură verticală sau orizontală.+<​note>​ Așa cum am zis în secțiunea de [[http://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​laborator-02?&#​sfaturireguli|sfaturi și reguli]] vrem să facem o **parționare** după un anumit **criteriu**:​ în cazul problemei de față, criteriul de parționare este dacă gardul se termină cu o scândură verticală sau orizontală.
  
  
-De asemenea, tot în secțiunea [[http://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​laborator-04?&#​sfaturireguli|sfaturi și reguli]] am precizat că nu vrem **să număram un obiect** (un mod de a construi gardul) **de două ori**. Recurența noastră (dp[i] = dp[i-1] + dp[i-4]) nu ia un obiect de două ori pentru că orice soluție care vine din dp[i-4] e diferită de alta care vine din dp[i-1] pentru că diferă în cel puțin ultima scândură așezată) </​note> ​+De asemenea, tot în secțiunea [[http://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​laborator-02?&#​sfaturireguli|sfaturi și reguli]] am precizat că nu vrem **să număram un obiect** (un mod de a construi gardul) **de două ori**. Recurența noastră (dp[i] = dp[i-1] + dp[i-4]) nu ia un obiect de două ori pentru că orice soluție care vine din dp[i-4] e diferită de alta care vine din dp[i-1] pentru că diferă în cel puțin ultima scândură așezată) </​note> ​
  
 == Implementare recurență == == Implementare recurență ==
Line 409: Line 409:
 De multe ori, este nevoie să folosim câteva tehnici pentru a obține performanța maximă cu recurența găsită. De multe ori, este nevoie să folosim câteva tehnici pentru a obține performanța maximă cu recurența găsită.
  
-În prima parte a laboratorului ​se menționa tehnica de memoizare. În acesta, ne vom rezuma la cum putem folosi cunoștințele de lucru matriceal pentru a favoriza implementarea unor anumite tipuri de recurențe.+În prima parte a [[pa:​laboratoare:​laborator-01|laboratorului ​01]] se menționa tehnica de **memoizare**. În acesta, ne vom rezuma la cum putem folosi cunoștințele de lucru matriceal pentru a favoriza implementarea unor anumite tipuri de recurențe.
  
 ==== Exponențiere pe matrice pentru recurențe liniare ==== ==== Exponențiere pe matrice pentru recurențe liniare ====
Line 498: Line 498:
 $$S_i = S_{k}C^{i -k}$$ $$S_i = S_{k}C^{i -k}$$
  
 +Pentru a aduce un plus de viteză, vom folosi un truc numit [[https://​en.wikipedia.org/​wiki/​Exponentiation_by_squaring|exponențiere rapidă]]. Pe scurt, vom ridica o valoare(notată $a$) la puterea n, împărțind ​ n folosind reprezentarea sa binară.
  
-În laboratorul ​2 (Divide et Imperaam învățat că putem calcula $^ n$ în timp logaritmic. Deoarece ​și înmulțirea matricilor ​este asociativă, putem calcula $n$ in timp logaritmic.+De exemplu, dacă am vrea să calculăm:​ 
 +$$ 5^{13} = 5^{1101_2}= 5^8 * 5^4 * 5^1 $$ 
 + 
 +Exponentul are exact $\lfloor log_2(n) \rfloor + 1$ cifre în baza 2, deci vom avea nevoie de $O(log(n))$ înmulțiri, fiind condiționați de faptul ​că trebuie să cunoaștem $a^1, a^2, a^4, etc.$ Din fericire, ​putem calcula ​rapid acești factori prin ridicarea la pătrat a elementului precedent. 
 + 
 +În final, putem implementa un algoritm iterativ pentru calcularea rezultatului ​$a^n$ iterând prin cifrele din baza 2 ale lui n și înmulțind cu ${a^2}^{k}$ atunci când cifra curentă ​este 1(pentru viteză, vom folosi operații pe biți în loc de o iterare propriu zisă prin cifre). 
 + 
 +Mai jos putem vedea o implementare in C++: 
 +<code cpp> 
 +long long pow(long long a, long long n) { 
 +    long long res = 1; 
 +    while (n > 0) { 
 +        // daca cel mai nesemnificativ bit(LSB) din n este 1 
 +        if (n & 1) { 
 +            res = res * a; 
 +        } 
 +         
 +        // calculam urmatorul factor 
 +        a = a * a; 
 +         
 +        // shiftam la dreapta n cu o pozitie(urmatorul bit va deveni LSB) 
 +        n >>= 1; 
 +    } 
 +    return res; 
 +
 +</​code>​ 
 + 
 +Acest truc poate fi folosit pentru orice tip de date pentru care înmulțirea este asociativă(inclusiv matrice).
  
 Obținem astfel o soluție cu următoarele complexități:​ Obținem astfel o soluție cu următoarele complexități:​
Line 641: Line 669:
  
  
-===== Exerciții ​=====+===== Pool probleme (pentru prezentări) ======
  
 +======= 1) Rectangle Cutting =======
  
-<​hidden>​ +**Enunt:​**  ​ 
-<spoiler Soluție>​ +Se dă un dreptunghi ​de dimensiuni ''​a × b''​Se pot face tăieturi doar pe linii paralele cu laturile dreptunghiului,​ împărțind dreptunghiul în două dreptunghiuri mai mici 
-Problema este preluată de [[https://​infoarena.ro/​problema/​azerah|aici]]. Soluția se găsește [[https://​www.infoarena.ro/​onis-2015/​solutii-runda-1#​azerah|aici]]. +
-</​spoiler>​ +
-</​hidden>​+
  
-Expresie booleană +Determinati numărul minim de tăieturi necesare pentru a împărți dreptunghiul în pătrate.
-Se dă o expresie booleană corectă cu n termeni. Fiecare din termeni poate fi unul din stringurile **true**, **false**, **and**, **or**, **xor**.+
  
-Numărați modurile în care se pot așeza paranteze astfel încât rezultatul să fie **true**. Se respectă regulile de la logică (tabelele de adevăr pentru operațiile **and**, **or**, **xor**).+**Date de intrare:**   
 +Două numere întregi ''​a''​ și ''​b''​ — dimensiunile dreptunghiului.
  
-Deoarece rezultatul poate fi prea mare, se cere **restul împărțirii** lui la $1000000007$ ($10^9 + 7$).+**Date de ieșire:**   
 +Se afișează un singur număr întreg — numărul minim de tăieturi necesare.
  
-<​note>​ +Problema se poate testa la:   
-În schelet vom codifica cu valori de tip char cele 5 stringuri: +https://​cses.fi/​problemset/​task/​1744
-  * **false**: '​F'​ +
-  * **true**: '​T'​ +
-  * **and**: '&'​ +
-  * **or**: '​|'​ +
-  * **xor**'​^'​+
  
-Funcția pe care va trebui să o implementați voi va folosi variabilele **n** (numărul de termeniși **expr** (vectorul cu termenii expresiei). +======= 2Removal Game =======
-</​note>​+
  
 +**Enunt:​**  ​
 +Se dă un șir de ''​n''​ numere întregi. Doi jucători joacă alternativ. La fiecare mutare, un jucător poate elimina primul sau ultimul element din șir și adaugă valoarea acelui element la scorul său.  ​
 +Ambii jucători joacă optim.  ​
  
-<spoiler Exemplu 1> +Determinati scorul maxim pe care îl poate obține primul jucător.
-$n = 5$ și $expr = ['​T',​ '&',​ '​F',​ '​^',​ '​T'​]$ (expr = [** true and false xor true**])+
  
-Răspuns$2$+**Date de intrare:**   
 +Pe prima linie se află un număr întreg ''​n''​. ​  
 +Pe a doua linie se află ''​n''​ numere întregi reprezentând valorile din șir.
  
-Explicație: Există 2 moduri corecte de a paranteza expresia astfel încât să obținem rezultatul ​**true** (1). +**Date de ieșire:**   
-  * $ T&(F^T) $ +Se afișează un singur număr întreg — scorul maxim al primului jucător.
-  * $ (T&F)^T $ +
-</​spoiler>​+
  
-<spoiler Hint> +Problema ​se poate testa la:  ​ 
-    Complexitate temporală dorită este $O(n ^ 3)$. +https://​cses.fi/​problemset/​task/​1097/
-     +
-    Opțional, ​se pot defini funcții ajutătoare precum **is_operand**,​ **is_operator**,​ **evaluate**. +
-</spoiler>+
  
-<note tip> +======= 3) Array Description =======
-Pentru rezolvarea celor două probleme gândiți-vă la ce scrise în secțiunea [[http://​ocw.cs.pub.ro/​courses/​pa/​laboratoare/​laborator-04?&#​sfaturireguli| Sfaturi / Reguli]]. Pentru fiecare dintre cele două probleme facem o **partiționare după un anumit criteriu**.+
  
 +**Enunt:​**  ​
 +Se dă un vector de lungime ''​n''​. Fiecare element este un număr între 1 și ''​m''​. Unele poziții sunt deja fixate, iar altele au valoarea 0, ceea ce înseamnă că pot fi alese liber.  ​
 +Un vector este valid dacă diferența absolută dintre două elemente consecutive este cel mult 1.  ​
  
-Pentru problema ​**DP or math?** partiționăm toate subșirurile după critieriul **parității ​sumei subșirului** (câte sunt pare/impare).\\  +Determinati câte vectori valizi pot fi formați respectând valorile deja fixate. 
-Pentru ​problema ​**expresie booleană** partiționă**toate parantezările posibile după rezultatul lor** (câte dau true/false).+ 
 +**Date de intrare:**   
 +Pe prima linie se află două numere întregi ''​n'' ​și ''​m''​. ​  
 +Pe a doua linie se află ''​n''​ numere întregi reprezentând vectorul inițial (valorile 0 indică poziții nefixate). 
 + 
 +**Date de ieșire:**   
 +Se afișează un singur număr întreg — numărul de vectori valizi modulo 10⁹+7. 
 + 
 +Problema se poate testa la:   
 +https://cses.fi/​problemset/​task/​1746/​ 
 + 
 +======= 4) Student Attendance Record II ======= 
 + 
 +**Enunt:​** ​  
 +Un elev are un istoric al prezentețor la școală pe parcursul a ''​n''​ zile. Pentru ​fiecare zi, status-ul său  poate fi:   
 +    ​ P (present) — prezent ​  
 +    ​L (late) — întârziat ​  
 +    * A (absent) — absent ​  
 + 
 +Un istoric este considerat valid dacă:   
 +    ​conține cel mult o absență (A)   
 +    ​nu conține mai mult de două întârzieri consecutive (L)   
 + 
 +Determinati câte istorice de prezență valide de lungime ''​n''​ există. 
 + 
 +**Date de intrare:​** ​  
 +Un număr întreg ''​n''​ — numărul de zile. 
 + 
 +**Date de ieșire:​** ​  
 +Se afișează un singur număr întreg — numărul de istorice valide modulo 10⁹+7. 
 + 
 +Problema se poate testa la:   
 +https://​leetcode.com/​problems/​student-attendance-record-ii/​description/​ 
 + 
 +======= 5Burst Balloons ======= 
 + 
 +**Enunt:​** ​  
 +Se dau ''​n''​ baloane, fiecare având un număr asociatCând se sparge balonul ''​i'',​ se câștigă un număr de monede egale cu produsul numerelor de pe balonul ''​i''​ și baloanele vecine lui în acel moment. ​  
 +După spargere, balonul dispare, iar vecinii lui devin adiacenți. La extremități se consideră două baloane imaginare cu valoarea 1.   
 + 
 +Determinati numărul maxim de monede pe care îl puteți obține spargând toate baloanele într-o anumită ordine. 
 + 
 +**Date de intrare:​** ​  
 +Un vector de ''​n''​ numere întregi care reprezintă valorile baloanelor. 
 + 
 +**Date de ieșire:​** ​  
 +Se afișează un singur număr întreg — numărul maxim de monede ce poate fi obținut. 
 + 
 +Problema se poate testa la:   
 +https://​leetcode.com/​problems/​burst-balloons/​description/​
  
-</​note>​ 
 ===== Extra (studiu de caz pentru acasă) ===== ===== Extra (studiu de caz pentru acasă) =====
 <spoiler Por Costel si Azerath> <spoiler Por Costel si Azerath>
Line 701: Line 771:
  
 <spoiler Parantezare booleană>​ <spoiler Parantezare booleană>​
-Rezolvati pe geeksforgeeks problema [[https://​www.geeksforgeeks.org/​problems/​boolean-parenthesization5610|Parantezare booleană]].+Rezolvati pe geeksforgeeks problema [[https://​www.geeksforgeeks.org/​problems/​boolean-parenthesization5610/1|Parantezare booleană]].
  
 Hint: Complexitate temporală dorită este $O(n ^ 3)$. Hint: Complexitate temporală dorită este $O(n ^ 3)$.
pa/laboratoare/laborator-02.1773093009.txt.gz · Last modified: 2026/03/09 23:50 by radu.nichita
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