Estructuras de Datosc++matricesarreglos 2Dbidimensional

Matrices

Aprende a trabajar con arreglos bidimensionales y matrices en C++

OOI Oaxaca9 de febrero de 20266 min read

¿Qué es una matriz?

Si un arreglo es una fila de casilleros, una matriz es una cuadrícula de casilleros con filas y columnas. Piensa en un tablero de ajedrez, un campo de minas, una hoja de cálculo de Excel, o la pantalla de píxeles de tu computadora.

Matriz 3×4:
         Col 0  Col 1  Col 2  Col 3
Fila 0 [  1  ,  2  ,  3  ,  4  ]
Fila 1 [  5  ,  6  ,  7  ,  8  ]
Fila 2 [  9  , 10  , 11  , 12  ]

Para acceder a un elemento, necesitas dos índices: la fila y la columna. mat[1][2] es el elemento en la fila 1, columna 2, que en el ejemplo es 7.

Declarar matrices

Arreglo estático 2D

int mat[3][4];                // Matriz 3×4 sin inicializar
int mat[3][4] = {{0}};        // Matriz 3×4 toda en ceros
int mat[3][3] = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

Con vectores (más flexible)

int filas = 3, cols = 4;
vector<vector<int>> mat(filas, vector<int>(cols, 0));  // 3×4, todo ceros

Global (recomendado en competencias)

const int MAXN = 1001;
int mat[MAXN][MAXN];  // Se inicializa a 0 automáticamente por ser global

Leer y escribir matrices

Leer

int n, m;  // n filas, m columnas
cin >> n >> m;

int mat[1001][1001];
for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        cin >> mat[i][j];
    }
}

Escribir

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        if (j > 0) cout << " ";
        cout << mat[i][j];
    }
    cout << '\n';
}

Recorridos de una matriz

Recorrer por filas (lo más natural)

for (int i = 0; i < n; i++) {       // Para cada fila
    for (int j = 0; j < m; j++) {   // Para cada columna
        // Procesar mat[i][j]
    }
}

Recorrer por columnas

for (int j = 0; j < m; j++) {       // Para cada columna
    for (int i = 0; i < n; i++) {   // Para cada fila
        // Procesar mat[i][j]
    }
}

Recorrer la diagonal principal

// Solo funciona si es cuadrada (n×n)
for (int i = 0; i < n; i++) {
    cout << mat[i][i] << " ";
}

Recorrer la diagonal secundaria

for (int i = 0; i < n; i++) {
    cout << mat[i][n - 1 - i] << " ";
}

Los 4 (u 8) vecinos

En muchos problemas, necesitas visitar las celdas vecinas de una posición (i, j):

        (i-1,j)
           ↑
(i,j-1) ← (i,j) → (i,j+1)
           ↓
        (i+1,j)

4 vecinos (arriba, abajo, izquierda, derecha)

int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

for (int d = 0; d < 4; d++) {
    int ni = i + dx[d];
    int nj = j + dy[d];

    // Verificar que esté dentro de los límites
    if (ni >= 0 && ni < n && nj >= 0 && nj < m) {
        // mat[ni][nj] es un vecino válido
    }
}

8 vecinos (incluye diagonales)

int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};

for (int d = 0; d < 8; d++) {
    int ni = i + dx[d];
    int nj = j + dy[d];
    if (ni >= 0 && ni < n && nj >= 0 && nj < m) {
        // Procesar vecino mat[ni][nj]
    }
}

Problemas clásicos con matrices

1. Suma de elementos

int suma = 0;
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        suma += mat[i][j];

2. Transponer una matriz

La transpuesta intercambia filas por columnas: mat[i][j] se convierte en mat[j][i].

int transpuesta[1001][1001];
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        transpuesta[j][i] = mat[i][j];

3. Rotar 90 grados (en sentido horario)

int rotada[1001][1001];
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        rotada[j][n - 1 - i] = mat[i][j];

4. Matriz de cuadrícula (grid) como mapa

Muchos problemas representan mapas como matrices de caracteres:

5 5
.....
.###.
.#...
.###.
.....
int n, m;
cin >> n >> m;

char grid[1001][1001];
for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        cin >> grid[i][j];
    }
}

// O leer como strings
string grid2[1001];
for (int i = 0; i < n; i++) {
    cin >> grid2[i];
}
// Acceso: grid2[i][j]

5. Suma de prefijos 2D

Para responder rápidamente "¿cuál es la suma del subrectángulo de (r1,c1) a (r2,c2)?":

// Construir la tabla de prefijos
int prefix[1001][1001] = {0};
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
        prefix[i][j] = mat[i][j]
                      + prefix[i-1][j]
                      + prefix[i][j-1]
                      - prefix[i-1][j-1];
    }
}

// Consultar suma del subrectángulo (r1,c1) a (r2,c2)
int suma = prefix[r2][c2]
         - prefix[r1-1][c2]
         - prefix[r2][c1-1]
         + prefix[r1-1][c1-1];

Esto permite responder cada consulta en O(1)O(1) después de O(n×m)O(n \times m) de preprocesamiento.

Ejercicio de práctica

Lee una matriz de N×M y encuentra el valor máximo junto con su posición (fila y columna).

Entrada:

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

Salida: 12 2 3 (el máximo es 12, en fila 2, columna 3, contando desde 0)

Ver solución
#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;

    int mat[1001][1001];
    int maxVal = -1e9;
    int maxFila = 0, maxCol = 0;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> mat[i][j];
            if (mat[i][j] > maxVal) {
                maxVal = mat[i][j];
                maxFila = i;
                maxCol = j;
            }
        }
    }

    cout << maxVal << " " << maxFila << " " << maxCol << endl;

    return 0;
}

Siguiente paso

Aprende sobre Structs para crear tus propios tipos de datos combinados.