InfoBook · Evaluare inițială · materia clasei a X-a
Test inițial — Clasa a XI-a
Verifică bagajul clasei a X-a: căutare binară, interclasare, pointeri, șiruri de caractere, matrice, recursivitate, divide et impera și greedy. Backtracking-ul și grafurile de anul acesta se sprijină direct pe recursivitate și pe matrice.
1 pdin oficiu
5 × 0,2 pgrile = 1 p
4 × 2 pprobleme = 8 p
10 ptotal
timp de lucru: 50 de minute · oficiu + grile complete = nota 2
1.00nota curentăoficiu 1.00 · grilă 0.00 · probleme 0.00
Cum se rezolvă: problemele se scriu în C++. Fiecare subpunct are punctajul lui, iar baremul conține rezolvarea completă, comentată. Recursivitatea (problema 3) e cea mai importantă de recuperat — fără ea, Modulul 01 de anul acesta nu are pe ce să stea.
Recapitulare — bagajul minim
10 noțiuni · fără notă
Înainte de test, treci prin noțiunile pe care se sprijină TOT anul acesta. Cele marcate ★ sunt cele fără de care Modulul 01 nu are pe ce sta. Bifează sincer ce știi — la final vezi unde stai. Nu e notă, e diagnoză.
♾️
Recursivitate
clasa a X-a
★ ESENȚIAL
Cazul de bază — unde se oprește
Pasul recursiv — cum se apropie de caz
Stiva de apeluri: ultimul apel se termină primul
Ce se întoarce și cui
int fact(int n) {
if (n == 0) return 1; // caz de baza
return n * fact(n - 1); // pas recursiv
}
De ce contează acum: Backtracking, DFS, parcurgerile de arbori — toate sunt recursive. Dacă recuperezi un singur lucru, acesta e.
▦
Matrice (tablou 2D)
clasa a X-a
★ ESENȚIAL
Declarare int a[100][100]
Citire cu două bucle imbricate
Acces a[i][j]: i = linia, j = coloana
Diagonala principală i == j
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> a[i][j];
De ce contează acum: Matricea de adiacență a unui graf ESTE o matrice. Roy-Floyd, Dijkstra și Prim lucrează direct pe ea.
🧩
Subprograme
clasa a IX-a
Antet: tip, nume, parametri
return (dă rezultat) vs void (doar face)
Parametri prin valoare vs prin referință (&)
Variabile locale, nu globale
bool estePrim(int n) {
if (n < 2) return false;
for (int d = 2; d * d <= n; d++)
if (n % d == 0) return false;
return true;
}
De ce contează acum: Orice algoritm de anul acesta se scrie ca subprogram cu antet impus — exact ca la bacalaureat.
📊
Vectori și parcurgeri
clasa a IX-a
Citire, afișare, parcurgere cu for
Sumă, minim, maxim, numărare
Căutare secvențială cu break
Vector de frecvență: fr[v[i]]++
int minim = v[0];
for (int i = 1; i < n; i++)
if (v[i] < minim) minim = v[i];
De ce contează acum: Vectorul de tați al unui arbore, vectorul de vizitat la BFS/DFS, vectorul soluție la backtracking.
🥞
Stivă și coadă
clasa a IX-a
Stiva: LIFO — ultimul intrat, primul ieșit
Coada: FIFO — primul intrat, primul ieșit
Operațiile de adăugare și extragere
// stiva
st[vf] = x; vf++; // adaug
vf--; x = st[vf]; // scot
De ce contează acum: DFS merge pe stivă, BFS pe coadă. Sunt chiar motoarele celor două parcurgeri de grafuri.
🎯
Căutare binară
clasa a X-a
Funcționează DOAR pe vector ordonat
Compari cu mijlocul, arunci jumătate
Circa log₂n pași
while (st <= dr) {
int m = (st + dr) / 2;
if (v[m] == x) return m;
if (v[m] < x) st = m + 1;
else dr = m - 1;
}
De ce contează acum: Arborele binar de căutare e aceeași idee, mutată pe o structură arborescentă.
✂️
Divide et impera
clasa a X-a
Descompun → rezolv → combin
Se scrie recursiv
Exemple: maxim, căutare binară, merge sort
int maxim(int st, int dr) {
if (st == dr) return v[st];
int m = (st + dr) / 2;
return max(maxim(st,m), maxim(m+1,dr));
}
De ce contează acum: Aceeași gândire recursivă ca la backtracking — doar că acolo apare și revenirea.
💰
Greedy
clasa a X-a
Alegi ce e mai bun ACUM, local
Nu dă mereu optimul global
Contraexemplul cu monedele
sort(v, v + n);
for (int i = 0; i < n; i++)
if (incape(v[i])) iau(v[i]);
De ce contează acum: Dijkstra și Prim SUNT algoritmi greedy — dar cu garanție că ajung la optim.
📝
Șiruri de caractere
clasa a X-a
Șirul = vector de char + terminator
strlen nu numără terminatorul
Parcurgere cu s[i]
Cuvinte separate prin spațiu
char s[256];
cin.get(s, 256);
for (int i = 0; i < strlen(s); i++)
if (s[i] == ' ') cuvinte++;
De ce contează acum: Apar la orice problemă cu date de tip text și la subiectele de bacalaureat.
📍
Adrese și pointeri
clasa a X-a
& dă adresa unei variabile
* dă valoarea de la adresă
Numele unui tablou e o adresă
int x = 5;
int *p = &x;
cout << *p; // 5
De ce contează acum: Nu-i folosim direct anul acesta, dar explică de ce vectorii se transmit „prin adresă" la subprograme.
Cât de pregătit ești0 / 10
Bifează noțiunile pe care le stăpânești, apoi treci la test.
Subiectul I — grilă
5 × 0,2 p = 1 p
Un singur răspuns corect. Apeși pe variantă și afli imediat dacă ai nimerit, cu explicație.
Subiectul II — probleme
4 × 2 p = 8 p
Fiecare problemă e împărțită pe subpuncte cu punctaj propriu. Rezolvi pe hârtie sau în editor,
apoi deschizi baremul și te autoevaluezi: apasă pe butonul din dreapta fiecărui subpunct pentru
nerezolvat → parțial (jumătate) → corect.
1.
Text: caractere, cuvinte, ștergeri
M05 · <cstring>2 p
Se citește de la tastatură un text de cel mult 255 de caractere, format din cuvinte separate prin câte un spațiu. Se folosesc șiruri în stil C (char s[256]).
Exemplus = "azi avem test la informatica"
a) 11 vocale b) cel mai lung cuvânt: informatica c) după ștergerea literei 'a': "zi vem test l informtic"
a)Afișează numărul de vocale din text (indiferent de literă mare sau mică).0,5 p
b)Afișează cel mai lung cuvânt din text. Dacă sunt mai multe de lungime maximă, afișează-l pe primul.0,75 p
c)Elimină din text toate aparițiile literei 'a' și afișează rezultatul.0,75 p
Barem de corectare & rezolvare
a) 0,5 p
Citirea se face cu cin.getline — cin >> s s-ar opri la primul spațiu. Testul de vocală se scrie elegant cu strchr.
C++
#include <iostream>
#include <cstring>
#include <cctype>
usingnamespace std;
char s[256];
int main() {
cin.getline(s, 256); // ia toata linia, cu spatiiint nv = 0;
for (int i = 0; s[i]; i++) {
char c = tolower(s[i]);
if (strchr("aeiou", c)) nv++;
}
cout << nv << '\n';
return0;
}
b) 0,75 p
strtok este funcția-vedetă de la BAC. Atenție la două capcane de barem: primul apel primește șirul, iar următoarele primesc NULL; și strtok modifică șirul, punând \0 în locul separatorilor — de aceea se lucrează pe o copie.
Trucul suprem al șirurilor: strcpy(s + i, s + i + 1) mută toată coada cu o poziție la stânga, peste caracterul de șters. Capcana de barem: după o ștergere indicele i NU trebuie mărit — pe poziția i a venit un caracter nou, care poate fi tot 'a' (ex.: "baaba").
C++
int i = 0;
while (s[i]) {
if (s[i] == 'a')
strcpy(s + i, s + i + 1); // suprascriu cu ce urmeaza; i RAMANEelse
i++;
}
cout << s << '\n';
2.
Matrice pătratică
M06 · M06a2 p
Se citește un număr natural n (n ≤ 20) și apoi elementele unei matrice pătratice a cu n linii și n coloane, numere întregi. Se folosește indexarea de la 1.
Exemplun = 3 1 2 3 4 5 6 7 8 9
a) diagonala secundară: 3 + 5 + 7 = 15 b) linia cu suma maximă: linia 3, suma 24 c) matricea NU este simetrică (a[1][2] = 2 ≠ 4 = a[2][1])
a)Calculează și afișează suma elementelor de pe diagonala secundară.0,5 p
b)Determină și afișează indicele liniei cu suma elementelor maximă, împreună cu suma respectivă.0,75 p
c)Verifică dacă matricea este simetrică față de diagonala principală și afișează DA sau NU.0,75 p
Barem de corectare & rezolvare
a) 0,5 p
Pe diagonala secundară i + j = n + 1, deci pentru linia i coloana este n + 1 - i. E nevoie de o singură buclă, nu de două.
C++
int n, a[25][25];
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> a[i][j];
int s = 0;
for (int i = 1; i <= n; i++)
s += a[i][n + 1 - i]; // diagonala secundaracout << s << '\n';
b) 0,75 p
Suma pe linie se calculează cu bucla interioară pe coloane. Inițializarea corectă a maximului: cu suma primei linii (nu cu 0 — elementele pot fi negative).
C++
int best = 1, sbest = 0;
for (int j = 1; j <= n; j++) sbest += a[1][j]; // suma liniei 1for (int i = 2; i <= n; i++) {
int s = 0;
for (int j = 1; j <= n; j++) s += a[i][j];
if (s > sbest) { sbest = s; best = i; }
}
cout << "Linia " << best << ", suma " << sbest << '\n';
c) 0,75 p
Simetrică înseamnă a[i][j] = a[j][i] pentru orice i, j. Este suficient să verifici doar deasupra diagonalei (j > i) — jumătatea de jos e aceeași pereche, verificată de două ori degeaba. Un singur element diferit strică totul, deci se iese imediat din bucle.
C++
bool sim = true;
for (int i = 1; i <= n && sim; i++)
for (int j = i + 1; j <= n; j++)
if (a[i][j] != a[j][i]) { sim = false; break; }
cout << (sim ? "DA" : "NU") << '\n';
3.
Recursivitate și divide et impera
M10 · M112 p
Toate subprogramele cerute trebuie scrise recursiv. O soluție iterativă corectă primește cel mult jumătate din punctaj.
a)Scrie funcția recursivă int cmmdc(int a, int b) (algoritmul lui Euclid).0,5 p
b)Scrie subprogramul recursiv void invers(int n) care afișează cifrele lui n în ordine inversă, și int nrCifre(int n) care întoarce numărul de cifre.0,75 p
c)Scrie funcția int maxim(int v[], int st, int dr) care determină, prin divide et impera, maximul dintre elementele v[st..dr].0,75 p
Barem de corectare & rezolvare
a) 0,5 p
Cazul de bază: b == 0 → răspunsul este a. Cazul general apelează funcția cu (b, a % b) — restul scade strict, deci se ajunge sigur la 0.
C++
int cmmdc(int a, int b) {
if (b == 0) return a; // cazul de bazareturn cmmdc(b, a % b); // progres garantat: a % b < b
}
// cmmdc(12, 8) -> cmmdc(8, 4) -> cmmdc(4, 0) -> 4
b) 0,75 p
Diferența de aur: dacă afișezi înainte de apelul recursiv, cifrele ies în ordine inversă; dacă afișezi după, ies în ordine normală. Capcana: pentru n = 0 funcția invers nu afișează nimic — se tratează separat în main.
C++
void invers(int n) {
if (n == 0) return;
cout << n % 10; // AFISEZ intai -> ordine inversa
invers(n / 10);
}
int nrCifre(int n) {
if (n < 10) return1;
return1 + nrCifre(n / 10);
}
// invers(1234) afiseaza 4321 ; nrCifre(1234) = 4// atentie: pentru n = 0 se afiseaza separat cifra 0
c) 0,75 p
Cele trei etape se văd direct în cod: DIVIDE (mijlocul), STĂPÂNEȘTE (două apeluri pe jumătăți), COMBINĂ (maximul celor două rezultate). Apelul din main este maxim(v, 0, n - 1).
C++
int maxim(int v[], int st, int dr) {
if (st == dr) return v[st]; // cazul de baza: un elementint m = (st + dr) / 2; // DIVIDEint a = maxim(v, st, m); // STAPANESTE (stanga)int b = maxim(v, m + 1, dr); // STAPANESTE (dreapta)return (a > b) ? a : b; // COMBINA
}
// apel: cout << maxim(v, 0, n - 1);
4.
Greedy și interclasare
M12 · M022 p
Două tehnici clasice și o întrebare de raționament despre limitele metodei Greedy.
Exemplua) S = 87 → 1×50, 3×10, 1×5, 2×1 = 7 monede b) a = 1 4 7 9, b = 2 3 8 → c = 1 2 3 4 7 8 9
a)Se dispune de monede de 50, 10, 5 și 1 leu, în număr nelimitat. Scrie programul care plătește o sumă S cu număr minim de monede, afișând câte monede de fiecare fel se folosesc.0,75 p
b)Se dau doi vectori a (n elemente) și b (m elemente), fiecare deja sortat crescător. Interclasează-i într-un vector c, sortat crescător, fără să sortezi la final.0,75 p
c)Se schimbă sistemul de monede în 1, 3 și 4 lei, iar restul de plătit este 6 lei. Ce răspuns dă algoritmul Greedy de la a)? Care este soluția optimă? Ce concluzie tragi?0,5 p
Barem de corectare & rezolvare
a) 0,75 p
Alegerea lacomă: iei mereu cât mai multe monede din cea mai mare valoare disponibilă. S / mon[i] dă numărul de monede, S %= mon[i] lasă restul de plătit.
C++
int mon[4] = {50, 10, 5, 1}; // OBLIGATORIU descrescatorint S, total = 0;
cin >> S;
for (int i = 0; i < 4; i++) {
int k = S / mon[i]; // alegerea lacomaif (k > 0) cout << k << " x " << mon[i] << '\n';
total += k;
S %= mon[i]; // ce ramane de platit
}
cout << "Total monede: " << total << '\n';
b) 0,75 p
Doi indicatori pornesc de la începutul vectorilor și coboară de fiecare dată minimul. Capcana de barem: cele două bucle de la final, care golesc vectorul rămas — fără ele se pierd elemente. Complexitatea este O(n + m), față de O((n+m)log(n+m)) dacă ai fi sortat.
C++
int i = 0, j = 0, k = 0;
while (i < n && j < m)
if (a[i] <= b[j]) c[k++] = a[i++];
else c[k++] = b[j++];
while (i < n) c[k++] = a[i++]; // ce a ramas din awhile (j < m) c[k++] = b[j++]; // ce a ramas din bfor (int t = 0; t < k; t++) cout << c[t] << ' ';
c) 0,5 p
Greedy alege lacom: 4 + 1 + 1 → 3 monede. Optimul este 3 + 3 → 2 monede. Concluzia: Greedy nu este corect pentru orice sistem de monede — el garantează optimul doar dacă sistemul are proprietatea potrivită (cum au 50/10/5/1 sau monedele reale). Pentru cazul general este nevoie de programare dinamică, exact ce se învață anul acesta.
Nota ta
1.00
Începe cu grila — nota pornește de la 1 punct din oficiu.