Bỏ qua
Tuần 6

Mảng 2 chiều

Độ khó
★★★☆☆ Vừa
Thời lượng
Khoảng 90 phút
Học trước
Mảng 1 chiều, Vector
Chủ đề
ma trậnmảng 2 chiều
Trạng thái

Kiến thức cơ bản

Mảng 2 chiều

Mảng 2 chiều (2D array), còn gọi là ma trận (matrix), là một bảng số gồm nhiều dòng và nhiều cột. Mỗi ô trong bảng được gọi bằng hai chỉ số: dòng i và cột j, viết là a[i][j]. Như mảng 1 chiều các chỉ chỉ số dòng và cột trong C++ đều bắt đầu từ 0.

Ví dụ một bảng có n = 3 dòng và m = 4 cột:

Cột 0Cột 1Cột 2Cột 3
Dòng 0a[0][0]a[0][1]a[0][2]a[0][3]
Dòng 1a[1][0]a[1][1]a[1][2]a[1][3]
Dòng 2a[2][0]a[2][1]a[2][2]a[2][3]

Ô tô vàng ở dòng 1, cột 2 nên được viết là a[1][2] với quy tắc dòng trước, cột sau. Bảng trên có 12 ô chỉ số dòng từ 0 đến n-1 = 2, chỉ số cột từ 0 đến m-1 = 3.

Nếu mảng 1 chiều có một hàng và nhiều cột thì mảng 2 chiều chính là một mảng các mảng 1 chiều.

Đứng tại ô (i, j), một nhân vật trong game muốn bước sang 4 ô hàng xóm liền kề (Lên, Xuống, Trái, Phải) thì tọa độ thay đổi như sau:

  • Đi lên (Up): Hàng giảm 1, cột giữ nguyên (i - 1, j).
  • Đi xuống (Down): Hàng tăng 1, cột giữ nguyên (i + 1, j).
  • Sang trái (Left): Hàng giữ nguyên, cột giảm 1 (i, j - 1).
  • Sang phải (Right): Hàng giữ nguyên, cột tăng 1 (i, j + 1).

Khai báo, nhập xuất mảng 2 chiều

Để khai báo mảng, ta dùng một số cú pháp sau:

int a[100][100]; // mảng a tối đa 100 dòng, 100 cột
// mảng b có n dòng, m cột, mọi ô ban đầu là 0
vector<vector<int>> b(n, vector<int>(m));
// mảng c có n dòng, m cột, mọi ô khởi tạo là 5
vector<vector<int>> c(n, vector<int>(m, 5));

Để nhập mảng, ta đọc lần lượt từng ô, từ trái sang phải, từ trên xuống dưới:

for (int i = 0; i < n; ++i)      // vòng ngoài: từng dòng i
    for (int j = 0; j < m; ++j)  // vòng trong: từng cột j của dòng i
        cin >> a[i][j];

Ví dụ in mảng, hết một dòng thì xuống dòng:

for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j)
        cout << a[i][j] << " ";
    cout << endl; // xuống dòng sau khi in xong dòng i
}

Đôi khi ta cần duyệt theo cột, khi đó chỉ cần đổi vai hai vòng lặp: vòng ngoài là cột j, vòng trong là dòng i.

Mảng vuông

Khi mảng có số dòng bằng số cột (n × n) ta gọi là mảng vuông. Mảng vuông có hai đường chéo:

  • Đường chéo chính: đi từ góc trên trái xuống góc dưới phải, gồm các ô có chỉ số dòng bằng cột (i == j). Các ô nằm trên đường chéo chính có j > i, các ô nằm dưới đường chéo chính có j < i.
  • Đường chéo phụ: đi từ góc trên phải xuống góc dưới trái, tổng chỉ số của dòng + cột = n - 1 (i + j == n - 1).

Luyện tập

Bài 1. Bảng điểm của lớp

