Tablouri bidimensionale (matrice)
Ideile de bază pe scurt și, unde există, exercițiile din subiectele de BAC care le verifică. Lecția completă, animată, cu grile și exerciții corectate, e în aplicația Tomomi.
Pe scurt
Sintaxă: declararea și citirea unei matrice
Forma canonică: capacitățile maxime se declară o dată, apoi primele n linii și m coloane se umplu din intrare, cu două bucle imbricate:
int a[10][10];
int n;
int m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
}
}Capcana: întâi linia, apoi coloana
a[i][j] este LINIA i, COLOANA j - nu coordonatele (x, y) de la matematică. a[1][3] și a[3][1] sunt celule diferite. Și indicii pornesc de la 0 pe ambele dimensiuni: ultima celulă este a[n - 1][m - 1], nu a[n][m].
Șablon: suma pe fiecare linie
Acumulatorul se resetează la începutul fiecărei linii:
for (int i = 0; i < n; i++) {
int s = 0;
for (int j = 0; j < m; j++) {
s = s + a[i][j];
}
cout << s << "\n";
}
// coloana fixă j: bucla pe i, s = s + a[i][j];Idee: un indice fix, unul liber
Suma pe o linie ține i fix și lasă j să alerge; suma pe o coloană ține j fix și lasă i să alerge. Orice prelucrare pe zone (linii, coloane, diagonale) pornește de la întrebarea: care indice este fix și care variază?
Șablon: diagonalele matricei pătratice
Câte o singură buclă pe i ajunge pentru fiecare diagonală:
// principala: i == j
s = s + a[i][i];
// secundara: i + j == n - 1
s = s + a[i][n - 1 - i];Capcana: transpusa se face o singură dată per pereche
La transpunere interschimbi a[i][j] cu a[j][i]. Dacă bucla interioară pornește de la j = 0, fiecare pereche se schimbă de două ori și revine la loc. Pornește de la j = i + 1: vizitezi doar celulele de deasupra diagonalei, iar diagonala nu se atinge.
Din subiectele de BAC
Exerciții reale din subiectele anilor trecuți. Încearcă-le singur înainte să deschizi rezolvarea.
Indicați o declarare a unui tablou bidimensional m, care poate memora maximum 100 de numere reale.
a. float m[2,50];
b. float m[4][25];
c. float m[10] x float m[10];
d. int m[100];
Vezi rezolvarea
Cerința are trei condiții: tabloul trebuie să fie bidimensional, să memoreze numere reale și să aibă cel mult 100 de elemente.
- a.
float m[2,50];- în C/C++ virgula dintre paranteze este operatorul virgulă, nu un separator de dimensiuni; declarația este echivalentă cufloat m[50];, deci un tablou unidimensional. - b.
float m[4][25];- bidimensional, elemente reale, elemente. Corect. - c.
float m[10] x float m[10];- nu este o sintaxă C/C++ validă. - d.
int m[100];- unidimensional și cu elemente întregi.
Răspunsul corect este litera b.
Variabilele i și j sunt de tip întreg, iar variabila a memorează un tablou bidimensional cu 9 linii și 9 coloane, numerotate începând de la 0, având inițial toate elementele nule. Scrieți secvența de instrucțiuni de mai jos, înlocuind punctele de suspensie cu instrucțiuni adecvate, dintre care cel mult patru de atribuire, astfel încât, în urma executării secvenței obținute, variabila a să memoreze tabloul alăturat.
for(i=0;i<9;i++)
for(j=0;j<9;j++)
..................Tabloul cerut (liniile 0-8):
4 4 4 4 2 2 2 2 2
4 4 4 2 2 2 2 2 2
4 4 2 2 2 2 2 2 2
4 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 4
2 2 2 2 2 2 2 4 4
2 2 2 2 2 2 4 4 4
2 2 2 2 2 4 4 4 4Vezi rezolvarea
Observăm poziția valorilor 4: în colțul din stânga-sus apar exact acolo unde (pe linia 0 primele 4 coloane, pe linia 1 primele 3 etc.), iar în colțul din dreapta-jos exact acolo unde (pe linia 5 doar coloana 8, pe linia 8 coloanele 5-8). În rest, elementele sunt 2.
Secvența completată, cu două instrucțiuni de atribuire:
for(i=0;i<9;i++)
for(j=0;j<9;j++)
if(i+j<=3 || i+j>=13)
a[i][j]=4;
else
a[i][j]=2;Pentru a identifica punctele în care se concentrează apa în albia unui râu în cazul secetei, se determină talvegul acesteia, adică linia care unește punctele cele mai adânci ale albiei. În acest scop s-au stabilit ns secțiuni transversale pe cursul apei, numerotate începând de la 1, și în cadrul fiecărei secțiuni s-a măsurat adâncimea apei în np puncte, numerotate începând de la 1. Din fiecare secțiune, în ordine, se include în talveg cel mai adânc punct al acesteia, iar dacă în secțiune sunt mai multe puncte aflate la aceeași adâncime, maximă, se va lua în considerare doar primul dintre ele.
Scrieți un program C/C++ care citește de la tastatură două numere naturale, ns și np (, ), și cele elemente ale unui tablou bidimensional, valori naturale din intervalul . Fiecare linie a tabloului corespunde câte unei secțiuni, în ordinea numerotării acestora, iar valorile memorate pe linie reprezintă adâncimile celor np puncte stabilite pentru acea secțiune, în ordinea numerotării lor. Programul afișează pe ecran, pentru fiecare secțiune, o pereche formată din numărul de ordine al secțiunii și numărul de ordine al punctului său care s-a inclus în talveg. Numerele din fiecare pereche sunt afișate separate prin câte un caracter : (două puncte), iar fiecare pereche este urmată de un spațiu.
Exemplu: pentru ns=6, np=4 și tabloul cu liniile (2 4 5 3), (2 6 6 3), (1 5 2 5), (1 3 3 3), (3 4 3 5), (0 1 2 1), se afișează pe ecran valorile: 1:3 2:2 3:2 4:2 5:4 6:3
Vezi rezolvarea
#include <iostream>
using namespace std;
int main() {
int ns, np, a[1001][51];
cin >> ns >> np;
for (int i = 1; i <= ns; i++)
for (int j = 1; j <= np; j++)
cin >> a[i][j];
for (int i = 1; i <= ns; i++) {
int pmax = 1;
for (int j = 2; j <= np; j++)
if (a[i][j] > a[i][pmax])
pmax = j;
cout << i << ":" << pmax << " ";
}
return 0;
}Comparația strictă a[i][j] > a[i][pmax] garantează că, la adâncimi egale, rămâne selectat primul punct de adâncime maximă din secțiune. Pentru exemplul dat se afișează 1:3 2:2 3:2 4:2 5:4 6:3.