Hướng dẫn giải của Tô màu 5
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 tính số cách tô một bảng m × n bằng hai màu (đen, trắng) sao cho:
- Có đúng k ô màu đen.
- Hai ô cùng chung một cạnh không được cùng màu.
Điều kiện 2 là điều kiện của một bàn cờ vua (tô màu xen kẽ). Bất kỳ cách tô đúng điều kiện 2 đều có thể được tạo ra bằng cách chọn 1 trong 2 màu cho ô (1,1) và sau đó các ô còn lại được xác định hoàn toàn (màu của ô (i, j) sẽ bằng màu của (1,1) nếu i+j chẵn, và khác nếu i+j lẻ).
Vì vậy, có tối đa 2 cách tô thỏa mãn điều kiện 2 (tương ứng với ô (1,1) là đen hoặc trắng). Tuy nhiên, nếu t tổng số ô là số lẻ, thì hai cách tô này sẽ có số lượng ô đen khác nhau (một cách có ceil(total/2) ô đen, cách kia có floor(total/2) ô đen). Nếu tổng số ô là số chẵn, cả hai cách đều có total/2 ô đen.
Bài toán quy về kiểm tra xem k có bằng số ô đen của một trong các cách tô hợp lệ hay không.
Các cách tiếp cận
Cách Phân tích Ma trận (Grid Analysis)
#include <iostream>
using namespace std;
int main() {
long long m, n, k;
cin >> m >> n >> k;
long long total = m * n;
if (total % 2 != 0) {
// Ma trận có số ô lẻ
// Hai cách tô sẽ có số ô đen khác nhau: (total + 1) / 2 và total / 2
if (k == (total + 1) / 2 || k == total / 2) {
cout << 1;
} else {
cout << 0;
}
} else {
// Ma trận có số ô chẵn
// Cả hai cách tô đều có total / 2 ô đen
if (k == total / 2) {
cout << 2;
} else {
cout << 0;
}
}
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Cách tiếp cận này dựa trên quan sát rằng một bảng được tô màu đúng quy tắc 'không ô chung cạnh cùng màu' là một bàn cờ vua.
- Nếu tổng số ô
total = m * nlà số lẻ, thì hai cách tô tương ứng với 'ô (1,1) đen' và 'ô (1,1) trắng' sẽ cho số lượng ô đen khác nhau. Cụ thể, một cách có(total + 1) / 2ô đen, cách còn lại cótotal / 2ô đen. Do đó, nếukbằng 1 trong 2 giá trị này, đáp án là 1 (vì chỉ có 1 cách tô phù hợp với k đó). Nếu không, đáp án là 0. - Nếu
totallà số chẵn, cả hai cách tô đều có chính xáctotal / 2ô đen. Do đó, nếuk == total / 2, đáp án là 2 (cả hai cách đều hợp lệ). Nếu không, đáp án là 0. - Mã nguồn của
dvhcoderlà minh chứng cho cách này.
Cách Tính Toán Số Lượng Ô Đen Theo Kiểu Chẵn/Lẻ (Formulaic Approach)
#include <bits/stdc++.h>
using namespace std;
int main() {
long long m, n, k;
cin >> m >> n >> k;
// Tính số ô đen theo kiểu 1 (ô (1,1) là ô có số lượng nhiều hơn nếu t tổng lẻ)
// Số hàng chẵn và lẻ
long long rows_odd = (m + 1) / 2;
long long rows_even = m / 2;
// Trong một hàng, số ô có cùng màu với ô đầu tiên (tọa độ chẵn) nhiều hơn hoặc bằng
long long cols_odd = (n + 1) / 2;
long long cols_even = n / 2;
// Số ô đen kiểu 1: các ô (i, j) với i+j chẵn
long long c1 = rows_odd * cols_odd + rows_even * cols_even;
// Số ô đen kiểu 2: các ô (i, j) với i+j lẻ
// Số này bằng tổng số ô trừ đi c1
long long c2 = (m * n) - c1;
int ans = 0;
if (c1 == k) ans++;
if (c2 == k) ans++;
cout << ans;
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Cách này tính trực tiếp số ô thuộc mỗi nhóm (các ô có tổng tọa độ chẵn và lẻ).
c1là số ô (i, j) sao cho i+j là số chẵn.c2là số ô (i, j) sao cho i+j là số lẻ.c1được tính bằng cách nhân số hàng có chỉ số lẻ (vì i bắt đầu từ 1) với số cột có chỉ số lẻ, cộng với số hàng chẵn nhân số cột chẵn.c2bằngtotal - c1.- Nếu
kbằngc1, có 1 cách tô (ô (1,1) cùng màu với các ô trong nhómc1). - Nếu
kbằngc2, có 1 cách tô (ô (1,1) cùng màu với các ô trong nhómc2). - Nếu
kbằng cả hai (chỉ xảy ra khic1 == c2), đáp án là 2. - Mã nguồn của
dainghiajustiinthể hiện chính xác phương pháp này.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(1) | O(1) | Phân tích Ma trận (Grid Analysis) |
| 2 | O(1) | O(1) | Tính Toán Số Lượng Ô Đen Theo Kiểu Chẵn/Lẻ (Formulaic Approach) |
Bài học kinh nghiệm
- Bài toán này chỉ là bài toán đếm số cách tô màu trên bàn cờ vua (Checkerboard) sao cho số ô đen bằng k.
- Nếu t tổng số ô là số lẻ, hai cách tô sẽ cho số ô đen khác nhau (khác nhau 1 đơn vị). Nếu t tổng số ô chẵn, hai cách tô cho số ô đen như nhau.
- Vì các ô còn lại được xác định hoàn toàn bởi màu của ô (1,1), nên chỉ có tối đa 2 cách tô hợp lệ về mặt cấu trúc.
Lỗi thường gặp
- Sử dụng
intchom,nvàk. Vớim, nlên tới 10^9,m * ncó thể lên tới 10^18.int(32-bit) chỉ chứa được khoảng 2*10^9. Phải dùnglong long(64-bit). - Tính toán sai công thức chia đôi cho các số lẻ (ví dụ tính sai số lượng ô chẵn/lẻ trong một chiều). Phải dùng
(n + 1) / 2cho số lượng phần tử có chỉ số lẻ (từ 1) vàn / 2cho chỉ số chẵn. - Quên xử lý trường hợp
kquá lớn hoặc âm (dù đề bài cho0 <= k <= 10^18, nhưng logic phải xử lý đúng nếukkhông khớpc1hayc2).
Bình luận