O matrice (tablou bidimensional) e un tabel de valori organizat pe linii și coloane. La BAC informatică, matricele apar la itemii scurți de la Subiectul II și la problema cu tablouri de la Subiectul III: construiești o matrice după o regulă, calculezi sume pe linii sau coloane, cauți elemente cu o proprietate. Toate pornesc de la aceleași câteva tipare de parcurgere în C++, pe care le vezi mai jos.

Declararea și indicii

int a[101][101];   // linii 0..100, coloane 0..100
int n, m;          // n linii, m coloane folosite efectiv

Elementul de pe linia i și coloana j se scrie a[i][j] — întâi linia, apoi coloana. Ca la vectori, dimensiunea declarată e cea maximă, iar n și m spun cât folosești efectiv. Numerotarea poate începe de la 0 sau de la 1; aici folosim 1, ca în multe enunțuri. Declarată global, matricea e inițializată cu 0.

Atenție la memorie: o matrice int de 1000 × 1000 ocupă aproximativ 4 MB. Declar-o global, nu în main, unde spațiul pentru variabile locale e mult mai mic.

Citirea și afișarea

#include <iostream>
using namespace std;

int a[101][101], n, m;

int main()
{
    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++)
    {
        for (int j = 1; j <= m; j++)
            cout << a[i][j] << " ";
        cout << endl;              // linie nouă după fiecare linie a matricei
    }
    return 0;
}

Citirea se face pe linii: bucla exterioară e pe i (linii), cea interioară pe j (coloane), pentru că așa sunt date valorile în fișier sau la tastatură. La afișare, endl (sau '\n') stă după bucla interioară, nu în ea. Pus în interior, fiecare element ar apărea pe un rând separat; uitat de tot, matricea iese pe un singur rând.

Parcurgerea pe linii și pe coloane

Pentru exemplele de mai jos folosim matricea cu n = 3 linii și m = 4 coloane:

 1  2  3  4
 5  6  7  8
 9 10 11 12

Suma fiecărei linii: pentru fiecare linie i, pornești suma de la 0 și aduni elementele de pe coloanele 1..m.

for (int i = 1; i <= n; i++)
{
    int s = 0;                    // resetată pentru fiecare linie
    for (int j = 1; j <= m; j++)
        s = s + a[i][j];
    cout << s << " ";             // 10 26 42
}

Suma fiecărei coloane: inversezi buclele — exterior pe coloane, interior pe linii.

for (int j = 1; j <= m; j++)
{
    int s = 0;
    for (int i = 1; i <= n; i++)
        s = s + a[i][j];
    cout << s << " ";             // 15 18 21 24
}

Verificare rapidă: suma sumelor pe linii (10 + 26 + 42) și suma sumelor pe coloane (15 + 18 + 21 + 24) trebuie să dea același total, 78. E un test bun pe ciornă.

La BAC: greșeala clasică e inițializarea sumei o singură dată, înainte de ambele bucle. Atunci a doua linie primește suma cumulată (36 în loc de 26). Variabila care se calculează „pentru fiecare linie” se inițializează în interiorul buclei pe linii, înainte de bucla pe coloane.

Maximul pe fiecare linie și linia cu suma maximă

int smax = -1, lmax = 0;
for (int i = 1; i <= n; i++)
{
    int mx = a[i][1], s = 0;
    for (int j = 1; j <= m; j++)
    {
        if (a[i][j] > mx) mx = a[i][j];
        s = s + a[i][j];
    }
    cout << "maximul liniei " << i << ": " << mx << endl;
    if (s > smax) { smax = s; lmax = i; }
}
cout << "linia cu suma maxima: " << lmax;

Pe exemplu: maximele pe linii sunt 4, 8, 12, iar linia cu suma maximă e 3 (suma 42). Inițializarea smax = -1 merge doar dacă elementele sunt naturale; altfel pornește smax de la suma primei linii.

Căutarea unui element

Ca să afli dacă valoarea x apare în matrice și unde apare prima dată (parcurgând pe linii), folosești o variabilă de tip „găsit”:

bool gasit = false;
for (int i = 1; i <= n && !gasit; i++)
    for (int j = 1; j <= m && !gasit; j++)
        if (a[i][j] == x)
        {
            cout << i << " " << j;
            gasit = true;
        }
if (!gasit) cout << "nu exista";

Condiția !gasit din ambele bucle oprește parcurgerea imediat după prima apariție. Un simplu break ar ieși doar din bucla interioară, iar cea exterioară ar continua cu linia următoare.

Interschimbarea a două linii sau coloane

// liniile p și q
for (int j = 1; j <= m; j++)
{ int aux = a[p][j]; a[p][j] = a[q][j]; a[q][j] = aux; }

// coloanele p și q
for (int i = 1; i <= n; i++)
{ int aux = a[i][p]; a[i][p] = a[i][q]; a[i][q] = aux; }

Reține simetria: la linii, indicele care variază e coloana j; la coloane, variază linia i.

Program complet

Se citesc n, m și o matrice cu n linii și m coloane de numere naturale. Afișați indicii coloanelor care conțin doar numere pare, sau mesajul „nu exista”.

#include <iostream>
using namespace std;

int a[101][101], n, m;

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];

    bool exista = false;
    for (int j = 1; j <= m; j++)
    {
        bool toatePare = true;
        for (int i = 1; i <= n; i++)
            if (a[i][j] % 2 != 0) toatePare = false;
        if (toatePare)
        {
            cout << j << " ";
            exista = true;
        }
    }
    if (!exista) cout << "nu exista";
    return 0;
}

Pentru matricea cu liniile 2 3 4 și 6 8 10, coloana 1 (2, 6) și coloana 3 (4, 10) au doar numere pare, iar coloana 2 conține 3, deci programul afișează 1 3.

De reținut