Vecinii unei celule
Tehnica standard: vectorii de direcție.
#include <iostream>
using namespace std;
int main() {
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, n = 3, m = 3;
int i = 1, j = 1, s = 0;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, 1, -1};
for (int d = 0; d < 4; d++) {
int ni = i + dx[d], nj = j + dy[d];
if (ni >= 0 && ni < n && nj >= 0 && nj < m)
s += a[ni][nj];
}
cout << s;
return 0;
}Atenție: Verificarea marginilor e obligatorie. Fara ea, pentru o celula de pe margine s-ar citi in afara matricei.
Pentru 8 vecini (cu diagonale), extinzi vectorii la 8 perechi.
Bordarea (santinela)
Alternativa elegantă la verificarea limitelor: ÎNCONJORI matricea cu un cadru de valori neutre (0 sau o valoare care nu deranjează) și lucrezi cu indicii 1..n:
#include <iostream>
using namespace std;
int main() {
int a[5][5] = {0};
int n = 3, m = 3;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = (i - 1) * m + j;
int s = 0;
for (int d = 0; d < 4; d++) {
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, 1, -1};
s += a[2 + dx[d]][2 + dy[d]];
}
cout << s;
return 0;
}Atenție: Bordarea inseamna a lasa in jurul matricei o rama de zerouri. Asa nu mai trebuie verificate marginile: vecinii din afara exista si valoreaza zero.
Acum a[i-1][j] există întotdeauna pentru i din 1..n: dispar toate condițiile de margine.
Exemplu rezolvat
Matricea 3×3 cu valorile 1..9 (pe linii). Suma vecinilor pe 4 direcții ai celulei centrale (valoarea 5): vecinii sunt 2 (N), 8 (S), 6 (E), 4 (V): suma 20.
Unde apare la BAC
Sume pe vecinătăți, numărarea elementelor "izolate" (mai mari decât toți vecinii), drumuri în matrice, jocuri de viață simplificate: toate se reduc la dx/dy + verificarea limitelor sau bordare.
Greșeli frecvente
- Fără verificarea limitelor, colțurile citesc memorie din afara matricei.
- La bordare, valorile santinelei trebuie NEUTRE pentru operație (0 la sumă, dar -infinit la maxim!).
- Perechile dx/dy se parcurg sincron: dx[d] cu dy[d], nu combinații încrucișate.