Hướng dẫn giải của Kính phóng đại
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Bài toán yêu cầu phóng đại một văn bản dưới dạng ma trận ký tự. Với mỗi ký tự trong ma trận ban đầu (kích thước R x C), ta cần thay thế nó bằng một ma trận con nhỏ hơn (kích thước ZR x ZC) chứa toàn ký tự đó. Đầu ra sẽ là ma trận mới có kích thước (RZR) x (CZC). Ví dụ, với ZR=2, ZC=2, mỗi ký tự 'x' sẽ thành một khối 2x2 toàn 'x'.
Các cách tiếp cận
Cách Lồng vòng lặp
#include <iostream>
using namespace std;
int main() {
int r,c,zr,zc;
cin>>r>>c>>zr>>zc;
char a[r][c];
for (int i=0;i<r;i++) {
for (int j=0;j<c;j++) {
cin>>a[i][j];
}
}
for (int i=0;i<r;i++) {
for (int k=0;k<zr;k++){
for (int j=0;j<c;j++) {
for (int b=0;b<zc;b++) cout<<a[i][j];
}
cout<<"\n";
}
}
}
- Time Complexity: O(R * C * ZR * ZC)
- Space Complexity: O(R * C)
Phương pháp này sử dụng 4 vòng lặp lồng nhau. Vòng lặp ngoài cùng (i) duyệt qua từng hàng của ma trận gốc. Vòng lặp thứ hai (k) lặp ZR lần để in ra ZR hàng cho mỗi hàng gốc. Bên trong, vòng lặp thứ ba (j) duyệt qua từng cột của hàng gốc, và vòng lặp thứ tư (b) in ra ký tự hiện tại ZC lần. Mỗi ký tự gốc được xử lý bằng cách in nó ZC lần, và mỗi hàng gốc được in lại ZR lần.
Cách Xử lý chuỗi
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int R, C, ZR, ZC;
cin >> R >> C >> ZR >> ZC;
vector<string> a(R);
for (int i = 0; i < R; i++) cin >> a[i];
for (int i = 0; i < R; i++) {
string row = "";
for (int j = 0; j < C; j++) {
row += string(ZC, a[i][j]);
}
for (int k = 0; k < ZR; k++) cout << row << "\n";
}
return 0;
}
- Time Complexity: O(R * C * ZR * ZC)
- Space Complexity: O(R * C)
Tiếp cận này tập trung vào việc xây dựng từng hàng của đầu ra trước. Với mỗi hàng của ma trận gốc, ta tạo một chuỗi mới bằng cách lặp qua từng ký tự và nối nó ZC lần vào chuỗi đó. Sau đó, ta chỉ cần in chuỗi đã tạo này ZR lần. Cách này đơn giản hóa logic bằng cách thao tác trực tiếp với chuỗi thay vì in từng ký tự.
Cách Hàm tái sử dụng
#include <bits/stdc++.h>
using namespace std;
string zoom_colume(string s,int zc){
string ans = "";
for (char c:s) ans += string(zc,c);
return ans;
}
string zoom_row(string s, int zr){
string ans = "";
while (zr--){
ans += s + "\n";
}
return ans;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int r,c,zr,zc;
cin >> r >> c >> zr >> zc;
string s;
cin.ignore();
for (int i = 0;i < r;i++){
getline(cin,s);
cout << zoom_row(zoom_colume(s,zc),zr);
}
return 0;
}
- Time Complexity: O(R * C * ZR * ZC)
- Space Complexity: O(R * C)
Đây là biến thể của phương pháp chuỗi, nhưng logic được chia thành các hàm riêng biệt: zoom_colume để phóng đại theo chiều ngang (mỗi ký tự thành ZC ký tự) và zoom_row để phóng đại theo chiều dọc (mỗi hàng thành ZR hàng). Điều này giúp mã nguồn dễ đọc và dễ bảo trì hơn. Tuy nhiên, nó vẫn thực hiện cùng một khối lượng công việc.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(R * C * ZR * ZC) | O(R * C) | Lồng vòng lặp |
| 2 | O(R * C * ZR * ZC) | O(R * C) | Xử lý chuỗi |
| 3 | O(R * C * ZR * ZC) | O(R * C) | Hàm tái sử dụng |
Bài học kinh nghiệm
- Bài toán có thể được chia thành hai giai đoạn độc lập: phóng đại theo chiều ngang (ZC) và chiều dọc (ZR).
- Sử dụng chuỗi string giúp đơn giản hóa việc in ra nhiều ký tự giống nhau liên tiếp.
- Vì kích thước đầu vào nhỏ (R, C <= 50; ZR, ZC <= 5), mọi phương pháp đều chạy rất nhanh và phức tạp thời gian không phải là vấn đề lớn.
Lỗi thường gặp
- Quên in ký tự newline '\n' ở cuối mỗi hàng đầu ra.
- Lỗi thứ tự lặp: phải xử lý phóng đại theo chiều ngang trước (tạo chuỗi hàng) rồi mới đến chiều dọc (in lại hàng đó nhiều lần).
- Nếu dùng mảng tĩnh
char a[55][55], cần đảm bảo kích thước đủ để tránh tràn bộ nhớ.
Bình luận