Lớp 6A0 có n bạn, mỗi bạn làm m bài kiểm tra. Cô giáo ghi điểm vào một bảng gồm n dòng, m cột (mỗi dòng là điểm của một bạn). Bạn giúp hãy giúp cô:

  • Tính tổng điểm của từng bạn.
  • Với mỗi bài kiểm tra, điểm của cả lớp là bao nhiêu
Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 100)
n dòng tiếp theo, mỗi dòng gồm m số nguyên (0 ≤ điểm ≤ 10)
Đầu ran dòng, dòng thứ i là tổng điểm của bạn ở dòng thứ i (i tính từ 0).
Dòng thứ n+1: tổng điểm của m bài kiểm tra, cách nhau dấu cách.
TestInputOutput
3 4
8 9 7 10
6 5 8 7
9 9 9 9
34
26
36
23 23 24 26

Bài 2. Bức tường thành vững chãi

Một lâu đài cổ hình chữ nhật có kích thước n.m. Nhà vua muốn xây dựng lại toàn bộ bức tường bao quanh lâu đài (chính là tất cả các ô nằm ở rìa ngoài cùng). Hãy tính tổng chi phí gia cố bức tường bao này!

Đầu vàoDòng 1: hai số nguyên n, m (2 ≤ n, m ≤ 1000)
n dòng tiếp theo, mỗi dòng gồm m số nguyên (0 ≤ a[i][j] ≤ 104)
Đầu raMột số nguyên duy nhất là tổng giá trị các ô nằm trên viền ma trận
TestInputOutput
3 4
1 2 3 4
5 1 2 6
7 8 9 0
40

Bài 3. Hai đường chéo của bàn cờ

Cho một bảng vuông n.n. Đường chéo chính đi từ góc trên bên trái xuống góc dưới bên phải. Đường chéo phụ đi từ góc trên bên phải xuống góc dưới bên trái. Hãy tính tổng các số trên mỗi đường chéo.

Đầu vàoDòng 1: số nguyên n (1 ≤ n ≤ 100).
n dòng tiếp theo, mỗi dòng gồm n số nguyên (|a[i][j]| ≤ 1000).
Đầu raTổng đường chéo chính và đường chéo phụ, cách nhau dấu cách
TestInputOutput
3
1 2 3
4 5 6
7 8 10
16 15

Bài 4. Số lớn nhất, nhỏ nhất

Hãy tìm số nhỏ nhất và số lớn nhất trong ma trận n.m, sau đó liệt kê các vị trí xuất hiện của các phần tử này trong ma trận.

Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 100).
n dòng tiếp theo, mỗi dòng gồm m số nguyên (|a[i][j]| ≤ 109).
Đầu raDòng đầu tiên in ra số nhỏ nhất trong ma trận, các dòng tiếp theo liệt kê các vị trí của số này trong ma trận.
Dòng tiếp theo in ra số lớn nhất trong ma trận, các dòng tiếp theo liệt kê các chỉ số của số này trong ma trận.
TestInputOutput
3 3
1 2 1
4 5 6
7 8 9
1
0 0
0 2
9
2 2

Bài 5. Chiếc kính lúp dò bạn thân

Cho một bàn cờ n.m gồm các số nguyên. Bạn hãy đếm xem trong 4 ô lân cận (trên, dưới, trái, phải) của ô (r, c) có bao nhiêu ô có giá trị lớn hơn giá trị tại ô này.

Đầu vàoDòng 1: hai số nguyên n, m, r, c (1 ≤ n, m ≤ 500; 0 ≤ r < n; 0 ≤ c < m).
n dòng tiếp theo, mỗi dòng gồm m số nguyên (|a[i][j]| ≤ 109).
Đầu raIn ra số lượng ô lân cận có giá trị lớn hơn ô a[r][c].
TestInputOutput
3 3 1 1
1 8 3
4 5 6
2 7 9
3

Hướng dẫn: thay vì viết 4 câu lệnh if dài dòng, dân Lập trình thi đấu dùng Bộ mảng biến hình:

// Thứ tự: Lên, Xuống, Trái, Phải
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

