Bài toán xếp gạch chữ L nổi tiếng
Trang 1Mô típ các bài toán phủ gạch chữ L
Công Hiệp
Các bài toán loại lát nền bằng những viên gạch thước thợ khá quen thuộc đối với mỗi chúng ta Nó từng được nhắc tới khá nhiều trong tạp chí và trong các kỳ thi HSG Cùng với một số bài mang tính tham khảo thêm, tôi muốn cùng các bạn tổ hợp lại những bài tập tin nhưng mang đậm tính suy luận toán học này.
Trước hết, hãy xét bài toán cơ sở:
I Bài toán 1: Hãy phủ kín một nền nhà hình chữ nhật kích thước M*N (M, N ≥ 3) bằng
những viên gạch thước thợ (hình chữ L, chiếm 3 ô vuông đơn vị) hoặc thông báo là không thể làm được điều đó
Dữ liệu: Đọc từ màn hình kích thước M N
Kết quả: Xuất ra file PHUCHU_L.OUT -1 nếu không tồn tại cách phủ, ngược lại in ra
ma trận số biểu hiện cách phủ, trong đó cứ 3 số giống nhau tạo miền liên thông hình chữ
L thể hiện một viên gạch
Ví dụ: M = 3 và N = 4
Cơ sở thuật toán: Dễ thấy rằng nếu cả hai chỉ số kích thước của bảng M, N đều không
chia hết cho 3 thì bài toán vô nghiệm, bởi khi đó M*N không chia hết cho 3 trong khi đó,
số ô mà các viên gạch phủ được lại luôn chia hết cho 3 Trong các trường hợp ngựơc lại, không mất tính tổng quát ta giả sử M (số dòng) chia hết cho 3 (nếu N chia hết cho 3 thì ta lại đảo cạnh) Ta tách hai trường hợp:
Nếu N là số chẵn, đặt N = 2k Ta hoàn toàn có thể làm tương tự như trường hợp 3*4 ở trên, 2 viên gạch đặt chồng lên nhau sẽ phủ kín hình chữ nhật 3*2 -> ghép những viên gạch này ta sẽ có được hình chữ nhật kích thước M*N tuỳ ý (với M = 3q và N = 2k) Trong trường hợp N là số lẻ, dễ thấy N -3 là số chẵn => ta đã phủ được hình chữ nhật M
* (N-3) như cách làm trên Vấn đề còn lại là phủ nốt hình chữ nhật kích thước M*3 (3 cột cuối cùng) Dễ thấy nếu M chia hết cho 2 thì ta lại quay chỉ số 3 làm dòng và M là số cột,
ta sẽ phủ nốt hình chữ nhật kích thước 3*M này => bài toán có nghiệm, trong trường hợp ngược lại (M lẻ), bài toán vô nghiệm
Ví dụ: M = 6, N = 5
Trang 2Chương trình cài đặt như sau:
Uses crt;
Const
fo = ′phuchu_l.out ′;
Var
a : array [1 150, 1 150] of integer;
m, n, sl : integer;
f : text;
Procedure Init;
Begin
clrscr;
write( ′Nhap kich thuoc m, n : ′); readln(m, n);
End;
Procedure error;
Begin
write( ′KHONG THE XEP DUOC! ′); readln;
halt;
End;
Procedure Check;
Begin
if m * n mod 3 <> 0 then error;
sl := 0;
End;
Procedure xep3(m, n : integer); Var
sl1, i : integer;
Begin
if m mod 2 <> 0 then error;
sl1 := sl;
for i := 1 to m do
begin
if i mod 2 = 1 then inc(sl, 2);
a[i, n - 2] := sl;
a[i, n] := sl + 1;
if i mod 2 = 1 then a[i, n - 1] := sl + 1 else a[i, n - 1] := sl;
end;
Trang 3Procedure xep(m, n : integer);
Var
c, i, sl1 : integer;
Begin
c := 1;
while (c < n)and(c<>n - 2) do
begin
sl1 := sl;
for i := 1 to m do
begin
if i mod 3 = 1 then inc(sl);
if i mod 3 = 0 then inc(sl);
a[i, c] := sl;
end;
inc(c); sl := sl1;
for i := 1 to m do
begin
if i mod 3 = 1 then inc(sl);
if i mod 3 = 2 then inc(sl);
a[i, c] := sl;
end;
inc(c);
end;
if c = n - 2 then xep3(m, n); {xet rieng 3 cot cuoi} End;
Procedure Print;
Var
i, j, k : integer;
Begin
assign(f, fo);rewrite(f);
if m mod 3 = 0 then
for i := 1 to m do
begin
for j := 1 to n do
begin
textbackground((a[i, j] mod 7));
if (m <= 15) and (n <= 15) then write(a[i, j] : 4); write(f, a[i, j] : 5);
textbackground(black);
end;
writeln; writeln(f);
end
else
for j := 1 to m do
begin
Trang 4for i := 1 to n do
begin
textbackground((a[i, j] mod 7));
if (m <= 15) and (n <= 15) then write(a[i, j] : 4);
write(f, a[i, j] : 5);
textbackground(black);
end;
writeln;writeln(f);
end;
close(f);
writeln( ′Moi mo tep phuchu_l.out xem ′);
readln
End;
Begin
Init;
check;
if m mod 3 = 0 then xep(m, n)
else xep(n, m);
Print;
End.
II Bài toán 2:
Hãy phủ một nền nhà hình vuông kích 2N * 2N (N ≤ 7) bằng những viên gạch thước thợ sao cho còn lại đúng một ô tại vị trí (x, y) cho trước (lỗ thoát nước)
Dữ liệu: Đọc từ màn hình N
Kết quả: Xuất ra file LATCHU_L.OUT -1 nếu không tồn tại cách phủ, ngược lại in ra
ma trận số biểu hiện cách phủ, trong đó cứ 3 số giống nhau tạo miền liên thông hình chữ
L thể hiện một viên gạch Dấu X thể hiện lỗ thoát nước
Ví dụ: N = 2, X = 2, Y = 2 ta có vídụ về một cách xếp thoả mãn như sau:
Trước hết ta khẳng định bài toán luôn có nghiệm, để chứng minh ta dùng công cụ rất mạnh từ toán, nếu như chúng ta chứng minh được tính đúng đắn luôn có nghiệm của bài toán thì cũng là chúng ta đã giải quyết được 80%, vấn đề còn lại chỉ là 20% lập trình Thật vậy, ta chứng minh bài toán bằng phương pháp qui nạp, từ đó các bạn sẽ thấy việc cài đặt là rất đơn giản:
Với N = 1, hình vuông kích thước 2*2, khi đó ta luôn lát được bởi chỉ có thể là 1 trong 4 trường hợp sau:
Trang 5Giả sử ta đã chứng minh bài toán đúng với N = K (K> 1), vấn đề còn lại là bài toán phải đúng với N = K+1 Với hình vuông 2K+1 * 2K+1 ta hãy chia thành 4 hình vuông con kích thước 2K * 2K, đánh số từ 1 đến 4 Không mất tính tổng quát, giả sử lỗ thoát nước ở hình vuông I, khi đó hình vuông I bị mất một ô và theo giả sử N đúng tới K thì hình vuông này
có cách phủ kín Đối với 3 hình vuông còn lại, vấn đề làm cho chúng cùng mất đi một hình vuông đơn vị là rất đơn giản, ta hãy lát một viên gạch vào chính giữa sao cho, 3 ô của nó nằm trên 3 hình vuông còn lại này → các hình vuông kích thước 2K * 2K đều được phủ kín ↔hình vuông 2k+1 * 2K+1 cũng được phủ kín , minh hoạ như sau:
Như vậy ta đã chứng minh bài toán đúng đắn với mọi N Việc cài đặt bài toán này chúng
ta có thể dùng phép đệ qui (chú ý rằng N ≤ 7 nên phương pháp đệ qui hoàn toàn khả thi)
Do đệ qui không có quay lui nên thời gian chạy chương trình là không đáng kể
III Bài toán 3:
Tôi xin được mở rộng tiếp bài toán lát nền mà trong số báo vui xuân Tân Tỵ, PGS-TS Nguyễn Xuân Huy đã đề cập tới Bài toán được phát biểu lại như sau: Cần phải lát kín một nền nhà kích thước N*N với N = 2K bằng những viên gạch thước thợ Sao cho: Nền nhà còn thừa đúng một ô tại vị trí (x, y) Hai viện gạch chung cạnh phải khác màu
nhau Số màu phải dùng là ít nhất Dữ liệu: Trong file văn bản LATNEN.INP gồm một
dòng duy nhất chứa 3 số tự nhiên N, X, Y (N ≤ 128)
Kết quả: Ra file văn bản LATNEN.OUT gồm
Dòng đầu là số màu ít nhất cần dùng Tiếp đó là một phương án lát nền tìm được trong đó
cứ mỗi viên gạch được biểu diễn bởi 3 số giống nhau tạo hình viên gạch và hiển thị mầu của viên gạch đó (ví dụ) Ô có toạ độ (x, y) ghi chữ ′X ′ thể hiện lỗ thoát nước
Nhận xét: với N = 2 thì cần 1 mầu còn với mọi N > 2 ta cần tối đa 3 mầu (xem thêm số
báo xuân Tân Tỵ để biết thêm chi tiết phần lập luận)
Cách giải: Khởi tạo, ta hãy khởi tạo giá trị cho một hình vuông 2*2, ba hình vuông bên
trong nhận giá trị 1, hình vuông trên phải nhận giá trị 2 sau đó ta sẽ thực hiện các phép biến hình sau:
Trang 6Tịnh tiến A theo đường chéo để thu được B Lật A sang phải để thu được hình C (chú ý việc lấy phần bù có nghĩa là hoán đổi 1, 3 cho nhau) Lật A lên trên để được D (cũng chú
ý việc hoán đổi 1, 3 cho nhau) Như vậy ta có được cách lát cho hình kích thước 2K * 2K
bất kỳ, tuy nhiên ô trống bây giờ đang ở vị trí góc trái trên của nền (chính là ô mang mầu
2 của hình B) Vấn đề còn lại của ta là làm thế nào để chuyển ô trống này về vị trí yêu cầu (x, y) mà không làm mất đi tính liên kết (thoả mãn về mầu gạch) của bài toán Để giải quyết vấn đề này, ta lại phải sử dụng đến phương pháp qui nạp Với N=2 thì ta dễ dàng chuyển từ vị trí trái trên tới bất kỳ vị trí nào khác
Ví dụ:
Với 2K bất kỳ, ta cũng có thể làm tương tự Ví dụ ở trên, ta muốn chuyển từ ô trái trên của
B (toạ độ (1,8) ) tới một ô bất kỳ của D, giả sử là ô (2,3) Ta làm như sau:
Đầu tiên ta xoay các ô theo đường chéo để chuyển được ô trống từ (1,8) đến vị trí (4,5) Khi đó hình B sẽ có dạng như sau:
3 3 1 1
3 2 2 1
1 1 2 3
X 1 3 3
Tiếp đó, ta xoay viên gạch ở chính giữa sao cho ô trống chuyển sang phần D Khi đó, phối cảnh toàn nền sẽ là như sau:
Như vậy, bài toán đã được thu hẹp, bây giờ ta chỉ phải xử lí trong hình D kích thước 4*4
để chuyển ô trống từ vị trí (4,4) về vị trí (2,3) Ta lại xoay để chuyển ô trống về giữa và cuối cùng ta được nền cần lát với ô trống ở (2,3)
Trang 7Nhận xét: Có lẽ để cài đặt bài toán này ta nên chia 2 giai đoạn, giai đoạn khởi tạo (lát kín
nền với phần trống ở đỉnh trái trên) và phần đệ qui mô phỏng tính qui nạp của thuật toán (để xoay ô trống về đúng vị trí của nó) Chương trình cài đặt của bài 2 và bài 3 khá dài dòng, tôi không tiện nêu ở đây Nếu bạn nào muốn có chương trình để cùng trao đổi Xin liên hệ với tác giả qua mail
IV Bài toán 4:
Cuối cùng, xin được nêu một bài toán lát nền nữa để các bàn cùng tham khảo Đây là bài
4 trong đề thi chọn đội tuyển Quốc gia dự thi Olympic tin học quốc tế năm 2001 Bài toán phát biểu như sau: Ông chủ X dùng các viên gạch màu ghép bởi 3 ô vuông đơn vị tạo thành hình thước thợ để lát một căn phòng hình vuông được chia ra làm 4n*4n ô vuông đơn vị, trong đó n là một số nguyên dương không chia hết cho 3 Mỗi một viên gạch chỉ có một màu, nhưng có nhiều loại gạch mầu khác nhau và không hạn chế số lượng Trong phòng phải có 4 lỗ để thoát nước, mỗi lỗ một ô vuông đơn vị Hãy giúp ông
X tìm cách lát nền thoả mãn các yêu cầu sau:
Mỗi viên gạch được lát trùng khít 3 ô vuông đơn vị của phòng và mỗi ô vuông đơn vị của phòng, trừ các ô thoát nước phải được phủ bởi đúng một viên Hai viên có điểm chúng không là đỉnh phải có mầu khác nhau Số mầu dùng là ít nhất
Dữ liệu: Trong file văn bản COVER.INP
Dòng đầu ghi số nguyên N (1 ≤ N ≤ 50)
Dòng thứ hai ghi 4 cặp toạ độ (x, y) của 4 lỗ thoát nước Toạ độ dòng được đánh số từ trên xuống dưới và toạ độ cột được đánh số từ trái sang phải, bắt đầu từ 1
Kết quả: Ra file văn bản COVER.OUT
Dòng đầu ghi số lượng mầu đã sử dụng, là số -1 nếu như không tồn tại cách lát nền Trường hợp có cách lát thì:
Dòng thứ i trong 4n dòng tiếp theo, ghi 4n số nguyên, trong đó số thứ j mà số hiệu mầu của viên gạch phủ ô (i,j), ghi số 0 nếu đó là ô thoát nước Số hiệu mầu được đánh số bắt đầu từ 1
Ghí chú: Nếu có nhiều cách lát thì chỉ cần đưa ra một.
Ví dụ: