Skip to content

Chenarul matricei ​

Chenarul unei matrici este format din elementele aflate pe marginea ei:

  • prima linie (linia 1)
  • ultima linie (linia n)
  • prima coloana (coloana 1)
  • ultima coloana (coloana m)

Pentru o matrice cu n = 4 linii si m = 5 coloane, elementele de pe chenar sunt cele marcate cu *:

coloana 1coloana 2coloana 3coloana 4coloana 5
linia 1*****
linia 2**
linia 3**
linia 4*****

Observatie

colturile matricei (a[1][1], a[1][m], a[n][1], a[n][m]) fac parte si din linia, si din coloana corespunzatoare — trebuie sa le numaram o singura data.


Afisarea elementelor de pe chenar ​

Vrem sa afisam elementele chenarului in ordine, fiecare o singura data, mergand "in jurul" matricei pornind din coltul din stanga-sus:

  1. prima linie, de la stanga la dreapta: a[1][1], a[1][2], ..., a[1][m]
  2. ultima coloana, de sus in jos, sarind peste a[1][m] (deja afisat): a[2][m], a[3][m], ..., a[n][m]
  3. ultima linie, de la dreapta la stanga, sarind peste a[n][m]: a[n][m-1], a[n][m-2], ..., a[n][1]
  4. prima coloana, de jos in sus, sarind peste a[n][1] si peste a[1][1]: a[n-1][1], a[n-2][1], ..., a[2][1]

Folosim patru for-uri separate, cate unul pentru fiecare latura. Nu parcurgem toata matricea.

cpp
#include <iostream>
using namespace std;
int a[101][101], n, m, i, j;

int main()
{
    cin >> n >> m;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> a[i][j];
        }
    }
    // 1. prima linie, de la stanga la dreapta
    for (j = 1; j <= m; j++)
    {
        cout << a[1][j] << " ";
    }
    // 2. ultima coloana, de sus in jos (de la linia 2 in jos)
    for (i = 2; i <= n; i++)
    {
        cout << a[i][m] << " ";
    }
    // 3. ultima linie, de la dreapta la stanga (de la coloana m-1 catre coloana 1)
    for (j = m - 1; j >= 1; j--)
    {
        cout << a[n][j] << " ";
    }
    // 4. prima coloana, de jos in sus (de la linia n-1 catre linia 2)
    for (i = n - 1; i >= 2; i--)
    {
        cout << a[i][1] << " ";
    }
    return 0;
}

Intrare:

4 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20

Afisare:

1 2 3 4 5 10 15 20 19 18 17 16 11 6

Observatie

observa cum am pornit din coltul din stanga-sus (1) si am mers in sensul acelor de ceasornic, terminand la elementul de deasupra punctului de plecare (6):

  • prima linie: 1 2 3 4 5
  • ultima coloana (de sus in jos, fara 5 care era pe prima linie): 10 15 20
  • ultima linie (de la dreapta la stanga, fara 20 care era pe ultima coloana): 19 18 17 16
  • prima coloana (de jos in sus, fara 16 care era pe ultima linie si fara 1 care era pe prima linie): 11 6

Atentie

indicii de start 2 (la al doilea for) si n - 1, 2 (la ultimele doua) sunt alesi tocmai pentru a evita coltul care a fost deja afisat de for-ul anterior. Fara aceste ajustari, colturile ar fi afisate de doua ori.


Chenare imbricate ​

  • Chenarul de mai sus este chenarul exterior al matricei.
  • Dar daca "intram" cu o pozitie mai aproape de centru, gasim un alt chenar, mai mic, in interiorul lui.

Notam:

  • chenarul 1 = chenarul exterior (prima si ultima linie, prima si ultima coloana)
  • chenarul 2 = un nivel spre interior (liniile 2 si n-1, coloanele 2 si m-1)
  • chenarul 3 = inca un nivel spre interior (liniile 3 si n-2, coloanele 3 si m-2)
  • ...
  • chenarul k = liniile k si n-k+1, coloanele k si m-k+1

Iata cum arata chenarele unei matrici cu n = 5 si m = 5. Pe fiecare element am scris numarul chenarului din care face parte:

coloana 1coloana 2coloana 3coloana 4coloana 5
linia 111111
linia 212221
linia 312321
linia 412221
linia 511111

Cate chenare sunt? ​

Numarul de chenare depinde de cea mai mica dimensiune (cea care "se termina prima" cand intram spre centru):

  • daca min(n, m) este par, sunt exact min(n, m) / 2 chenare
  • daca min(n, m) este impar, sunt (min(n, m) + 1) / 2 chenare, iar chenarul din mijloc este degenerat: are o singura linie, o singura coloana sau un singur element

Observatie

in matricea 5 x 5 de mai sus, min(n, m) = 5 este impar, deci sunt (5 + 1) / 2 = 3 chenare. Chenarul 3 este degenerat — un singur element, a[3][3].

Sfat

pentru a calcula numarul chenarului din care face parte elementul a[i][j] exista o formula scurta:

chenar = min(i, j, n - i + 1, m - j + 1)

intuitia: e distanta pana la cea mai apropiata margine (sus, stanga, jos sau dreapta).


Etichetarea chenarelor ​

Vrem sa completam matricea astfel incat fiecare element sa contina numarul chenarului din care face parte, apoi sa o afisam.

Logica:

  • parcurgem matricea cu doua for-uri imbricate pe i si j
  • pentru fiecare element, calculam min(i, j, n - i + 1, m - j + 1) si il scriem in a[i][j]