// Duyệt 4 hàng xóm chỉ bằng 1 vòng lặp duy nhất:
for (int k = 0; k < 4; ++k) {
    int u = i + dx[k]; // Tọa độ hàng mới
    int v = j + dy[k]; // Tọa độ cột mới

    // Kiểm tra xem có bị "ngã khỏi mép bản đồ" không!
    if (u >= 0 && u < n && v >= 0 && v < m) {
        // xử lý ô (u, v) là hàng xóm hợp lệ
    }
}

Bài 6. Kho báu lớn nhất

Bản đồ kho báu là một bảng n dòng, m cột, mỗi ô ghi số lượng vàng. Hãy tìm ô có nhiều vàng nhất. Nếu có nhiều ô cùng nhiều nhất, chọn ô gặp đầu tiên khi đọc từ trên xuống dưới, mỗi dòng đọc từ trái sang phải.

Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 100).
n dòng tiếp theo, mỗi dòng gồm m số nguyên (0 ≤ số vàng ≤ 1000).
Đầu raBa số cách nhau bởi dấu cách: số vàng lớn nhất, chỉ số dòng và chỉ số cột của ô đó (tính từ 0).
TestInputOutput
3 4
5 2 9 1
7 9 3 4
6 8 2 0
9 0 2

Bài 7. Xoay bảng điểm

Cô giáo muốn đổi bảng điểm: dòng thứ i của bảng cũ sẽ trở thành cột thứ i của bảng mới. Bạn hãy in ra bảng mới nhé! (Phép biến đổi này gọi là chuyển vị)

Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 100).
n dòng tiếp theo, mỗi dòng gồm m số nguyên (|a[i][j]| ≤ 1000).
Đầu ram dòng, mỗi dòng gồm n số cách nhau bởi dấu cách: bảng sau khi chuyển vị
TestInputOutput
2 3
1 2 3
4 5 6
1 4
2 5
3 6

Bài 8. Snake

Hãy in các phần tử thuộc ma trận vuông n.n theo hình con rắn. Với chỉ số hàng tính từ 0, hàng chẵn in từ trái qua phải, hàng lẻ in từ phải qua trái.

Hình minh họa

Đầu vàoDòng 1: số nguyên dương n (1 ≤ n ≤ 100). n dòng tiếp mỗi dòng gồm n số nguyên |a[i][j]| ≤ 109.
Đầu raIn ra ma trận theo yêu cầu.
TestInputOutput
3
1 2 3
4 5 6
7 8 9
1 2 3
6 5 4
7 8 9

Bài tập tự luyện

Bài 1. Bàn cờ X và O

Hãy vẽ một bàn cờ gồm n dòng, m cột bằng hai ký tự X và O. Ô ở góc trên bên trái là X, hai ô kề nhau (trên, dưới, trái, phải) luôn khác ký tự.

Đầu vàoMột dòng gồm hai số nguyên n, m (1 ≤ n, m ≤ 100)
Đầu ran dòng, mỗi dòng gồm m ký tự X hoặc O, không có dấu cách
TestInputOutput
3 4XOXO
OXOX
XOXO

Bài 2. Hoán vị hàng, cột

Hãy hoán vị các phần tử trên 2 hàng, 2 cột của ma trận vuông kích thước n.n.

Đầu vàoDòng 1: số nguyên n (1 ≤ n ≤ 200).
n dòng tiếp theo, mỗi dòng gồm n số nguyên (|a[i]| ≤ 109).
Dòng tiếp theo là 2 chỉ số u, v (tính từ 0) cần hoán vị.
Đầu raIn ra ma trận sau khi hoán vị 2 hàng u, v
Cách một dòng, in ra ma trận sau khi hoán vị 2 cột u, v
TestInputOutput
3
1 2 3
4 5 6
7 8 9
0 2
7 8 9
4 5 6
1 2 3
3 2 1
6 5 4
9 8 7

Bài 3. Hình vuông kỳ diệu

