VÀ MỘT VÀI BÀI TOÁN ỨNG DỤNGA Đặt vấn đề Mảng hai chiều là một cấu trúc dữ liệu rất gần gủi với những ai đã từng học lập trình, không những thế đây còn là cấu trúc quen thuộc để giải quy
Trang 1VÀ MỘT VÀI BÀI TOÁN ỨNG DỤNG
A) Đặt vấn đề
Mảng hai chiều là một cấu trúc dữ liệu rất gần gủi với những ai đã từng học lập trình, không những thế đây còn là cấu trúc quen thuộc để giải quyết khá nhiều bài toán trong các kì thi lập trình cấp tỉnh, cấp quốc gia hay khu vực Tuy là cấu trúc quen thuộc nhưng không phải học sinh nào cũng có thể sử dụng thành thạo khi gặp một bài toán có sử dụng cấu trúc này, đặc biệt hơn là khi gặp các bài toán cần xoay mảng hai chiều Để giúp các em có hướng tiếp cận với các dạng bài toán xoay mảng hai chiều và làm quen với cách truy xuất các phần tử khi
mảng được xoay 45 hay 90 độ, chúng tôi đã chọn chuyên đề PHÉP XOAY MẢNG HAI CHIỀU VÀ MỘT VÀI BÀI TOÁN ỨNG DỤNG.
B) Nội dung chính
I) Một số công thức quay ma trận
1) Quay phải 45 độ
a Bài toán:
Cho ma trận có kích thước n*m, nhiệm vụ của bạn là in ra ma trận sau khi đã xoay ma trận
ban đầu 45 độ sang phải.
3 3
b Xây dựng công thức
Để tiện cho quá trình xây dựng công thức ta gọi:
(i,j) là tọa độ của ma trận ban đầu.
Ta vẽ bảng mô tả quá trình xoay
Trang 2Hình 1.1 Ma trận ban đầu a Hình 1.2 Ma trận đã xoay b
Từ đây ta rút ra được công thức chuyển: Ô ở vị trí (i,j) của ma trận acó kích thước là n*m, sẽ chuyển thành ô có tọa độ (xp,yp) ở ma trận bcó kích thước (n+m-1)* (n+m- 1)với công thức:
(xp,yp) = (i + j – 1, n - i + j)
c Code tham khảo
Trang 3FOR(j,1,m) b[xp][yp] = a[i][j];
//Hiển thị ma trận b sau khi xoay
Cho ma trận có kích thước n*m, nhiệm vụ của bạn là in ra ma trận sau khi đã xoay ma
trận ban đầu 45 độ sang trái.
Trang 4INPUT OUTPUT
3 4
b Xây dựng công thức
Để tiện cho quá trình xây dựng công thức ta gọi:
(i,j) là tọa độ của ma trận ban đầu.
(xp,yp) là tọa độ của ma trận sau khi xoay trái 45 độ
Ta vẽ bảng mô tả quá trình xoay
Hình 2.1 Ma trận ban đầu a Ma trận đã xoay b
Từ đây ta rút ra được công thức chuyển: Ô ở vị trí (i,j) của ma trận a có kích thước là n*m, sẽ chuyển thành ô có tọa độ (xp,yp) ở ma trận b có kích thước (n+m-1)* (n+m-1)
với công thức:
(xp, yp) = (m+i-j, 1)
Trang 5i+j-c Code tham khảo
Trang 6FOR(j,1,m) b[xp][yp] = a[i][j];
Cho ma trận có kích thước n*m, nhiệm vụ của bạn là in ra ma trận sau khi đã xoay ma
trận ban đầu 90 độ sang phải.
3 4
b Xây dựng công thức
Để tiện cho quá trình xây dựng công thức ta gọi:
(i,j) là tọa độ của ma trận ban đầu.
Ta vẽ bảng mô tả quá trình xoay
Trang 7Từ đây ta rút ra được công thức chuyển: Ô ở vị trí (i,j) của ma trận a có kích thước là n*m, sẽ chuyển thành ô có tọa độ (xp,yp) ở ma trận b có kích thướcm*n với công thức:
(xp, yp) = (j, n - i + 1)
c Code tham khảo
Trang 8//Hien thi ma tran goc
Cho ma trận có kích thước n*m, nhiệm vụ của bạn là in ra ma trận sau khi đã xoay ma
trận ban đầu 90 độ sang trái.
3 4
b Xây dựng công thức
Để tiện cho quá trình xây dựng công thức ta gọi:
(i,j) là tọa độ của ma trận ban đầu.
(xp,yp) là tọa độ của ma trận sau khi xoay trái 90 độ
Ta vẽ bảng mô tả quá trình xoay
Trang 9Từ đây ta rút ra được công thức chuyển: Ô ở vị trí (i,j) của ma trận a có kích thước là n*m, sẽ chuyển thành ô có tọa độ (xp,yp) ở ma trận b có kích thước m*n với công thức:
(xp, yp) = (m-j+1, i)
c Code tham khảo
Trang 10II) Một số bài toán vận dụng
1) Chefland và khoảng cách trung bình
a Đề bài
Chefland là một lưới gồm N dòng và M cột Mỗi ô của lưới hoặc rỗng hoặc chứa một
ngôi nhà Khoảng cách giữa hai ngôi nhà là khoảng cách Manhattan giữa hai ô chứa
chúng Với mỗi d nằm giữa 1 và N + M – 2 (tính cả hai biên), Chef muốn tính số cặp ngôi nhà khác nhau có khoảng cách bằng d Hãy giúp anh ấy nhé!
Dữ liệu vào
Dòng đầu tiên của dữ liệu vào chứa một số nguyên T – số test T test được miêu
tả như sau:
Dòng đầu tiên của mỗi test chứa hai số nguyên N và M
N dòng tiếp theo Dòng thứ i (1 ≤ i ≤ N) chứa một xâu nhị phân có độ dài M, với mỗi j (1 ≤ j ≤ M), ký tự thứ j của xâu là ‘1’ nếu ô ở hàng thứ i và cột thứ j chứa một ngôi nhà hoặc ‘0’ nếu nó rỗng
Dữ liệu ra
Trang 11 Với mỗi test, in ra một dòng chứa N + M – 2 số nguyên Với mỗi i, số nguyên thứ i thể hiện số cặp có khoảng cách bằng i
Xin nhắc lại khái niệm Khoảng cách Manhattan cho những ai quan tâm:
Khoảng cách Manhattan, còn được gọi là khoảng cách trong thành phố, là một dạng khoảng cách giữa hai điểm trong không gian Euclid với hệ tọa độ Descartes Đại lượng này được tính bằng tổng chiều dài của hình chiếu của đường thẳng nối hai điểm này trong
Trang 12 Khoảng cách Manhattan có độ dài là 1 từ ô (5,4) là các ô được bôi màu:
Theo như mô tả trên , ta có thể thấy rằng, số lượng các thành phố cách thành phố (i,j) khoảng là d chính là số lượng số 1 trên hình thoi cách tâm d vị trí.
Trang 13Để tiện cho việc đếm số lượng số 1 trên hình thoi, ta tiến hành xoay 45 độ qua phải, lúc
trên cạnh hình vuông.
Với ví dụ ban đầu có thể mô hình hóa thành ma trận như sau:
Đánh giá độ phức tạp:
ta duyệt từng vị trí có thành phố trong ma trận đã xoay O((N+M)^2)
Từ đây, ta suy ra độ phức tạp của toàn bài O(d^2 * (N+M)^2)
Với ràng buộc bài toán hiện tại ta vẫn có thể giải quyết được.
Bên cạnh giải thuật trên, bài toán còn có thể tối ưu để giải quyết với ràng buộc
2<=N,M <= 300, chi tiết tham khảo: https://www.codechef.com/problems/AVGMAT
c Code tham khảo
Code tham khảo với hướng xử lý xoay ma trận
#include <bits/stdc++.h>
Trang 14#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
Trang 15FOR(i,1,n+m-1)
FOR(j,1,n+m-1) b[i][j]=0;
//xu lyFOR(i,1,n)
FOR(j,1,m){
cin >> ch;
if (ch=='1'){
a[i][j] =1;
}else{
Trang 16a[i][j] =0;
}//xoay ma tran 45 do sang phaib[xp][yp] = a[i][j];
}/*
tinh ket qua: duyet voi moi khoang cach i can tinh
ta duyet tat ca cac o de kiem tra
*/
int ans;
FOR(d,1,n+m-2){
ans =0;
FOR(i,1,n+m-1){
FOR(j,1,n+m-1){
if (b[i][j]==1){
/*
voi moi o, ta dem cac so 1 tren vien
hinh vuong tam (i,j) ban kinh d
*/
ans = ans + count1square(b,i,j,d,n+m-1);
}}
}cout << ans/2 << " ";
}}
Trang 17int n,m;
cin>>n>>m;
vector<long long> distances(m*(n+m));
vector<long long> acc(n+m);
acc[s-(n-1)+i]+=distances[j*(n+m)+s];
}}
}}
Trang 18Ông Bảo là chủ của một trang trại, đang nuôi một đàn bò trên khu đất hình chữ nhật chia thành lưới mxn ô vuông đơn vị Các hàng của lưới được đánh số từ 1 tới m từ trên xuống,
và các cột của lưới được đánh số từ 1 tới n từ trái qua phải Ô nằm trên giao điểm của hàng i và cột j được gọi là ô (i, j) Tại tâm của một số ô đã cắm cọc, mỗi cọc để buộc một con bò Để bảo vệ đàn bò tót quý của mình khỏi những tên trộm, ông Bảo thuê Hùng tìm một thửa đất có dạng hình thoi (mà theo quan niệm của ông Bảo là biểu tượng cho may mắn) trong khu đất để nhốt đàn bò của mình Thửa đất hình thoi có tâm tại ô (x0, y0) và bán kính là r là tập hợp tất cả các ô có tọa độ (x, y) thỏa mãn |x – x0| + |y – y0| <= r Do
bò tót là các con vật rất hung dữ, nên ông Bảo yêu cầu trong thửa đất tìm được không có hai ô có cọc nào lại có cạnh chung.
Yêu cầu: Giúp Hùng xác định thửa đất có dạng hình thoi nằm trọng vẹn trong khu đất
với số cọc cột bò là nhiều nhất đáp ứng yêu cầu của ông Bảo.
Kết quả: Đưa ra 4 số nguyên S, x0, y0, r được ghi cách nhau một dấu cách, trong đó: S là
tổng số cọc trong thửa đất được chọn; x0, y0 là tọa độ tâm và r là bán kính của thửa đất
đó Nếu có nhiều lời giải hãy đưa ra một lời giải bất kỳ.
Trang 19
*.*
Ràng buộc:
- Có 40% số test ứng với 40% số điểm của bài có 1 <= m,n <= 100
- Có 40% số test khác ứng với 40% số điểm của bài có 1 <= m,n <= 500
- Có 20% số test còn lại ứng với 20% số điểm của bài có 1 <= m,n <= 1000
b Hướng dẫn giải
Việc đầu tiên ta phải xoay bảng 1 góc 45 độ thì mới có thể tính tổng trong 1 hình thoi (khi
đó đã chuyển thành hình vuông) được
Ô (u, v) ⇒ (u+v-1, n-u+v) (nháp sẽ có công thức này) : xoay giấy sang phải 45 độ
4 mảng F1(i, j), F2(i, j), F3(i, j), F4(i, j) là bán kính lớn nhất thỏa mãn về 4 phía, tức là tam giác vuông về 4 phía thỏa mãn ko có 2 ô cạnh nhau nào cùng có cọc
Xem chi tiết cách tính 4 mảng F bằng QHĐ trong code.
Sau khi đã tính mảng F, ta duyệt hết n*m ô vuông, coi ô đang duyệt (i, j) là tâm hình thoi
⇒ bán kính hình thoi bằng min 4 mảng F(i, j)
Ta sử dụng mảng tổng đã tính trước để tính tổng khi có hình thoi tâm i, j bán kính r và update kết quả
c Code tham khảo
Trang 20int calc(int u, int v, int r)
s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + b[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
Trang 21if (a[i][j] && (a[i-1][j] || a[i][j-1])) F1[i][j] = 1;
else F1[i][j] = min(F1[i-1][j], F1[i][j-1]) + 1;
for (int i = 1; i <= n; i++)
for (int j = m; j >= 1; j )
if (a[i][j] && (a[i][j+1] || a[i-1][j])) F2[i][j] = 1;
else F2[i][j] = min(F2[i-1][j], F2[i][j+1]) + 1;
for (int i = n; i >= 1; i )
for (int j = 1; j <= m; j++)
if (a[i][j] && (a[i][j-1] || a[i+1][j])) F3[i][j] = 1;
else F3[i][j] = min(F3[i+1][j], F3[i][j-1]) + 1;
for (int i = n; i >= 1; i )
for (int j = m; j >= 1; j )
if (a[i][j] && (a[i][j+1] || a[i+1][j])) F4[i][j] = 1;
else F4[i][j] = min(F4[i+1][j], F4[i][j+1]) + 1;
for (int i = 1; i <= n; i++)
Trang 22a Đề bài:
Hôm nay là một ngày hè nóng nực nên cô bò Bessie có cảm giác lười biếng Cô ta muốn đặt mình vào một vị trí trên cánh đồng của cô ta để có thể vươn tới được nhiều đám cỏ ngon nhất có thể chỉ với một quãng đường ngắn.
Cánh đồng của Bessie có kích thước NxN (1 <= N <= 400) Tại dòng r, cột c của cánh đồng chứa G(r,c) đơn vị cỏ Bessie muốn chọn một điểm trên cánh đồng làm vị trí ban đầu của cô ta sao cho số lượng cỏ mà cô ta có thể đi tới trong vòng K bước là lớn nhất.
Khi Bessie đi một bước, cô ta sẽ di chuyển một đơn vị độ dài về hướng đông, tây, nam, hoặc bắc ở vị trí hiện tại của cô ta
Hãy giúp cô bò Bessie tính toán số lượng đơn vị cỏ lớn nhất mà cô ta có thể đi tới nếu cô
Trang 23Hướng tiếp cận 1: Ta duyệt tất cả các ô (r,c) có thể đặt Bessie, tính tổng các đám cỏ
Hướng tiếp cận 2: Ta tính sẵnlượng cỏ có hình thoi như hình vẽ, mỗi điểm ta trượt hình
thoi đến vị trí tiếp theo, tính lại lượng cỏ có thể ăn được ở vị trí tiếp theo Ở đây, chi phí
để tính không còn là K^2 nữa mà ta sử dụng kĩ thuật bổ sung các ô mới đến được và loại
bỏ các ô củ không đến được Với hướng tiếp cận này ta có khả năng sẽ giải quyết được bài toán với ràng buộc như trên.
Tuy nhiên để việc trượt hình thoi dễ dàng, ta thay vì trượt hình thoi, ta xoay ma trận ban đầu 45 độ sang phải, sau đó việc trượt hình thoi sẽ thành trượt hình vuông có kích thước
Trang 24int main()
{
ifstream fin("lazy.in");
fin >> n >> k;
// rotate the matrix 45 degrees
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
fin >> mat[i+j][n-i+j-1];
fin.close();
// 45 degree rotation expands the size of the matrix
// it also includes the cells with half distance
int t=(n+1)%2; // t is used to avoid non-lattice points
for (int a=max(i-k,0); a<n && a<=i+k; a++)
for (int b=max(t-k,0); b<n && b<=t+k; b++)
sum+=mat[a][b];
if (best<sum) best=sum;
// slide the regionfor (int j=t+1; j+k<n; j++){
for (int a=max(i-k,0); a<n && a<=i+k; a++){
if (j-k-1>=0) sum-=mat[a][j-k-1];
sum+=mat[a][j+k];
}// update the sum only in lattice points
if (j%2==t && best<sum) best=sum;
}}
ofstream fout("lazy.out");
fout << best << endl;
Trang 25Ưu điểm:
Chuyên đề giúp các em làm quen với xác định các phần tử trên mảng hai chiều khi xoay mảng, thông qua đó các em hình thành dần kĩ năng thao tác trên mảng hai chiều để vận dụng vào các kì thi có sự dụng mảng hai chiều một cách hiệu quả.
Nhược điểm:
Bài tập vận dụng vẫn chưa nhiều để thấy rõ được ý nghĩa của chuyên đề Bên cạnh đó, đây chỉ là một kĩ thuật nhỏ để giải quyết bài toán, trong bài tập thực tế cần kết hợp nhiều
kĩ thuật và kĩ năng khác để giải quyết bài toán một cách triệt để.
D) TÀI LIỆU THAM KHẢO
1 https://www.codechef.com/problems/AVGMAT
2 http://vnoi.info/problems/RBULL/
3 http://usaco.org/index.php?page=viewproblem2&cpid=416
Trang 26MỤC LỤC
A) Đặt vấn đề 1
B) Nội dung chính 1
I) Một số công thức quay ma trận 1
1) Quay phải 45 độ 1
a Bài toán: 1
b Xây dựng công thức 1
c Code tham khảo 2
2) Quay trái 45 độ 3
a Bài toán: 3
b Xây dựng công thức 4
c Code tham khảo 5
3) Quay phải 90 độ 6
a Bài toán: 6
b Xây dựng công thức 6
c Code tham khảo 7
4) Quay trái 90 độ 8
a Bài toán: 8
b Xây dựng công thức 8
c Code tham khảo 9
II) Một số bài toán vận dụng 10
1) Chefland và khoảng cách trung bình 10
a Đề bài 10
b Hướng dẫn giải 11
c Code tham khảo 14
2) RBULL - VOI 2016 - Trại bò tót ( http://vnoi.info/problems/RBULL/ ) 18
a Đề bài 18
b Hướng dẫn giải 20
c Code tham khảo 20
3) The Lazy Cow 22
a Đề bài: 22
b Hướng dẫn giải 24
Trang 27c Code tham khảo 24 C) Kết luận 26 D) TÀI LIỆU THAM KHẢO 26