Bài giảng Chuyên đề Bài toán liệt kê

 
Bài toán lit kê  
\ 1 [  
MC LC  
Lê Minh Hoàng  
Bài toán lit kê  
\ 2 [  
§
0. GII THIU  
Trong thc tế, có mt sbài toán yêu cu chrõ: trong mt tp các đi tượng cho trước có bao  
nhiêu đi tượng thomãn nhng điu kin nht định. Bài toán đó gi là bài toán đếm cu hình tổ  
hp.  
Trong lp các bài toán đếm, có nhng bài toán còn yêu cu chrõ nhng cu hình tìm được thoả  
mãn điu kin đã cho là nhng cu hình nào. Bài toán yêu cu đưa ra danh sách các cu hình có thể  
có gi là bài toán lit kê thp.  
Để gii bài toán lit kê, cn phi xác định được mt thut toán để có ththeo đó ln lượt xây dng  
được tt ccác cu hình đang quan tâm. Có nhiu phương pháp lit kê, nhưng chúng cn phi đáp  
ng được hai yêu cu dưới đây:  
Không được lp li mt cu hình  
Không được bsót mt cu hình  
Có thnói rng, phương pháp lit kê là phương kế cui cùng để gii được mt sbài toán thp  
hin nay. Khó khăn chính ca phương pháp này chính là sbùng nthp. Để xây dng 1 tcu  
hình (con snày không phi là ln đi vi các bài toán thp - Ví dlit kê các cách xếp n13  
người quanh mt bàn tròn) và githiết rng mi thao tác xây dng mt khong 1 giây, ta phi mt  
quãng 31 năm mi gii xong. Tuy nhiên cùng vi sphát trin ca máy tính đin t, bng phương  
pháp lit kê, nhiu bài toán thp đã tìm thy li gii. Qua đó, ta cũng nên biết rng chnên dùng  
phương pháp lit kê khi không còn mt phương pháp nào khác tìm ra li gii. Chính nhng nỗ  
lc gii quyết các bài toán thc tế không dùng phương pháp lit kê đã thúc đẩy sphát trin ca  
nhiu ngành toán hc.  
Cui cùng, nhng tên gi sau đây, tuy vnghĩa không phi đng nht, nhưng trong mt strường  
hp người ta có thdùng ln nghĩa ca nhau được. Đó là:  
Phương pháp lit kê  
Phương pháp vét cn trên tp phương án  
Phương pháp duyt toàn bộ  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 3 [  
§
1. NHC LI MT SKIN THC ĐẠI STHP  
Cho S là mt tp hu hn gm n phn tvà k là mt stnhiên.  
Gi X là tp các snguyên dương t1 đến k: X = {1, 2, ..., k}  
I. CHNH HP LP  
Mi ánh xf: X S. Cho tương ng vi mi i X, mt và chmt phn tf(i) S.  
Được gi là mt chnh hp lp chp k ca S.  
Nhưng do X là tp hu hn (k phn t) nên ánh xf có thxác định qua bng các giá trf(1), f(2),  
..., f(k).  
Ví d: S = {A, B, C, D, E, F}; k = 3. Mt ánh xf có thcho như sau:  
i
1
E
2
C
3
E
f(i)  
Nên người ta đồng nht f vi dãy giá tr(f(1), f(2), ..., f(k)) và coi dãy giá trnày cũng là mt  
chnh hp lp chp k ca S. Như ví dtrên (E, C, E) là mt chnh hp lp chp 3 ca S. Ddàng  
chng minh được kết qusau bng quy np hoc bng phương pháp đánh giá khnăng la chn:  
Schnh hp lp chp k ca tp gm n phn t:  
Akn = nk  
II. CHNH HP KHÔNG LP  
Khi f là đơn ánh có nghĩa là vi i, j X ta có f(i) = f(j) i = j. Nói mt cách dhiu, khi dãy giá  
trf(1), f(2), ..., f(k) gm các phn tthuc S khác nhau đôi mt thì f được gi là mt chnh hp  
không lp chp k ca S. Ví dmt chnh hp không lp (C, A, E):  
i
1
C
2
A
3
E
f(i)  
Schnh hp không lp chp k ca tp gm n phn t:  
n!  
(n k)!  
Akn = n(n 1)(n 2)...(n k +1) =  
III. HOÁN VỊ  
Khi k = n. Mt chnh hp không lp chp n ca S được gi là mt hoán vcác phn tca S.  
Ví d: mt hoán v: (A, D, C, E, B, F) ca S = {A, B, C, D, E, F}  
i
1
A
2
D
3
C
4
E
5
B
6
F
f(i)  
Để ý rng khi k = n thì sphn tca tp X = {1, 2, .., n} đúng bng sphn tca S. Do tính cht  
đôi mt khác nhau nên dãy f(1), f(2), ..., f(n) slit kê được hết các phn ttrong S. Như vy f là  
toàn ánh. Mt khác do githiết f là chnh hp không lp nên f là đơn ánh. Ta có tương ng 1-1 gia  
các phn tca X và S, do đó f là song ánh. Vy nên ta có thể định nghĩa mt hoán vca S là mt  
song ánh gia {1, 2, ..., n} và S.  
Shoán vca tp gm n phn t= schnh hp không lp chp n:  
Pn = n!  
IV. THP  
Mt tp con gm k phn tca S được gi là mt thp chp k ca S.  
Lê Minh Hoàng  
         
Bài toán lit kê  
\ 4 [  
Ly mt tp con k phn tca S, xét tt ck! hoán vca tp con này. Dthy rng các hoán vị đó  
là các chnh hp không lp chp k ca S. Ví dly tp {A, B, C} là tp con ca tp S trong ví dụ  
trên thì: (A, B, C), (C, A, B), (B, C, A), ... là các chnh hp không lp chp 3 ca S. Điu đó tc là  
khi lit kê tt ccác chnh hp không lp chp k thì mi thp chp k sẽ được tính k! ln. Vy:  
Sthp chp k ca tp gm n phn t:  
Ank  
n!  
Ckn =  
=
k! k!(n k)!  
Stp con ca tp n phn t:  
C0n + C1n + ... + Cnn = (1+1)n = 2n  
Lê Minh Hoàng  
Bài toán lit kê  
\ 5 [  
§
2. PHƯƠNG PHÁP SINH (GENERATE)  
Phương pháp sinh có tháp dng để gii bài toán lit kê thp đặt ra nếu như hai điu kin sau  
thomãn:  
1. Có thxác định được mt thttrên tp các cu hình thp cn lit kê. Từ đó có thxác  
định được cu hình đầu tiên và cu hình cui cùng trong thtự đã xác định  
2. Xây dng được thut toán tcu hình chưa phi cu hình cui, sinh ra được cu hình kế  
tiếp nó.  
Phương pháp sinh có thmô tnhư sau:  
<Xây dng cu hình đầu tiên>;  
repeat  
<Đưa ra cu hình đang có>;  
<Tcu hình đang có sinh ra cu hình kế tiếp nếu còn>;  
until <hết cu hình>;  
Thttừ đin  
Trên các kiu dliu đơn gin chun, người ta thường nói ti khái nim tht. Ví dtrên kiu số  
thì có quan h: 1 < 2; 2 < 3; 3 < 10; ..., trên kiu ký tChar thì cũng có quan h'A' < 'B'; 'C' < 'c'...  
Xét quan hthttoàn phn "nhhơn hoc bng" ký hiu "" trên mt tp hp S, là quan hhai  
ngôi thomãn bn tính cht:  
Vi a, b, c S  
Tính phbiến: Hoc là a b, hoc b a;  
Tính phn x: a a  
Tính phn đi xng: Nếu a b và b a thì bt buc a = b.  
Tính bc cu: Nếu có a b và b c thì a c.  
Trong trường hp a b và a b, ta dùng ký hiu "<" cho gn, (ta ngm hiu các ký hiu như , >,  
khi phi định nghĩa)  
Ví dnhư quan h"" trên các snguyên cũng như trên các kiu vô hướng, lit kê là quan hthtự  
toàn phn.  
Trên các dãy hu hn, người ta cũng xác định mt quan htht:  
Xét a = (a1, a2, ..., an) và b = (b1, b2, ..., bn); trên các phn tca a1, ..., an, b1, ..., bn đã có quan hệ  
tht"". Khi đó a b nếu như  
Hoc ai = bi vi i: 1 i n.  
Hoc tn ti mt snguyên dương k: 1 k < n để:  
a1  
a2  
=
=
b1  
b2  
...  
ak-1  
ak  
=
=
<
bk-1  
bk  
bk+1  
ak+1  
Trong trường hp này, ta có thviết a < b.  
Thtự đó gi là thttừ đin trên các dãy độ dài n.  
Khi độ dài hai dãy a và b không bng nhau, người ta cũng xác định được thttừ đin. Bng cách  
thêm vào cui dãy a hoc dãy b nhng phn tử đặc bit gi là phn tđể độ dài ca a và b bng  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 6 [  
nhau, và coi nhng phn tnày nhhơn tt ccác phn tkhác, ta li đưa vxác định thttừ  
đin ca hai dãy cùng độ dài. Ví d:  
(1, 2, 3, 4) < (5, 6)  
(a, b, c) < (a, b, c, d)  
'calculator' < 'computer'  
I. SINH CÁC DÃY NHPHÂN ĐỘ DÀI N  
Mt dãy nhphân độ dài n là mt dãy x = x1x2...xn trong đó xi {0, 1} (i : 1 i n).  
Dthy: mt dãy nhphân x độ dài n là biu din nhphân ca mt giá trnguyên p(x) nào đó nm  
trong đon [0, 2n - 1]. Scác dãy nhphân độ dài n = scác snguyên [0, 2n - 1] = 2n. Ta slp  
chương trình lit kê các dãy nhphân theo thttừ đin có nghĩa là slit kê ln lượt các dãy nhị  
phân biu din các snguyên theo tht0, 1,..., 2n-1.  
Ví d: Khi n = 3, các dãy nhphân độ dài 3 được lit kê như sau:  
p(x)  
x
0
000  
1
001  
2
010  
3
011  
4
100  
5
101  
6
110  
7
111  
Như vy dãy đầu tiên slà 00...0 và dãy cui cùng slà 11...1. Nhn xét rng nếu dãy x = (x1, x2, ...,  
xn) là dãy đang có và không phi dãy cui cùng thì dãy kế tiếp snhn được bng cách cng thêm 1  
( theo cơ s2 có nh) vào dãy hin ti.  
Ví dkhi n = 8:  
Dãy đang có:  
cng thêm 1:  
10010000  
+ 1  
Dãy đang có:  
cng thêm 1:  
10010111  
+ 1  
  
10010001  
  
10011000  
Dãy mi:  
Dãy mi:  
Như vy kthut sinh cu hình kế tiếp tcu hình hin ti có thmô tnhư sau: Xét tcui  
dãy về đầu (xét thàng đơn vlên), gp s0 đu tiên thì thay nó bng s1 và đt tt ccác phn  
tphía sau vtrí đó bng 0.  
i := n;  
while (i > 0) and (xi = 1) do i := i - 1;  
if i > 0 then  
begin  
xi := 1;  
for j := i + 1 to n do xj := 0;  
end;  
Dliu vào (Input): nhp tfile văn bn BSTR.INP cha snguyên dương n 30  
Kết qura(Output): ghi ra file văn bn BSTR.OUT các dãy nhphân độ dài n.  
BSTR.INP  
3
BSTR.OUT  
000  
001  
010  
011  
100  
101  
110  
111  
PROG02_1.PAS * Thut toán sinh lit kê các dãy nhphân độ dài n  
program Binary_Strings;  
const  
max = 30;  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 7 [  
var  
x: array[1..max] of Integer;  
n, i: Integer;  
begin  
{Định nghĩa li thiết bnhp/xut chun}  
Assign(Input, 'BSTR.INP'); Reset(Input);  
Assign(Output, 'BSTR.OUT'); Rewrite(Output);  
ReadLn(n);  
FillChar(x, SizeOf(x), 0);  
repeat  
{Cu hình ban đầu x1 = x2 = ... = xn := 0}  
{Thut toán sinh}  
for i := 1 to n do Write(x[i]);  
WriteLn;  
{In ra cu hình hin ti}  
i := n;  
{xi là phn tcui dãy, lùi dn i cho ti khi gp s0 hoc khi i = 0 thì dng}  
while (i > 0) and (x[i] = 1) do Dec(i);  
if i > 0 then  
begin  
{Chưa gp phi cu hình 11...1}  
x[i] := 1;  
{Thay xi bng s1}  
FillChar(x[i + 1], (n - i) * SizeOf(x[1]), 0);  
end;  
until i = 0;  
{Đặt xi + 1 = xi + 2 = ... = xn := 0}  
{Đã hết cu hình}  
{Đóng thiết bnhp xut chun, thc ra không cn vì BP stự động đóng Input và Output trước khi thoát chương trình}  
Close(Input); Close(Output);  
end.  
II. LIT KÊ CÁC TP CON K PHN TỬ  
Ta slp chương trình lit kê các tp con k phn tca tp {1, 2, ..., n} theo thttừ đin  
Ví d: vi n = 5, k = 3, ta phi lit kê đủ 10 tp con:  
1.{1, 2, 3} 2.{1, 2, 4} 3.{1, 2, 5} 4.{1, 3, 4} 5.{1, 3, 5}  
6.{1, 4, 5} 7.{2, 3, 4} 8.{2, 3, 5} 9.{2, 4, 5} 10.{3, 4, 5}  
Như vy tp con đầu tiên (cu hình khi to) là {1, 2, ..., k}.  
Cu hình kết thúc là {n - k + 1, n - k + 2, ..., n}.  
Nhn xét: Ta sin ra tp con bng cách in ra ln lượt các phn tca nó theo thttăng dn. Từ  
đó, ta có nhn xét nếu x = {x1, x2, ..., xk} và x1 < x2 < ... < xk thì gii hn trên (giá trln nht có  
thnhn) ca xk là n, ca xk-1 là n - 1, ca xk-2 là n - 2...  
Cth: gii hn trên ca xi = n - k + i;  
Còn tt nhiên, gii hn dưới ca xi (giá trnhnht xi có thnhn) là xi-1 + 1.  
Như vy nếu ta đang có mt dãy x đại din cho mt tp con, nếu x là cu hình kết thúc có nghĩa là  
tt ccác phn ttrong x đều đã đạt ti gii hn trên thì quá trình sinh kết thúc, nếu không thì ta  
phi sinh ra mt dãy x mi tăng dn thomãn va đủ ln hơn dãy cũ theo nghĩa không có mt tp  
con k phn tnào chen gia chúng khi sp thttừ đin.  
Ví d: n = 9, k = 6. Cu hình đang có x = {1, 2, 6, 7, 8, 9}. Các phn tx3 đến x6 đã đt ti gii  
hn trên nên để sinh cu hình mi ta không thsinh bng cách tăng mt phn ttrong scác x6, x5,  
x4, x3 lên được, ta phi tăng x2 = 2 lên thành x2 = 3. Được cu hình mi là x = {1, 3, 6, 7, 8, 9}. Cu  
hình này đã thomãn ln hơn cu hình trước nhưng chưa thomãn tính cht va đủ ln mun vy  
ta li thay x3, x4, x5, x6 bng các gii hn dưới ca nó. Tc là:  
x3 := x2 + 1 = 4  
x4 := x3 + 1 = 5  
x5 := x4 + 1 = 6  
x6 := x5 + 1 = 7  
Ta được cu hình mi x = {1, 3, 4, 5, 6, 7} là cu hình kế tiếp. Nếu mun tìm tiếp, ta li nhn thy  
rng x6 = 7 chưa đt gii hn trên, như vy chcn tăng x6 lên 1 là được x = {1, 3, 4, 5, 6, 8}.  
Vy kthut sinh tp con kế tiếp ttp đã có x có thxây dng như sau:  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 8 [  
Tìm tcui dãy lên đầu cho ti khi gp mt phn txi chưa đạt gii hn trên n - k + i.  
i := n;  
while (i > 0) and (xi = n - k + i) do i := i - 1;  
(1, 2, 6, 7, 8, 9);  
Nếu tìm thy:  
if i > 0 then  
Tăng xi đó lên 1.  
xi := xi + 1;  
(1, 3, 6, 7, 8, 9)  
Đặt tt ccác phn tphía sau xi bng gii hn dưới:  
for j := i + 1 to k do xj := xj-1 + 1;  
(1, 3, 4, 5, 6, 7)  
Input: file văn bn SUBSET.INP cha hai snguyên dương n, k (1 k n 30) cách nhau ít nht  
mt du cách  
Output: file văn bn SUBSET.OUT các tp con k phn tca tp {1, 2, ..., n}  
SUBSET.INP  
5 3  
SUBSET.OUT  
{1, 2, 3}  
{1, 2, 4}  
{1, 2, 5}  
{1, 3, 4}  
{1, 3, 5}  
{1, 4, 5}  
{2, 3, 4}  
{2, 3, 5}  
{2, 4, 5}  
{3, 4, 5}  
PROG02_2.PAS * Thut toán sinh lit kê các tp con k phn tử  
program Combinations;  
const  
max = 30;  
var  
x: array[1..max] of Integer;  
n, k, i, j: Integer;  
begin  
{Định nghĩa li thiết bnhp/xut chun}  
Assign(Input, 'SUBSET.INP'); Reset(Input);  
Assign(Output, 'SUBSET.OUT'); Rewrite(Output);  
ReadLn(n, k);  
for i := 1 to k do x[i] := i;  
Count := 0;  
――repeat  
{x1 := 1; x2 := 2; ... ; x3 := k (Cu hình khi to)}  
{Biến đếm}  
{In ra cu hình hin ti}  
Write('{');  
for i := 1 to k - 1 do Write(x[i], ', ');  
WriteLn(x[k], '}');  
{Sinh tiếp}  
i := k;  
{xi là phn tcui dãy, lùi dn i cho ti khi gp mt xi chưa đạt gii hn trên n - k + i}  
while (i > 0) and (x[i] = n - k + i) do Dec(i);  
if i > 0 then  
begin  
{Nếu chưa lùi đến 0 có nghĩa là chưa phi cu hình kết thúc}  
――  
Inc(x[i]);  
{Tăng xi lên 1, Đặt các phn tử đứng sau xi bng gii hn dưới ca nó}  
for j := i + 1 to k do x[j] := x[j - 1] + 1;  
end;  
until i = 0;  
Close(Input); Close(Output);  
{Lùi đến tn 0 có nghĩa là tt ccác phn tử đã đạt gii hn trên - hết cu hình}  
end.  
Lê Minh Hoàng  
Bài toán lit kê  
\ 9 [  
III. LIT KÊ CÁC HOÁN VỊ  
Ta slp chương trình lit kê các hoán vca {1, 2, ..., n} theo thttừ đin.  
Ví dvi n = 4, ta phi lit kê đủ 24 hoán v:  
1.1234  
7.2134  
2.1243  
8.2143  
3.1324  
4.1342  
5.1423  
6.1432  
9.2314 10.2341 11.2413 12.2431  
13.3124 14.3142 15.3214 16.3241 17.3412 18.3421  
19.4123 20.4132 21.4213 22.4231 23.4312 24.4321  
Như vy hoán vị đầu tiên slà (1, 2, ..., n). Hoán vcui cùng là (n, n-1, ... , 1).  
Hoán vssinh ra phi ln hơn hoán vhin ti, hơn thế na phi là hoán vva đủ ln hơn hoán vị  
hin ti theo nghĩa không thcó mt hoán vnào khác chen gia chúng khi sp tht.  
Gishoán vhin ti là x = (3, 2, 6, 5, 4, 1), xét 4 phn tcui cùng, ta thy chúng được xếp gim  
dn, điu đó có nghĩa là cho dù ta có hoán v4 phn tnày thế nào, ta cũng được mt hoán vbé  
hơn hoán vhin ti!. Như vy ta phi xét đến x2 = 2, thay nó bng mt giá trkhác. Ta sthay bng  
giá trnào?, không thlà 1 bi nếu vy sẽ được hoán vnhhơn, không thlà 3 vì đã có x1 = 3 ri  
(phn tsau không được chn vào nhng giá trmà phn ttrước đã chn). Còn li các giá tr4, 5,  
6. Vì cn mt hoán vva đủ ln hơn hin ti nên ta chn x2 = 4. Còn các giá tr(x3, x4, x5, x6) sẽ  
ly trong tp {2, 6, 5, 1}. Cũng vì tính va đủ ln nên ta stìm biu din nhnht ca 4 snày gán  
cho x3, x4, x5, x6 tc là (1, 2, 5, 6). Vy hoán vmi slà (3, 4, 1, 2, 5, 6).  
(3, 2, 6, 5, 4, 1) (3, 4, 1, 2, 5, 6).  
Ta có nhn xét gì qua ví dnày: Đon cui ca hoán vị được xếp gim dn, sx5 = 4 là snhnht  
trong đon cui gim dn thomãn điu kin ln hơn x2 = 2. Nếu đổi chx5 cho x2 thì ta sẽ được x2  
= 4 và đon cui vn được sp xếp gim dn. Khi đó mun biu din nhnht cho các giá trị  
trong đon cui thì ta chcn đảo ngược đon cui.  
Trong trường hp hoán vhin ti là (2, 1, 3, 4) thì hoán vkế tiếp slà (2, 1, 4, 3). Ta cũng có thể  
coi hoán v(2, 1, 3, 4) có đon cui gim dn, đon cui này chgm 1 phn t(4)  
Vy kthut sinh hoán vkế tiếp thoán vhin ti có thxây dng như sau:  
Xác định đon cui gim dn dài nht, tìm chsi ca phn txi đứng lin trước đon cui đó.  
Điu này đng nghĩa vi vic tìm tvtrí sát cui dãy lên đu, gp chsi đu tiên tha mãn xi  
< xi+1. Nếu toàn dãy đã là gim dn, thì đó là cu hình cui.  
i := n - 1;  
while (i > 0) and (xi > xi+1) do i := i - 1;  
Trong đon cui gim dn, tìm phn txk nhnht thomãn điu kin xk > xi. Do đon cui  
gim dn, điu này thc hin bng cách tìm tcui dãy lên đu gp chsk đu tiên thomãn  
xk > xi (có thdùng tìm kiếm nhphân).  
k := n;  
while xk < xi do k := k - 1;  
Đổi chxk và xi, lt ngược thtự đon cui gim dn (txi+1 đến xk) trthành tăng dn.  
Input: file văn bn PERMUTE.INP cha snguyên dương n 12  
Output: file văn bn PERMUTE.OUT các hoán vca dãy (1, 2, ..., n)  
PERMUTE.INP  
3
PERMUTE.OUT  
1 2 3  
1 3 2  
2 1 3  
2 3 1  
3 1 2  
3 2 1  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 10 [  
PROG02_3.PAS * Thut toán sinh lit kê hoán vị  
program Permute;  
const  
max = 12;  
var  
n, i, k, a, b: Integer;  
x: array[1..max] of Integer;  
procedure Swap(var X, Y: Integer); {Thtc đảo giá trhai tham biến X, Y}  
var  
Temp: Integer;  
begin  
Temp := X; X := Y; Y := Temp;  
end;  
begin  
Assign(Input, 'PERMUTE.INP'); Reset(Input);  
Assign(Output, 'PERMUTE.OUT'); Rewrite(Output);  
ReadLn(n);  
for i := 1 to n do x[i] := i;―  
――repeat  
{Khi to cu hình đầu: x1 := 1; x2 := 2; ..., xn := n}  
――――for i := 1 to n do Write(x[i], ' ');  
{In ra cu hình hoán vhin ti}  
WriteLn;  
i := n - 1;  
while (i > 0) and (x[i] > x[i + 1]) do Dec(i);  
if i > 0 then  
――――――begin  
{Chưa gp phi hoán vcui (n, n-1, ... ,1)}  
k := n;  
{xk là phn tcui dãy}  
――――  
while x[k] < x[i] do Dec(k);―  
Swap(x[k], x[i]);  
{Lùi dn k để tìm gp xk đầu tiên ln hơn x }  
i
{Đổi chxk và xi}  
{Lt ngược đon cui gim dn, a: đầu đon, b: cui đon}  
―――――― a := i + 1; b := n;  
――  
while a < b do  
begin  
Swap(x[a], x[b]);  
Inc(a);  
Dec(b);  
{Đổi chxa và xb}  
{Tiến a và lùi b, đổi chtiếp cho ti khi a, b chm nhau}  
end;  
end;  
until i = 0;{Toàn dãy là dãy gim dn - không sinh tiếp được - hết cu hình}  
Close(Input); Close(Output);  
end.  
Bài tp:  
1. Các chương trình trên xlý không tt trong trường hp tm thường, đó là trường hp n = 0 đi  
vi chương trình lit kê dãy nhphân cũng như trong chương trình lit kê hoán v, trường hp k = 0  
đi vi chương trình lit kê thp, hãy khc phc điu đó.  
2. Lit kê các dãy nhphân độ dài n có thcoi là lit kê các chnh hp lp chp n ca tp 2 phn tử  
{0, 1}. Hãy lp chương trình:  
Nhp vào hai sn và k, lit kê các chnh hp lp chp k ca {0, 1, ..., n -1}.  
Gi ý: thay hcơ s2 bng hcơ sn.  
3. Hãy lit kê các dãy nhphân độ dài n mà trong đó cm chs"01" xut hin đúng 2 ln.  
Bài tp:  
4. Nhp vào mt danh sách n tên người. Lit kê tt ccác cách chn ra đúng k người trong sn  
người đó.  
Gi ý: xây dng mt ánh xttp {1, 2, ..., n} đến tp các tên người. Ví dxây dng mt mng  
Tên: Tên[1] := 'Nguyn văn A'; Tên[2] := 'Trn thB';.... sau đó lit kê tt ccác tp con k phn tử  
Lê Minh Hoàng  
Bài toán lit kê  
\ 11 [  
ca tp {1, 2, ..., n}. Chđiu khi in tp con, ta không in giá trs{1, 3, 5} mà thay vào đó sin  
ra {Tên[1], Tên [3], Tên[5]}. Tc là in ra nh ca các giá trtìm được qua ánh xạ  
5. Lit kê tt ccác tp con ca tp {1, 2, ..., n}. Có thdùng phương pháp lit kê tp con như trên  
hoc dùng phương pháp lit kê tt ccác dãy nhphân. Mi s1 trong dãy nhphân tương ng vi  
mt phn tử được chn trong tp. Ví dvi tp {1, 2, 3, 4} thì dãy nhphân 1010 stương ng vi  
tp con {1, 3}. Hãy lp chương trình in ra tt ccác tp con ca {1, 2, ..., n} theo hai phương pháp.  
5. Nhp vào danh sách tên n người, in ra tt ccác cách xếp n người đó vào mt bàn  
6. Nhp vào danh sách n người nam và n người n, in ra tt ccác cách xếp 2n người đó vào mt  
bàn tròn, mi người nam tiếp đến mt người n.  
7. Người ta có thdùng phương pháp sinh để lit kê các chnh hp không lp chp k. Tuy nhiên có  
mt cách là lit kê tt ccác tp con k phn tca tp hp, sau đó in ra đủ k! hoán vca nó. Hãy  
viết chương trình lit kê các chnh hp không lp chp k ca {1, 2, ..., n}.  
8. Lit kê tt ccác hoán vchcái trong tMISSISSIPPI theo thttừ đin.  
9. Lit kê tt ccác cách phân tích snguyên dương n thành tng các snguyên dương, hai cách  
phân tích là hoán vca nhau chtính là mt cách.  
Cui cùng, ta có nhn xét, mi phương pháp lit kê đều có ưu, nhược đim riêng và phương pháp  
sinh cũng không nm ngoài nhn xét đó. Phương pháp sinh không thsinh ra được cu hình thứ  
p nếu như chưa có cu hình thp - 1, chng trng phương pháp sinh tra ưu đim trong trường  
hp lit kê toàn bmt slượng nhcu hình trong mt bdliu ln thì li có nhược đim và  
ít tính phdng trong nhng thut toán duyt hn chế. Hơn thế na, không phi cu hình ban đầu  
lúc nào cũng dtìm được, không phi kthut sinh cu hình kế tiếp cho mi bài toán đều đơn gin  
như trên (Sinh các chnh hp không lp chp k theo thttừ đin chng hn). Ta sang mt chuyên  
mc sau nói đến mt phương pháp lit kê có tính phdng cao hơn, để gii các bài toán lit kê  
phc tp hơn đó là: Thut toán quay lui (Back tracking).  
Lê Minh Hoàng  
Bài toán lit kê  
\ 12 [  
§
3. THUT TOÁN QUAY LUI  
Thut toán quay lui dùng để gii bài toán lit kê các cu hình. Mi cu hình được xây dng  
bng cách xây dng tng phn t, mi phn tử được chn bng cách thtt ccác khnăng.  
Githiết cu hình cn lit kê có dng (x1, x2,..., xn). Khi đó thut toán quay lui thc hin qua các  
bước sau:  
1) Xét tt ccác giá trx1 có thnhn, thcho x1 nhn ln lượt các giá trị đó. Vi mi giá trthử  
gán cho x1 ta s:  
2) Xét tt ccác giá trx2 có thnhn, li thcho x2 nhn ln lượt các giá trị đó. Vi mi giá trị  
thgán cho x2 li xét tiếp các khnăng chn x3 ... ctiếp tc như vy đến bước:  
n) Xét tt ccác giá trxn có thnhn, thcho xn nhn ln lượt các giá trị đó, thông báo cu hình  
tìm được (x1, x2, ..., xn).  
Trên phương din quy np, có thnói rng thut toán quay lui lit kê các cu hình n phn tdng  
(x1, x2, .., xn) bng cách thcho x1 nhn ln lượt các giá trcó th. Vi mi giá trthgán cho x1 li  
lit kê tiếp cu hình n - 1 phn t(x2, x3, ..., xn).  
Mô hình ca thut toán quay lui có thmô tnhư sau:  
{Thtc này thcho xi nhn ln lượt các giá trmà nó có thnhn}  
procedure Try(i: Integer);  
begin  
for (mi giá trV có thgán cho xi) do  
begin  
<Thcho xi := V>;  
if (xi là phn tcui cùng trong cu hình) then  
<Thông báo cu hình tìm được>  
else  
begin  
<Ghi nhn vic cho xi nhn giá trV (Nếu cn)>;  
Try(i + 1); {Gi đệ quy để chn tiếp x  
}
i+1  
――  
<Nếu cn, bghi nhn vic thxi := V, để thgiá trkhác>;  
end;  
end;  
end;  
Thut toán quay lui sbt đu bng li gi Try(1)  
Ta có thtrình bày quá trình tìm kiếm li gii ca thut toán quay lui bng cây sau:  
Try(1)  
Try(2)  
Try(2)  
Try(3)  
Try(3)  
Try(3)  
Try(3)  
Hình 1: Cây tìm kiếm quay lui  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 13 [  
I. LIT KÊ CÁC DÃY NHPHÂN ĐỘ DÀI N  
Input/Output vi khuôn dng như trong PROG2_1.PAS  
Biu din dãy nhphân độ dài N dưới dng (x1, x2, ..., xn). Ta slit kê các dãy này bng cách thử  
dùng các giá tr{0, 1} gán cho xi. Vi mi giá trthgán cho xi li thcác giá trcó thgán cho  
xi+1.Chương trình lit kê bng thut toán quay lui có thviết:  
PROG03_1.PAS * Thut toán quay lui lit kê các dãy nhphân độ dài n  
program BinaryStrings;  
const  
max = 30;  
var  
x: array[1..max] of Integer;  
n: Integer;  
procedure PrintResult;  
var  
{In cu hình tìm được, do thtc tìm đệ quy Try gi khi tìm ra mt cu hình}  
i: Integer;  
begin  
for i := 1 to n do Write(x[i]);  
WriteLn;  
end;  
procedure Try(i: Integer);  
var  
{Thcác cách chn x}  
i
j: Integer;  
begin  
for j := 0 to 1 do  
――――begin  
{Xét các giá trcó thgán cho xi, vi mi giá trị đó}  
x[i] := j;  
{Thử đặt x}  
if i = n then PrintResult {Nếu i = n ithì in kết qu}  
―――― else Try(i + 1);  
end;  
{Nếu i chưa phi là phn tcui thì tìm tiếp x }  
i+1  
end;  
begin  
Assign(Input, 'BSTR.INP'); Reset(Input);  
Assign(Output, 'BSTR.OUT'); Rewrite(Output);  
ReadLn(n);  
Try(1);  
Close(Input);  
Close(Output);  
{Nhp dliu}  
{Thcác cách chn giá trx1}  
end.  
Ví d: Khi n = 3, cây tìm kiếm quay lui như sau:  
Try(1)  
x1 := 1  
x1 := 0  
Try(2)  
x2 := 1  
Try(2)  
x2 := 0  
x2 := 1  
x2 := 0  
Try(3)  
x3 := 1  
Try(3)  
x3 := 1  
Try(3)  
x3 := 1  
Try(3)  
x3 := 1  
x3 := 0  
x3 := 0  
x3 := 0  
x3 := 0  
000  
010  
100  
110  
001  
011  
101  
111  
result  
Hình 2: Cây tìm kiếm quay lui trong bài toán lit kê dãy nhphân  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 14 [  
II. LIT KÊ CÁC TP CON K PHN TỬ  
Input/Output có khuôn dng như trong PROG02_2.PAS  
Để lit kê các tp con k phn tca tp S = {1, 2, ..., n} ta có thể đưa vlit kê các cu hình (x1, x2,  
..., xk) ở đây các xi S và x1 < x2 < ... < xk. Ta có nhn xét:  
xk n  
xk-1 xk - 1 n - 1  
...  
xi n - k + i  
...  
x1 n - k + 1.  
Từ đó suy ra xi-1 + 1 xi n - k + i (1 i k) ở đây ta githiết có thêm mt sx0 = 0 khi xét i = 1.  
Như vy ta sxét tt ccác cách chn x1 t1 (=x0 + 1) đến n - k + 1, vi mi giá trị đó, xét tiếp tt  
ccác cách chn x2 tx1 + 1 đến n - k + 2,... cnhư vy khi chn được đến xk thì ta có mt cu  
hình cn lit kê. Chương trình lit kê bng thut toán quay lui như sau:  
PROG03_2.PAS * Thut toán quay lui lit kê các tp con k phn tử  
program Combinations;  
const  
max = 30;  
var  
x: array[0..max] of Integer;  
n, k: Integer;  
procedure PrintResult; (*In ra tp con {x1, x2, ..., xk}*)  
var  
i: Integer;  
begin  
Write('{');  
for i := 1 to k - 1 do Write(x[i], ', ');  
WriteLn(x[k], '}');  
end;  
procedure Try(i: Integer);  
var  
{Thcác cách chn giá trcho x[i]}  
j: Integer;  
begin  
for j := x[i - 1] + 1 to n - k + i do  
begin  
x[i] := j;  
if i = k then PrintResult  
else Try(i + 1);  
end;  
end;  
begin  
Assign(Input, 'SUBSET.INP'); Reset(Input);  
Assign(Output, 'SUBSET.OUT'); Rewrite(Output);  
ReadLn(n, k);  
x[0] := 0;  
Try(1);  
Close(Input); Close(Output);  
end.  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 15 [  
Nếu để ý chương trình trên và chương trình lit kê dãy nhphân độ dài n, ta thy vcơ bn chúng  
chkhác nhau thtc Try(i) - chn thcác giá trcho xi, chương trình lit kê dãy nhphân ta  
thchn các giá tr0 hoc 1 còn chương trình lit kê các tp con k phn tta thchn xi là mt  
trong các giá trnguyên txi-1 + 1 đến n - k + i. Qua đó ta có ththy tính phdng ca thut toán  
quay lui: mô hình cài đt có ththích hp cho nhiu bài toán, khác vi phương pháp sinh tun t,  
vi mi bài toán li phi có mt thut toán sinh kế tiếp riêng làm cho vic cài đt mi bài mt khác,  
bên cnh đó, không phi thut toán sinh kế tiếp nào cũng dcài đt.  
III. LIT KÊ CÁC CHNH HP KHÔNG LP CHP K  
Để lit kê các chnh hp không lp chp k ca tp S = {1, 2, ..., n} ta có thể đưa vlit kê các cu  
hình (x1, x2, ..., xk) ở đây các xi S và khác nhau đôi mt.  
Như vy thtc Try(i) - xét tt ccác khnăng chn xi - sthhết các giá trt1 đến n, mà các giá  
trnày chưa bcác phn tử đứng trước chn. Mun xem các giá trnào chưa được chn ta sdng  
kthut dùng mng đánh du:  
Khi to mt mng c1, c2, ..., cn mang kiu logic. Ở đây ci cho biết giá tri có còn tdo hay đã  
bchn ri. Ban đầu khi to tt ccác phn tmng c là TRUE có nghĩa là các phn tt1  
đến n đều tdo.  
Ti bước chn các giá trcó thca xi ta chxét nhng giá trj có cj = TRUE có nghĩa là chỉ  
chn nhng giá trtdo.  
Trước khi gi đệ quy tìm xi+1: ta đặt giá trj va gán cho xi đã bchn có nghĩa là đặt cj :=  
FALSE để các thtc Try(i + 1), Try(i + 2)... gi sau này không chn phi giá trj đó na  
Sau khi gi đệ quy tìm xi+1: có nghĩa là sp ti ta sthgán mt giá trkhác cho xi thì ta sẽ đặt  
giá trj va thử đó thành tdo (cj := TRUE), bi khi xi đã nhn mt giá trkhác ri thì các phn  
tử đứng sau: xi+1, xi+2 ... hoàn toàn có thnhn li giá trj đó. Điu này hoàn toàn hp lý trong  
phép xây dng chnh hp không lp: x1 có n cách chn, x2 có n - 1 cách chn, ...Lưu ý rng khi  
thtc Try(i) có i = k thì ta không cn phi đánh du gì cvì tiếp theo chcó in kết quchứ  
không cn phi chn thêm phn tnào na.  
Input: file văn bn ARRANGES.INP cha hai snguyên dương n, k (1 k n 20) cách nhau ít  
nht mt du cách  
Output: file văn bn ARRANGES.OUT ghi các chnh hp không lp chp k ca tp {1, 2, ..., n}  
ARRANGES.INP  
3 2  
ARRANGES.OUT  
1 2  
1 3  
2 1  
2 3  
3 1  
3 2  
PROG03_3.PAS * Thut toán quay lui lit kê các chnh hp không lp chp k  
program Arranges;  
const  
max = 20;  
var  
x: array[1..max] of Integer;  
c: array[1..max] of Boolean;  
n, k: Integer;  
procedure PrintResult;  
{Thtc in cu hình tìm được}  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 16 [  
var  
i: Integer;  
begin  
for i := 1 to k do Write(x[i],' ');  
WriteLn;  
end;  
procedure Try(i: Integer); {Thcác cách chn x  
}
i
var  
j: Integer;  
begin  
for j := 1 to n do  
if c[j] then  
begin  
{Chxét nhng giá trj còn tdo}  
x[i] := j;  
if i = k then PrintResult {Nếu đã chn được đến xk thì chvic in kết qu}  
else  
――  
begin  
c[j] := False;  
Try(i + 1);  
c[j] := True;  
{Đánh du: j đã bchn}  
{Thtc này chxét nhng giá trcòn tdo gán cho xi+1, tc là skhông chn phi j}  
{Bỏ đánh du: j li là tdo, bi sp ti sthmt cách chn khác ca x  
――――――――  
――  
}
i
―――――――― end;  
end;  
end;  
begin  
Assign(Input, 'ARRANGES.INP'); Reset(Input);  
Assign(Output, 'ARRANGES.OUT'); Rewrite(Output);  
ReadLn(n, k);  
FillChar(c, SizeOf(c), True); {Tt ccác số đều chưa bchn}  
Try(1);  
{Thcác cách chn giá trca x1}  
Close(Input); Close(Output);  
end.  
Nhn xét: khi k = n thì đây là chương trình lit kê hoán vị  
IV. BÀI TOÁN PHÂN TÍCH SỐ  
Bài toán  
Cho mt snguyên dương n 30, hãy tìm tt ccác cách phân tích sn thành tng ca các số  
nguyên dương, các cách phân tích là hoán vca nhau chtính là 1 cách.  
Cách làm:  
1. Ta slưu nghim trong mng x, ngoài ra có mt mng t. Mng t xây dng như sau: ti slà tng  
các phn ttrong mng x tx1 đến xi: ti := x1 + x2 + ... + xi.  
2. Khi lit kê các dãy x có tng các phn tử đúng bng n, để tránh strùng lp ta đưa thêm ràng  
buc xi-1 xi.  
3. Vì sphn tthc sca mng x là không cố định nên thtc PrintResult dùng để in ra 1 cách  
phân tích phi có thêm tham scho biết sin ra bao nhiêu phn t.  
4. Thtc đệ quy Try(i) sthcác giá trcó thnhn ca xi (xi xi - 1)  
5. Khi nào thì in kết quvà khi nào thì gi đệ quy tìm tiếp ?  
Lưu ý rng ti - 1 là tng ca tt ccác phn ttx1 đến xi-1 do đó  
Khi ti = n tc là (xi = n - ti - 1) thì in kết quả  
Khi tìm tiếp, xi+1 sphi ln hơn hoc bng xi. Mt khác ti+1 là tng ca các stx1 ti xi+1  
không được vượt quá n. Vy ta có ti+1 n ti-1 + xi + xi+1 n xi + xi + 1 n - ti - 1 tc là xi  
Lê Minh Hoàng  
 
Bài toán lit kê  
\ 17 [  
(n - ti - 1)/2. Ví dụ đơn gin khi n = 10 thì chn x1 = 6, 7, 8, 9 là vic làm vô nghĩa vì như  
vy cũng không ra nghim mà cũng không chn tiếp x2 được na.  
Mt cách dhiu ta gi đệ quy tìm tiếp khi giá trxi được chn còn cho phép chn thêm mt  
phn tkhác ln hơn hoc bng nó mà không làm tng vượt quá n. Còn ta in kết quchkhi  
xi mang giá trị đúng bng sthiếu ht ca tng i-1 phn tử đầu so vi n.  
6. Vy thtc Try(i) thcác giá trcho xi có thmô tnhư sau: (để tng quát cho i = 1, ta đặt x0 =  
1 và t0 = 0).  
Xét các giá trca xi txi - 1 đến (n - ti-1) div 2, cp nht ti := ti - 1 + xi và gi đệ quy tìm tiếp.  
Cui cùng xét giá trxi = n - ti-1 và in kết qutx1 đến xi.  
Input: file văn bn ANALYSE.INP cha snguyên dương n 30  
Output: file văn bn ANALYSE.OUT ghi các cách phân tích sn.  
ANALYSE.INP  
6
ANALYSE.OUT  
6 = 1+1+1+1+1+1  
6 = 1+1+1+1+2  
6 = 1+1+1+3  
6 = 1+1+2+2  
6 = 1+1+4  
6 = 1+2+3  
6 = 1+5  
6 = 2+2+2  
6 = 2+4  
6 = 3+3  
6 = 6  
PROG03_4.PAS * Thut toán quay lui lit kê các cách phân tích số  
program Analyses;  
const  
max = 30;  
var  
n: Integer;  
x: array[0..max] of Integer;  
t: array[0..max] of Integer;  
procedure Init;  
begin  
{Khi to}  
ReadLn(n);  
x[0] := 1;  
t[0] := 0;  
end;  
procedure PrintResult(k: Integer);  
var  
i: Integer;  
begin  
Write(n,' = ');  
for i := 1 to k - 1 do Write(x[i], '+');  
WriteLn(x[k]);  
end;  
procedure Try(i: Integer);  
var  
j: Integer;  
begin  
for j := x[i - 1] to (n - T[i - 1]) div 2 do  
{Trường hp còn chn tiếp x }  
i+1  
begin  
x[i] := j;  
Lê Minh Hoàng  
Bài toán lit kê  
\ 18 [  
t[i] := t[i - 1] + j;  
Try(i + 1);  
end;  
x[i] := n - T[i - 1];  
PrintResult(i);  
{Nếu xi là phn tcui thì nó bt buc phi là ... và in kết qu}  
end;  
begin  
Assign(Input, 'ANALYSE.INP'); Reset(Input);  
Assign(Output, 'ANALYSE.OUT'); Rewrite(Output);  
Init;  
Try(1);  
Close(Input);  
Close(Output);  
end.  
Bây gita xét tiếp mt ví dkinh đin ca thut toán quay lui:  
V. BÀI TOÁN XP HU  
Bài toán  
Xét bàn ctng quát kích thước nxn. Mt quân hu trên bàn ccó thể ăn được các quân khác nm  
ti các ô cùng hàng, cùng ct hoc cùng đường chéo. Hãy tìm các xếp n quân hu trên bàn csao  
cho không quân nào ăn quân nào.  
Ví dmt cách xếp vi n = 8:  
Hình 3: Xếp 8 quân hu trên bàn c8x8  
Phân tích  
Rõ ràng n quân hu sẽ được đặt mi con mt hàng vì hu ăn được ngang, ta gi quân hu sẽ đặt  
hàng 1 là quân hu 1, quân hu hàng 2 là quân hu 2... quân hu hàng n là quân hu n.  
Vy mt nghim ca bài toán sẽ được biết khi ta tìm ra được vtrí ct ca nhng quân hu.  
Nếu ta định hướng Đông (Phi), Tây (Trái), Nam (Dưới), Bc (Trên) thì ta nhn thy rng:  
Mt đường chéo theo hướng Đông Bc - Tây Nam (ĐB-TN) bt ksẽ đi qua mt sô, các ô  
đó có tính cht: Hàng + Ct = C (Const). Vi mi đường chéo ĐB-TN ta có 1 hng sC và  
vi mt hng sC: 2 C 2n xác định duy nht 1 đường chéo ĐB-TN vì vy ta có thể đánh  
chscho các đường chéo ĐB- TN t2 đến 2n  
Mt đường chéo theo hướng Đông Nam - Tây Bc (ĐN-TB) bt ksẽ đi qua mt sô, các ô  
đó có tính cht: Hàng - Ct = C (Const). Vi mi đường chéo ĐN-TB ta có 1 hng sC và  
vi mt hng sC: 1 - n C n - 1 xác định duy nht 1 đường chéo ĐN-TB vì vy ta có thể  
đánh chscho các đường chéo ĐN- TB t1 - n đến n - 1.  
Lê Minh Hoàng  
 
Tải về để xem bản đầy đủ
pdf 258 trang yennguyen 09/04/2022 6060
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Chuyên đề Bài toán liệt kê", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfbai_giang_chuyen_de_bai_toan_liet_ke.pdf