Một bảng vuông n.n được gọi là kỳ diệu nếu tổng của mọi dòng, tổng của mọi cột, tổng đường chéo chính và tổng đường chéo phụ đều bằng nhau. Hãy kiểm tra xem bảng cho trước có kỳ diệu không.

Đầu vàoDòng 1: số nguyên n (1 ≤ n ≤ 100).
n dòng tiếp theo, mỗi dòng gồm n số nguyên (|a[i][j]| ≤ 1000).
Đầu raIn YES nếu bảng kỳ diệu, ngược lại in NO
TestInputOutput
3
2 7 6
9 5 1
4 3 8
YES
3
1 2 3
4 5 6
7 8 9
NO

Bài 4. Bảng số đối xứng

Một bảng vuông gọi là đối xứng nếu đặt một chiếc gương dọc theo đường chéo chính thì hình phản chiếu trùng khít với bảng gốc. Hãy kiểm tra bảng cho trước.

Đầu vàoDòng 1: số nguyên n (1 ≤ n ≤ 100).
n dòng tiếp theo, mỗi dòng gồm n số nguyên (|a[i][j]| ≤ 1000).
Đầu raIn YES nếu bảng đối xứng, ngược lại in NO
TestInputOutput
3
1 2 3
2 5 6
3 6 9
YES
3
1 2 3
4 5 6
7 8 9
NO

Hướng dẫn: bảng đối xứng tức là a[i][j] = a[j][i] với mọi ô.

Bài 5. Tam giác Pascal

Tam giác Pascal có dòng 0 chỉ gồm số 1. Mỗi dòng bắt đầu và kết thúc bằng số 1, còn các số ở giữa bằng tổng của hai số đứng ngay phía trên nó (trên-trái và trên-phải). Hãy in n dòng đầu tiên của tam giác.

Đầu vàoMột số nguyên n (1 ≤ n ≤ 20).
Đầu ran dòng, dòng thứ i (tính từ 0) có i + 1 số cách nhau bởi dấu cách.
TestInputOutput
51
1 1
1 2 1
1 3 3 1
1 4 6 4 1

Bài 6. Đỉnh núi

Một vùng núi được vẽ thành bảng n dòng, m cột, mỗi ô ghi độ cao. Một ô được gọi là đỉnh núi nếu độ cao của nó lớn hơn độ cao của tất cả các ô kề bên (trên, dưới, trái, phải). Ô nằm ở mép bảng chỉ so sánh với những ô kề bên có trong bảng. Hãy đếm số đỉnh núi.

Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 1000)
n dòng tiếp theo, mỗi dòng gồm m số nguyên (0 ≤ độ cao ≤ 109)
Đầu raSố lượng đỉnh núi
TestInputOutput
3 4
1 2 1 3
2 5 2 1
1 2 1 4
3

Bài 7. Game Dò Mìn

Bản đồ mìn kích thước n.m gồm các ký tự: ký tự * đại diện cho quả mìn, ký tự . đại diện cho ô an toàn. Hãy tạo ra bảng số cho trò chơi: thay thế mỗi ô an toàn . bằng một chữ số biểu thị số lượng quả mìn nằm trong 8 ô bao quanh nó, các ô có mìn * giữ nguyên.

Đầu vàoDòng 1: hai số nguyên n, m (1 ≤ n, m ≤ 100)
n dòng tiếp theo, mỗi dòng gồm m kí tự * hoặc .
Đầu raIn ra bảng kích thước n.m sau khi tính toán
TestInputOutput
3 3
* . .
. . .
. . *
* 1 0
1 2 1
0 1 *

Bài 8. Ma trận xoắn ốc

Xây dựng ma trận xoắn ốc cấp n.

Hình minh họa

Đầu vàoSố nguyên dương n (1 ≤ n ≤ 100) là cấp của ma trận xoáy ốc.
Đầu raIn ra ma trận xoáy ốc cấp n.
TestInputOutput
31 2 3
8 9 4
7 6 5

Bài liên quan