cpp
#include <iostream>
using namespace std;
int a[101][101], n, m, i, j, chenar;

int main()
{
    cin >> n >> m;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            chenar = i;
            if (j < chenar)
                chenar = j;
            if (n - i + 1 < chenar)
                chenar = n - i + 1;
            if (m - j + 1 < chenar)
                chenar = m - j + 1;
            a[i][j] = chenar;
        }
    }
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Intrare:

5 5

Afisare:

1 1 1 1 1 
1 2 2 2 1 
1 2 3 2 1 
1 2 2 2 1 
1 1 1 1 1

Observatie

nu am citit valori pentru matrice — am completat noi matricea pornind de la n si m.

Sfat

aceeasi formula functioneaza si pentru matrici dreptunghiulare. Pentru n = 3 si m = 6 obtii:

1 1 1 1 1 1
1 2 2 2 2 1
1 1 1 1 1 1

Aici exista un singur chenar complet (1) si un chenar degenerat (2) — o singura linie din mijloc.


Parcurgerea in spirala ​

Vrem sa afisam elementele matricei in ordinea: mai intai chenarul exterior (in sensul acelor de ceasornic), apoi chenarul urmator, ... pana la chenarul cel mai interior. Aceasta este parcurgerea in spirala.

Logica:

  • un for exterior pe k, parcurge chenarele de la 1 la numarul total de chenare
  • pentru fiecare chenar k, repetam cele 4 for-uri de la afisarea unui chenar, dar parametrizate dupa k:
    • colturile chenarului k sunt (k, k), (k, m-k+1), (n-k+1, m-k+1), (n-k+1, k)

Trebuie sa avem grija la chenarele degenerate (cand n-k+1 == k sau m-k+1 == k):

  • daca n - k + 1 == k, chenarul are o singura linie — for-ul pentru linia de jos ar repeta linia de sus. Il sarim.
  • daca m - k + 1 == k, chenarul are o singura coloana — for-ul pentru coloana din stanga ar repeta coloana din dreapta. Il sarim.
cpp
#include <iostream>
using namespace std;
int a[101][101], n, m, i, j, k, nrChenare, ultimaLin, ultimaCol;

int main()
{
    cin >> n >> m;
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= m; j++)
        {
            cin >> a[i][j];
        }
    }
    if (n < m)
        nrChenare = (n + 1) / 2;
    else
        nrChenare = (m + 1) / 2;
    for (k = 1; k <= nrChenare; k++)
    {
        ultimaLin = n - k + 1;
        ultimaCol = m - k + 1;
        // 1. linia de sus a chenarului k: a[k][k..ultimaCol]
        for (j = k; j <= ultimaCol; j++)
        {
            cout << a[k][j] << " ";
        }
        // 2. coloana din dreapta: a[k+1..ultimaLin][ultimaCol]
        for (i = k + 1; i <= ultimaLin; i++)
        {
            cout << a[i][ultimaCol] << " ";
        }
        // 3. linia de jos (doar daca difera de linia de sus): a[ultimaLin][ultimaCol-1..k]
        if (ultimaLin > k)
        {
            for (j = ultimaCol - 1; j >= k; j--)
            {
                cout << a[ultimaLin][j] << " ";
            }
        }
        // 4. coloana din stanga (doar daca difera de coloana din dreapta): a[ultimaLin-1..k+1][k]
        if (ultimaCol > k)
        {
            for (i = ultimaLin - 1; i >= k + 1; i--)
            {
                cout << a[i][k] << " ";
            }
        }
    }
    return 0;
}

Intrare:

4 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20

Afisare:

1 2 3 4 5 10 15 20 19 18 17 16 11 6 7 8 9 14 13 12

Observatie

spirala incepe cu chenarul 1 (1 2 3 4 5 10 15 20 19 18 17 16 11 6), apoi continua cu chenarul 2 (7 8 9 14 13 12). Pentru o matrice 4 x 5, min(n, m) = 4 este par, deci sunt exact 4 / 2 = 2 chenare.

Important

colturile chenarului k sunt: (k, k) — stanga-sus, (k, m-k+1) — dreapta-sus, (n-k+1, m-k+1) — dreapta-jos, (n-k+1, k) — stanga-jos. Toate cele 4 for-uri lucreaza intre acesti indici.

Atentie

cele doua if-uri (ultimaLin > k si ultimaCol > k) sunt esentiale pentru cazul chenarelor degenerate. Daca le omiti, pentru o matrice cu dimensiune impara (ex. 5 x 5), chenarul din mijloc va fi afisat de mai multe ori sau in ordine gresita.

Acelasi cod functioneaza si pentru o matrice patratica. Pentru n = m = 5, min(n, m) = 5 este impar, deci sunt (5 + 1) / 2 = 3 chenare, iar chenarul 3 este degenerat (un singur element, a[3][3]):

Intrare:

5 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

Afisare:

1 2 3 4 5 10 15 20 25 24 23 22 21 16 11 6 7 8 9 14 19 18 17 12 13

Observatie

spirala parcurge chenarul 1 (1 2 3 4 5 10 15 20 25 24 23 22 21 16 11 6), apoi chenarul 2 (7 8 9 14 19 18 17 12) si in final chenarul 3, degenerat (13). Pentru chenarul 3 avem k = 3, ultimaLin = ultimaCol = 3: ambele if-uri sunt false, asa ca elementul din mijloc se afiseaza o singura data de primul for.