Declararea și citirea matricelor
O matrice (tablou bidimensional) stochează date în rânduri și coloane, accesate prin doi indici: a[linie][coloana].
int a[101][101]; // matrice de maxim 100×100 int n, m; // n linii, m coloane // Citire cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> a[i][j]; // Afișare for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) cout << a[i][j] << " "; cout << endl; }
Stocată pe linii în RAM (row-major order)
a[i][j] — acces direct prin indici
Parcurgere — sumă, minim, maxim
Suma elementelor pe linii și coloane
// Suma tuturor elementelor int suma = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) suma += a[i][j]; // Suma pe fiecare linie for (int i = 1; i <= n; i++) { int sumaLinie = 0; for (int j = 1; j <= m; j++) sumaLinie += a[i][j]; cout << "Suma linia " << i << ": " << sumaLinie << endl; }
Minimul și poziția sa
int minim = a[1][1], linMin = 1, colMin = 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (a[i][j] < minim) { minim = a[i][j]; linMin = i; colMin = j; }
Diagonalele matricei pătratice
• Diagonala principală: elemente unde
i == j • Diagonala secundară: elemente unde
i + j == n + 1 | Indexare | Diagonala principală | Diagonala secundară | Exemplu n=5 |
|---|---|---|---|
| de la 1 (BAC, standard) | i == j | i + j == n + 1 | (1,5),(2,4),(3,3),(4,2),(5,1) — suma i+j = 6 = n+1 |
| de la 0 (C++ array) | i == j | i + j == n - 1 | (0,4),(1,3),(2,2),(3,1),(4,0) — suma i+j = 4 = n-1 |
La BAC se folosește exclusiv indexarea de la 1. Condiția pentru diagonala secundară este i + j == n + 1, iar accesul în cod este a[i][n-i+1].
// Suma diagonalei principale int sumaDiagP = 0; for (int i = 1; i <= n; i++) sumaDiagP += a[i][i]; // Suma diagonalei secundare int sumaDiagS = 0; for (int i = 1; i <= n; i++) sumaDiagS += a[i][n-i+1];
Triunghiul superior și inferior
// Suma elementelor DEASUPRA diagonalei principale (triunghi superior) int sumaSup = 0; for (int i = 1; i <= n; i++) for (int j = i+1; j <= n; j++) // j > i sumaSup += a[i][j]; // Suma elementelor SUB diagonala principală (triunghi inferior) int sumaInf = 0; for (int i = 1; i <= n; i++) for (int j = 1; j < i; j++) // j < i sumaInf += a[i][j];
Apasă pe un buton pentru a evidenția zona corespunzătoare. Suma elementelor evidențiate apare în dreapta.
Transpusa matricei
Transpusa matricei A este matricea B unde B[i][j] = A[j][i] — liniile devin coloane și viceversa.
// Transpusa în matrice separată (funcționează și pentru dreptunghice) int t[101][101]; // t are m linii și n coloane for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) t[j][i] = a[i][j];
// Transpusa IN-PLACE pentru matrice PĂTRATICĂ (n×n) for (int i = 1; i <= n; i++) for (int j = i+1; j <= n; j++) swap(a[i][j], a[j][i]); // interschimbăm deasupra diagonalei
A = [[1,2,3],[4,5,6]] → Aᵀ = [[1,4],[2,5],[3,6]]
Pentru o matrice 4×4, executăm swap(a[i][j], a[j][i]) pentru fiecare j > i. Vor fi exact n(n−1)/2 = 6 interschimbări.
Rotirea matricei cu 90°
Rotirea unei matrice n×n cu 90° în sens orar: b[j][n-i+1] = a[i][j]
// Rotire 90° sens orar (Clockwise) int b[101][101]; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) b[j][n-i+1] = a[i][j]; // Rotire 90° sens antiorar (Counter-Clockwise) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) b[n-j+1][i] = a[i][j];
b[n-i+1][n-j+1] = a[i][j] Sursa în stânga, destinația în dreapta. Fiecare celulă din A își găsește locul în B.
Matrice pătratice speciale
Matrice simetrică față de diagonala principală
bool esteSimetrica = true; for (int i = 1; i <= n && esteSimetrica; i++) for (int j = 1; j < i; j++) if (a[i][j] != a[j][i]) esteSimetrica = false;
Matrice cu borduri (cadru)
// Suma elementelor de pe bordul matricei int sumaBord = 0; for (int j = 1; j <= m; j++) sumaBord += a[1][j] + a[n][j]; // liniile 1 și n for (int i = 2; i < n; i++) sumaBord += a[i][1] + a[i][m]; // coloanele 1 și m
Umplere cu 0 a bordurilor
for (int j = 1; j <= m; j++) a[1][j] = a[n][j] = 0; for (int i = 1; i <= n; i++) a[i][1] = a[i][m] = 0;
Matrice identitate
// Creare matrice identitate n×n for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) a[i][j] = (i == j) ? 1 : 0;
Parcurgere în spirală
void spirala(int a[][101], int n, int m) { int top = 1, bot = n, left = 1, right = m; while (top <= bot && left <= right) { for (int j = left; j <= right; j++) cout << a[top][j] << " "; top++; for (int i = top; i <= bot; i++) cout << a[i][right] << " "; right--; if (top <= bot) { for (int j = right; j >= left; j--) cout << a[bot][j] << " "; bot--; } if (left <= right) { for (int i = bot; i >= top; i--) cout << a[i][left] << " "; left++; } } }
Urmărește celula curentă (galben) și ordinea de vizitare (mov). Output-ul se construiește pas cu pas.
Demo Interactiv — Zone Matrice 5×5
O matrice pătratică n×n are mai multe zone speciale. Elementul de pe linia i și coloana j aparține:
- Diagonalei principale dacă
i == j - Diagonalei secundare dacă
i + j == n + 1 - Triunghiului superior dacă
j > i - Triunghiului inferior dacă
j < i - Bordurii dacă
i==1 || i==n || j==1 || j==n
Apasă butoanele de mai jos pentru a vedea evidențiată fiecare zonă:
Probleme rezolvate — matrici
5 probleme clasice cu enunț, exemplu și soluție comentată.
3 4 1 5 2 7 9 3 1 4 6 6 8 2
7 9 8
💡 Vezi soluția
#include <iostream> using namespace std; int a[55][55]; int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> a[i][j]; for (int i = 1; i <= n; i++) { int mx = a[i][1]; for (int j = 2; j <= m; j++) if (a[i][j] > mx) mx = a[i][j]; cout << mx << " "; } return 0; }
Idee: pentru fiecare linie, inițializăm mx cu primul element și actualizăm pe rest. Complexitate O(n·m).
3 1 2 3 4 5 6 7 8 9
11
💡 Vezi soluția
int sum = 0; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) // j > i ⇒ strict deasupra sum += a[i][j]; cout << sum;
Pe exemplu: 2 + 3 + 6 = 11. Atenție: dacă cerea „inclusiv diagonala", condiția ar fi j >= i.
a[i][j] == a[j][i] pentru orice i, j). Afișează DA sau NU.3 1 2 3 2 5 4 3 4 9
DA
💡 Vezi soluția
bool sim = true; for (int i = 1; i <= n && sim; i++) for (int j = 1; j < i && sim; j++) // doar sub diagonală if (a[i][j] != a[j][i]) sim = false; cout << (sim ? "DA" : "NU");
Optimizare: verificăm doar jumătate (j < i), pentru că (i,j) și (j,i) sunt simetrice; cu break-ul prin sim ieșim imediat ce găsim o nepotrivire.
3 3 1 2 3 4 5 6 7 8 9
3
💡 Vezi soluția
int idxMax = 1, sumMax = 0; for (int i = 1; i <= n; i++) sumMax += a[i][1]; for (int j = 2; j <= m; j++) { int s = 0; for (int i = 1; i <= n; i++) s += a[i][j]; if (s > sumMax) { sumMax = s; idxMax = j; } } cout << idxMax;
Pe exemplu: coloana 1: 12, coloana 2: 15, coloana 3: 18 → răspuns 3. Bucla externă pe j, internă pe i ⇒ parcurgem matricea pe coloane.
3 1 2 3 4 5 6 7 8 9
7 4 1 8 5 2 9 6 3
💡 Vezi soluția
// Truc: transpunere + inversare a fiecărei linii // 1) Transpunere in-place for (int i = 1; i <= n; i++) for (int j = i+1; j <= n; j++) swap(a[i][j], a[j][i]); // 2) Inversăm fiecare linie for (int i = 1; i <= n; i++) for (int j = 1; j <= n/2; j++) swap(a[i][j], a[i][n-j+1]);
De ce funcționează: transpunerea reflectă matricea pe diagonala principală; inversarea liniilor adaugă reflexia verticală. Compunerea celor două reflexii = rotație 90° CW. Complexitate O(n²), memorie O(1).
Pentru CCW: transpunere + inversare a fiecărei coloane.
Probleme tip BAC — matrici
bool esteMagica(int a[][101], int n) { int suma = 0; for (int i=1; i<=n; i++) suma += a[1][i]; // suma primei linii for (int i=2; i<=n; i++) { int s=0; for (int j=1;j<=n;j++) s+=a[i][j]; if(s!=suma) return false; } for (int j=1; j<=n; j++) { int s=0; for (int i=1;i<=n;i++) s+=a[i][j]; if(s!=suma) return false; } int d1=0, d2=0; for (int i=1;i<=n;i++) { d1+=a[i][i]; d2+=a[i][n-i+1]; } return (d1==suma && d2==suma); }