Chương I. KỸ THUẬT THIẾT KẾ THUẬT TOÁN
intelligent that survives. It is the one that is the most adaptable
Charles Darwin
i thiu mt s k thut quan trng trong vic tip cn bài toán và tìm
thut toán. Các lp thut toán s c tho lu n
tr (divide and conquer), Quy ho ng (dynamic
programming) và Tham lam (greedy).
Các bài toán trên thc th có muôn hình muôn v, không th t cách thc
tìm gii thut cho m là nhng
n.
Khác vi nhng thut toán c th mà chúng m nh
hc theo ki
tìm thy các thut toán này trong bt c n lp trình nào.
Chúng ta ch có th kho sát mt vài bài toán c th và hp cn
v, cách thit k gii thut. T n k t khi gii các bài
toán thc t.
Bài 1. Liệt kê
Có mt s bài toán trên thc t yêu cu ch rõ: trong mt tc có bao
ng tho mãn nhu kin nhng nào. Bài toán
này gi là bài toán lit kê hay bài toán duyt.
Nu ta biu ding ci dng mt cu hình các bin s gii bài
toán lit kê, cn phc mt thut toán có th t xây dc
tt c các cn ph
c hai yêu c
c lp li mt cu hình
c b sót mt cu hình
c khi nói v các thut toán lit kê, chúng ta gii thiu mt s khái nin:
1.1. Vài khái niệm cơ bản
1.1.1. Thứ tự từ điển
Nhc li rng quan h th t toàn ph c bt tp hp ,
là quan h hai ngôi tho mãn bn tính cht:
Vi
Tính ph bin (Universality): Hoc là , hoc ;
Tính phn x (Reflexivity):
Tính phi xng (Antisymmetry) : Nu và thì bt buc
Tính bc cu (Transitivity): Nu có và thì .
Các quan h có th t suy ra t quan h này.
Trên các dãy hu hnh mt quan h th t:
Xét
và
dài , trên các phn t ca và th t toàn
ph
n:
Hoc hai dãy ging nhau:
Hoc tn ti mt s
và
Th t i là th t t n (lexicographic order) dài .
Khi hai dãy và có s phn t c th t t n.
Bng cách thêm vào cui dãy hoc dãy nhng phn t c bit gi là dài ca và
bng nhau, và coi nhng phn t này nh t c các phn t khác, ta l xác
nh th t t n c dài.
Ví d:
Th t t t quan h th t toàn phn trên các dãy.
1.1.2. Chỉnh hợp, tổ hợp, hoán vị.
Cho là mt tp hu hn gm phn t và là mt s t nhiên. Gi là tp các s nguyên
1 ti :
Chỉnh hợp lặp
Mt ánh x ng mi phn t mt và ch mt phn t
,
c gi là mt chnh hp lp chp ca
Do là tp hu hn ( phn t) nên ánh x có th nh qua bng các giá tr
, vì vy ta có th ng nht vi dãy giá tr
và coi
dãy giá tr t chnh hp lp chp ca .
Ví d . Mt ánh x cho bi:
1
2
3
ng vi tp nh
là mt chnh hp lp ca
S chnh hp lp chp ca tp phn t là
Chỉnh hợp không lặp
M c gi là mt chnh hp không lp chp ca . Nói cách khác, mt
chnh hp không lp là mt chnh hp lp có các phn t t.
Ví d mt chnh hp không lp chp 3
ca tp
1
2
3
Số chỉnh hợp không lặp chập của tập phần tử là
Hoán vị
Khi mi song ánh c gi là mt hoán v ca . Nói cách khác mt hoán v
ca là mt chnh hp không lp chp ca .
Ví d:
là mt hoán v ca
1
2
3
4
5
6
S hoán v ca tp phn t là
Tổ hợp
Mi tp con gm phn t ca c gi là mt t hp chp ca .
Ly mt t hp chp ca , xét tt c hoán v ca nó, mi hoán v s là mt chnh hp
không lp chp ca . c là khi lit kê tt c các chnh hp không lp chp thì
mi t hp chp s c tính ly nu xét v mt s ng:
S t hp chp ca tp phn t là
Ta có công thc khai trin nh thc:
Vì vy s
c gi là h s nh thc (binomial coefficient) th , bc
1.2. Phương pháp sinh
áp d gii bài toán lit kê nu kin sau tho
mãn:
Có th c mt th t trên tp các cu hình t hp cn lit kê. T
bic cu tiên và cu hình cui cùng theo th t
Xây dc thut toán t mt cu hìni cu hình cuc cu
hình k tip nó.
1.2.1. Mô hình sinh
vit bng mô hình chung:
«Xây dựng cấu hình đầu tiên»;
repeat
«Đưa ra cấu hình đang có»;
«Từ cấu hình đang có sinh ra cấu hình kế tiếp nếu còn»;
until «hết cấu hình»;
1.2.2. Liệt kê các dãy nhị phân độ dài
Mt dãy nh dài là mt dãy
.
Có th nhn thy rng mt dãy nh phân
là biu din nh phân ca mt giá tr nguyên
. S các dãy nh dài bng
, th t t n trên các
dãy nh dài i quan h th t trên các giá tr s mà chúng biu
din. Vì vy, lit kê các dãy nh phân theo th t t i ch ra lt các dãy
nh phân biu din các s nguyên theo th t
.
Ví d vi , có 8 dãy nh c lit kê:
000
001
010
011
100
101
110
111
0
1
2
3
4
5
6
7
Theo th t liu tiên là
và dãy cui cùng là
. Nu ta có mt dãy
nh dài , ta có th sinh ra dãy nh phân k tip bng cách c
s 2 có nh) vào dãy hin ti.
10101111
+ 1
────────
10110000
Da vào tính cht ca phép cng hai s nh phân, cu hình k tip có th sinh t cu hình
hin ti bng cách: xét t cu lên), tìm s 0 gu
Nu thy thì thay s ng s t tt c các phn t phía sau v ng 0.
Nu không thy thì thì toàn dãy là s u hình cui cùng.
Input
S .
Output
Các dãy nh dài .
Sample
Input
Sample Output
3
000
001
010
011
100
101
110
111
BINARYSTRINGS_GEN.PAS
{$MODE OBJFPC}
program BinaryStringEnumeration;
var
x: AnsiString;
n, i: Integer;
begin
ReadLn(n);
SetLength(x, n);
FillChar(x[1], n, '0');
//Cu x=00 0
repeat
WriteLn(x);
//Tìm s u tiên t cui dãy
i := n;
while (i > 0) and (x[i] = '1') do Dec(i);
if i > 0 then
begin
x[i] := '1';
if i < n then
FillChar(x[i + 1], n - i, '0');
end
else
Break;
until False;
end.
1.2.3. Liệt kê các tập con có phần tử
Ta s lt kê các tp con phn t ca tp theo th t t
Ví d: , có 10 tp con:
{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}
Bài toán lit kê các tp con phn t ca tp có th quy v bài toán lit kê các
dãy phn t
. Nu sp xp các dãy này theo th
t t n, ta nhn thy:
Tu tiên (cu hình khi to) là .
u hình kt thúc) là .
, ta có nhn xét rng gii hn
trên (giá tr ln nht có th nhn) ca
là n, ca
là , ca
là ng
quát: gii hn trên ca
.
Còn tt nhiên, gii ha
.
St c các phn t trong x t ti
gii hx u không thì ta phi sinh ra mt dãy mn
tho lk phn t nào chen
gia chúng khi sp th t t n.
Ví d: . C. Các phn t
t ti gii
h sinh cu hình mi ta không th sinh bt phn t trong
s
c, ta ph
c cu
hình mi
. Cu hình này l mãn
tính cht v ln. Mu
bng các gii hi cc là:
c cu hình mi
là cu hình k ti
li nhn thy rng
t gii hy ch c
.
Thu tip t
có th xây d
Tìm t cuu cho ti khi gp mt phn t
t gii hn trên
Nu tìm thy:
lên 1
t tt c các phn t
bng gii h
Nu không tìm thy tc là mi phn t t gii hu hình cui cùng
Input
Hai s
Output
Các tp con k phn t ca tp
Sample Input
Sample Output
5 3
{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}
SUBSETS_GEN.PAS Thut toán sinh lit kê các tp con
{$MODE OBJFPC}
program SubSetEnumeration;
const
max = 100;
var
x: array[1 max] of Integer;
n, k, i, j: Integer;
begin
ReadLn(n, k);
for i := 1 to k do x[i] := i;
repeat
Write('{');
for i := 1 to k do
begin
Write(x[i]);
if i < k then Write(', ');
end;
WriteLn('}');
k + i
i := k;
while (i > 0) and (x[i] = n - k + i) do Dec(i);
if i > 0 then
begin
Inc(x[i]);
for j := i + 1 to k do x[j] := x[j - 1] + 1;
end
else Break;
until False;
end.
1.2.4. Liệt kê các hoán vị
Ta s lt kê các hoán v ca tp
theo th t t n.
Ví d vi n = 3, có 6 hoán v:
Mi hoán v ca tp
có th biu dii dng mt mt dãy s
. Theo
th t t n, ta nhn thy:
Hoán v u tiên cn lit kê:
Hoán v cui cùng cn lit kê:
Bu t hoán v
, ta s sinh ra các hoán v còn li theo quy tc: Hoán v s sinh
ra phi là hoán v v l hin t có mt hoán v nào
khác chen gia chúng khi sp th t.
Gi s hoán v hin ti là
, xét 4 phn t cui cùng, ta thc
xp gim d 4 phn t này th
c mt hoán v hin ty ta phn
và thay nó
bng mt giá tr khác. Ta s thay bng giá tr nào?, không th là 1 bi nu vy s c
hoán v nh
ri (phn t c chn vào
nhng giá tr mà phn t n). Còn li các giá tr: 4, 5 và 6. Vì cn mt hoán v
v l n ti nên ta chn
. Còn các giá tr
s ly trong tp
ln nên ta s tìm biu din nh nht ca 4 s này gán cho
tc là
. Vy hoán v mi s là
.
Ta có nhn xét gì qua ví d này: n cui ca hoán v hin ti
c xp gim dn, s
là s nh nhn cui gim dn tho u kin l
. No
giá tr
và
thì ta s c hoán v
n cui
vc sp xp
gim dn. Kn biu din nh nht cho các giá tr n cui thì ta ch co
n cui.
ng hp hoán v hin ti là
thì hoán v k tip s là
th coi hoán v
n cui gim dn cui này ch gm 1 phn t (4)
Thut toán sinh hoán v k tip t hoán v hin ti có th xây d
n cui gim dn dài nht, tìm ch s ca phn t
ng lin cui
i vic tìm t v trí sát cuu, gp ch s u tiên tha
mãn
.
Nu tìm thy ch s
n cui gim dn, tìm phn t
nh nht v l
n
cui gim du này thc hin bng cách tìm t cuu gp ch s
u tiên tho mãn
(có th dùng tìm kim nh phân).
o giá tr
và
Lc th t n cui gim dn (
n cui tr n.
Nu không tìm thy tp gim du hình cui cùng
Input
S nguy
Output
Các hoán v ca dãy
Sample Input
Sample Output
3
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
PERMUTATIONS_GEN.PAS
{$MODE OBJFPC}
program PermutationEnumeration;
const
max = 100;
var
x: array[1 max] of Integer;
n, i, k, l, h: Integer;
//Th to giá tr hai tham bin x, y
procedure Swap(var x, y: Integer);
var
temp: Integer;
begin
temp := x; x := y; y := temp;
end;
begin
ReadLn(n);
for i := 1 to n do x[i] := i;
repeat
//In cu hình hin ti
Write('(');
for i := 1 to n do
begin
Write(x[i]);
if i < n then Write(', ');
end;
WriteLn(')');
//Sinh cu hình k tip
//Tìm i là ch s n cui gim dn
i := n - 1;
while (i > 0) and (x[i] > x[i + 1]) do Dec(i);
if i > 0 then
//Nu tìm thy
begin
//Tìm t cui dãy phn t u tiên (x[k]) l
k := n;
while x[k] < x[i] do Dec(k);
o giá tr x[k] và x[i]
Swap(x[k], x[i]);
//Lc th t n cui gim dn cui tr n
l := i + 1; h := n;
while l < h do
begin
Swap(x[l], x[h]);
Inc(l);
Dec(h);
end;
end
else Break;
//C dãy là gim dn, ht cu hình
until False;
end.
m c c cu hình th n
có cu hình th tính ph dng trong nhng thut
toán duyt hn ch na, không phi c c,
không phi k thut sinh cu hình k tip cho mn (Sinh các chnh hp
không lp chp theo th t t n chng hn). Ta sang mt chuyên mn mt
t kê có tính ph d gii các bài toán lit kê phc t
là: Thut toán quay lui (Back tracking).
1.3. Thuật toán quay lui
Thu gii bài toán lit kê các cu hình. Thut toán này làm vic theo
cách:
Mi cc xây dng bng cách xây dng tng phn t
Mi phn t c chn bng cách th tt c các kh
Gi s cu hình cn lit kê có dng
t toán quay lui s xét tt c các giá tr
có th nhn, th cho
nhn lt các giá tr i mi giá tr th gán cho
, thut toán
s xét tt c các giá tr
có th nhn, li th cho
nhn lt các giá tr i mi giá
tr th gán cho
li xét tip các kh n
, c tip tc
mt cu hình thì lit kê ngay c
Có th mô t thut toán quay lui theo cách quy np: Thut toán s lit kê các cu hình
phn t dng
bng cách th cho
nhn lt các giá tr có th. Vi mi giá tr th
gán cho
, thut toán tip tc lit kê toàn b các cu hình phn t
1.3.1. Mô hình quay lui
//Th tc này th cho x[i] nhn lt các giá tr mà nó có th nhn
procedure Attempt(i);
begin
for «mọi giá trị v có thể gán cho x[i]» do
begin
«Thử cho x[i] := v»;
if «x[i] là phần tử cuối cùng trong cấu hình» then
«Thông báo cấu hình tìm được»
else
begin
«Ghi nhận việc cho x[i] nhận giá trị V (nếu cần)»;
Attempt(i + 1);
//G chn tip x[i+1]
«Nếu cần, bỏ ghi nhận việc thử x[i] := V để thử giá trị khác»;
end;
end;
end;
Thut toán quay lui s bu bng li gi .
Tên gi thut toán quay lui là d duyt các cu hình: Mi khi th chn mt giá
tr cho
, thut toán s g tìm tip
y cho ti khi tin trình
duyt xét tìm ti phn t cui cùng ca ct tt c kh n
, tin trình s lùi li th t mt giá tr khác cho
.
1.3.2. Liệt kê các dãy nhị phân
Biu din dãy nh dài i dng dãy
. Ta s lit kê các dãy này bng cách th
dùng các giá tr
gán cho
. Vi mi giá tr th gán cho
li th các giá tr có th gán
cho
t kê các dãy nh phân vnh khuôn d
trong mc 1.2.2.
BINARYSTRINGS_BT.PAS
{$MODE OBJFPC}
program BinaryStringEnumeration;
var
x: AnsiString;
n: Integer;
procedure Attempt(i: Integer);
//Th các cách chn x[i]
var
j: AnsiChar;
begin
for j := '0' to '1' do
//Xét các giá tr j có th gán cho x[i]
begin
//Vi mi giá tr
x[i] := j;
//Th t x[i]
if i = n then WriteLn(x)
//Nu i = n thì in kt qu
else Attempt(i + 1);
//Ni phn t cui thì tìm tip x[i + 1]
end;
end;
begin
ReadLn(n);
SetLength(x, n);
Attempt(1);
//Khng thut toán quay lui
end.
Ví d: Khi , các li g quy thc hin thut toán quay lui có th v
Hình 1-1.
Hình 1-1. Cây tìm kim quay lui trong bài toán lit kê dãy nh phân
1.3.3. Liệt kê các tập con có phần tử
lit kê các tp con phn t ca tp ta có th lit kê các cu hình
,
.
Theo các nhn xét mc 1.2.3, giá tr ci và cn trên ca
là:
(1.1)
(Gi thit rng có thêm mt s
khi xét công thc (1.1) vi )
Thut toán quay lui s xét tt c các cách chn
t 1
n , vi mi giá
tr p tt c các cách chn
t
n y khi chc
n
thì ta có mt cu hình cn lit kê.
t kê các tp con phn t bng thut toán quay lui vi khuôn
dnh trong mc 1.2.3.
Attempt(3)
000
x
3
:=0
x
3
:=1
Attempt(3)
x
3
:=0
x
3
:=1
Attempt(2)
x
2
:=0
x
2
:=1
Attempt(3)
x
3
:=0
x
3
:=1
Attempt(3)
x
3
:=0
x
3
:=1
Attempt(2)
x
2
:=0
x
2
:=1
Attempt(1)
x
1
:=0
x
1
:=1
001
010
011
000
001
010
011
SUBSETS_BT.PAS Thut toán quay lui lit kê các tp con
{$MODE OBJFPC}
program SubSetEnumeration;
const
max = 100;
var
x: array[0 max] of Integer;
n, k: Integer;
procedure PrintResult;
//In ra tp con {x[1 k]}
var
i: Integer;
begin
Write('{');
for i := 1 to k do
begin
Write(x[i]);
if i < k then Write(', ');
end;
WriteLn('}');
end;
procedure Attempt(i: Integer);
//Th các cách chn giá tr cho x[i]
var
j: Integer;
begin
for j := x[i - 1] + 1 to n - k + i do
begin
x[i] := j;
if i = k then PrintResult
else Attempt(i + 1);
end;
end;
begin
ReadLn(n, k);
x[0] := 0;
Attempt(1);
//Khng thut toán quay lui
end.
V t thut toán quay lui ch khác nhau th tc . Ví
d t kê dãy nh phân, th tc này s th chn các giá tr 0 hoc 1 cho
;
còn t kê các tp con phn t, th tc này s th chn
là mt trong các
giá tr nguyên t ci
ti cn trên thy tính ph
dng ca thut có th thích hp cho nhiu bài toán.
pháp sinh tun t, vi mi bài toán li phi có mt thut toán sinh cu hình k ti
làm cho vit mi bài mt khác, bên ci thut toán sinh k tip nào
c.
1.3.4. Liệt kê các chỉnh hợp không lặp chập
lit kê các chnh hp không lp chp ca tp ta có th lit kê các
cu hình
, các
t.
Th tc
xét tt c các kh n
s th ht các giá tr t n n
b các phn t c
chn. Mun xem các giá tr nàc chn ta s dng
k thut dùng mu:
Khi to mt mng
mang kiu logic boolean.
cho bit giá tr
có còn t chn ru khi to tt c các phn t mng
là
t n n u t do.
Tc chn các giá tr có th ca
ta ch xét nhng giá tr còn t do (
.
c khi g quy
th chn tip
t giá tr va gán cho
ch (
các th tc
,
gi sau này không chn phi giá tr a.
Sau khi g quy
p ti ta s th gán mt giá tr khác cho
thì ta s t giá tr va th cho
), bi khi
nhn mt giá tr khác ri thì các phn t ng sau (
) hoàn toàn có th nhn li
giá tr
Tt nhiên ta ch cu/b u trong th tc
có
, bi khi thì tip theo ch có in kt qu ch không cn phi chn thêm phn
t nào na.
Input
Hai s
.
Output
Các chnh hp không lp chp ca tp
Sample Input
Sample Output
3 2
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(3, 1)
(3, 2)
ARRANGE_BT.PAS
{$MODE OBJFPC}
program ArrangementEnumeration;
const
max = 100;
var
x: array[1 max] of Integer;
Free: array[1 max] of Boolean;
n, k: Integer;
procedure PrintResult;
//Th tc in cc
var
i: Integer;
begin
Write('(');
for i := 1 to k do
begin
Write(x[i]);
if i < k then Write(', ');
end;
WriteLn(')');
end;
procedure Attempt(i: Integer);
//Th các cách chn x[i]
var
j: Integer;
begin
for j := 1 to n do
if Free[j] then
//Ch xét nhng giá tr j còn t do
begin
x[i] := j;
if i = k then PrintResult
//Nn x[k] thì in kt qu
else
begin
Free[j] := False;
chn
Attempt(i + 1);
//Attempt(i + 1) s ch xét nhng giá tr còn t do gán cho x[i+1]
Free[j] := True;
//B u, sp ti s th mt cách chn khác ca x[i]
end;
end;
end;
begin
ReadLn(n, k);
FillChar(Free[1], n, True);
Attempt(1);
//Khng thut toán quay lui
end.
Khi t kê hoán v.
1.3.5. Liệt kê các cách phân tích số
Cho mt s , hãy tìm tt c các cách phân tích s thành tng ca các s
ca nhau ch tính là 1 cách và ch c lit kê
mt ln.
Ta s dùng thu lit kê các nghim, mi nghing vi mt dãy ,
tránh s trùng lp khi lic: dãy phi có th
t không gim:
Thut bng th t quy
: th các giá tr có th nhn
ca
, mi khi th xong mt giá tr cho
, th tc s g quy
th các
giá tr có th cho
c mc th các giá tr cho
là tng
ca tt c các phn t c
:
và th giá min giá tr mà
có th nhn.
Rõ ràng giá tr nh nht mà
có th nhn chính là
vì dãy có th t không gim (Gi
s rng có thêm mt phn t
, phn t này không tham gia vào vic lit kê cu hình
mà ch hp thc hoá giá tr ci ca
)
Nu
i là phn t cui cùng, tc là s phi chn tip ít nht mt phn t
na mà vic chn thêm
không làm cho tt quá . Ta có:
(1.2)
Tc là nu
i phn t cui cùng (cn g quy chn tip
) thì giá tr ln nht
có th nhn là
u
là phn t cui cùng thì bt buc
phi bng
.
Vy thì th tc
s g quy
tìm tip khi mà giá tr
c
chn còn cho phép chn thêm mt phn t khác lc bng nó mà không làm tng
t quá :
c li, th tc này s in kt qu ngay nu
mang giá tr
bng s thiu ht ca tng phn t u so vi . Ví d n khi thì th
là vin
tip
c na.
Vi giá tr khi to và
, thut toán quay lui s c khng bng li gi
và hong theo cách sau:
Vi mi giá tr :
, th gán
, cp nht
quy tìm ti xong các giá tr có th cho
, bin c phc hi li
c khi th gán mt giá tr khác cho
.
Cui cùng gán
và in kt qu ra dãy
.
Input
S
Output
Các cách phân tích s .
Sample Input
Sample Output
6
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
NUMBERPARTITION_BT.PAS L
{$MODE OBJFPC}
program NumberPartitioning;
const
max = 100;
var
x: array[0 max] of Integer;
n, m: Integer;
procedure Init;
//Khi to
begin
m := 0;
x[0] := 1;
end;
procedure PrintResult(k: Integer);
//In kt qu ra dãy x[1 k]
var
i: Integer;
begin
Write(n, ' = ');
for i := 1 to k - 1 do Write(x[i], '+');
WriteLn(x[k]);
end;
procedure Attempt(i: Integer);
//Thut toán quay lui
var
j: Integer;
begin
for j := x[i - 1] to (n - m) div 2 do
ng hp còn chn tip x[i+1]
begin
x[i] := j;
//Th t x[i]
m := m + j;
//Cp nht tng m
Attempt(i + 1);
//Chn tip
m := m - j;
//Phc hi tng m
end;
x[i] := n - m;
//Nu x[i] là phn t cui thì nó bt buc phi là n-m
PrintResult(i);
//In kt qu
end;
begin
ReadLn(n);
Init;
Attempt(1);
//Khng thut toán quay lui
end.
Bây gi ta xét tip mt ví d kinh n ca thu
1.3.6. Bài toán xếp hậu
Xét bàn c tc . Mt quân hu trên bàn c có th c các quân
khác nm ti các ô cùng hàng, cùng ct hong chéo. Hãy tìm các xp quân hu
trên bàn c sao cho không quân n mt cách xp vi c ch ra
trong Hình 1-2.
Hình 1-2. Mt cách xp 8 quân hu lên bàn c
N các hàng t trên xui theo th t t 1 ti , các ct t trái qua phi theo
th t t 1 ti t quân hu lên bàn c, mi hàng phu (hu
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 hàng là quân hu . Vy mt nghim ca bài toán s c bit khi ta
c v trí ct ca nhng quân hu.
ng bàn c i), Bc (Trên). Mt
quân hu ô
(hàng , ct ) s khng ch.
Toàn b hàng
Toàn b ct
Toàn b các ô
th ng thc . Nhng ô này nm trên mt
c--TN).
Toàn b các ô
th ng thc . Nhng ô này nm trên mt
-Tây B-TB)
T nhng nh ng chéo trên bàn c.
Vi mi hng s . Tt c các ô
trên bàn c tha mãn nm
trên m-TN, g-TN mang ch s
Vi mi hng s . Tt c các ô
trên bàn c tha mãn
nm trên m-TB, g-TB mang ch
s
Hình 1-3. TN mang ch s TB mang ch s 0
Chúng ta s s dng ba m u:
Mng
.
nt còn t do,
nt mt quân
hu khng ch.
Mng
.
n-TN th còn t do,
nu
mt quân hu khng ch.
Mng
.
n-TB th còn t do,
nu
mt quân hu khng ch.
u c 3 mu mang giá tr u nào trên bàn c, các
cu t do)
Thut toán quay lui:
Xét tt c các ct, th t quân hu 1 vào mt ct, vi my, xét tt c các
t quân hu 2 không b quân hi th t và xét tit quân
hi khi n quân hu , ta in ra cách xp hu và d
Khi chn v trí ct cho quân hu th , ta phi chn ô
không b các quân ht
c là phi chn tha mãn: ct còn t do:
-TN
ch s còn t do:
-TB ch s còn t do;
.
Khi th c quân hu vào ô
, nu cui cùng () thì ta có
mt nghim. Nu không:
W
E
S
N
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
c khi g t quân hu th u cng
chéo b quân hu vt khng ch:
các ln g
quy tip sau cht các quân hu k tip s không chn vào nhng ô b quân
hu vt khng ch.
Sau khi g t quân hu th sp ti ta li th
mt khác cho quân hu , ta b u cng chéo va b quân
hu va th t khng ch
tc là c
li thành t do, bt quân hu sang v trí khác ri thì trên ct và 2
t mt quân hu khác
Hãy xem lt kê chnh hp không lp và hoán v v k thu
du. khác vi lit kê hoán v là: lit kê hoán v ch cn mt mu xem giá
tr có t do không, còn bài toán xp hu thì cn phu c 3 thành phn: Cng
ng hu lit
quân xe lên bàn c t kê hoán
v.
Input
S
Output
Mt các quân hu lên bàn c
Sample Input
Sample Output
8
(1, 1)
(2, 5)
(3, 8)
(4, 6)
(5, 3)
(6, 7)
(7, 2)
(8, 4)
NQUEENS_BT.PAS
{$MODE OBJFPC}
program NQueens;
const
max = 100;
var
n: Integer;
x: array[1 max] of Integer;
a: array[1 max] of Boolean;
b: array[2 2 * max] of Boolean;
c: array[1 - max max - 1] of Boolean;
Found: Boolean;
procedure PrintResult;
//In kt qu mi khi tìm ra nghim
var
i: Integer;
begin
for i := 1 to n do WriteLn('(', i, ', ', x[i], ') ');
Found := True;
end;
//Kim tra ô (i, j) còn t mt quân hu khng ch?
function IsFree(i, j: Integer): Boolean;
begin
Result := a[j] and b[i + j] and c[i - j];
end;
u / b u mt ô (i, j)
procedure SetFree(i, j: Integer; Enabled: Boolean);
begin
a[j] := Enabled;
b[i + j] := Enabled;
c[i - j] := Enabled;
end;
procedure Attempt(i: Integer);
//Th t quân hu i vào hàng i
var
j: Integer;
begin
for j := 1 to n do
//Xét tt c các ct
if IsFree(i, j) then
//Tìm v khng ch
begin
x[i] := j;
//Th t vào ô (i, j)
if i = n then
begin
PrintResult;
n con hu n thì in ra 1 nghim
Exit;
end
else
begin
SetFree(i, j, False);
u
Attempt(i + 1);
//Th t quân hu th i + 1
if Found then Exit;
SetFree(i, j, True);
//B u
end;
end;
end;
begin
ReadLn(n);
u tt c các cng chéo là t do
FillChar(a[1], n, True);
FillChar(b[2], 2 * n - 1, True);
FillChar(c[1 - n], 2 * n - 1, True);
Found := False;
Attempt(1);
//Khng thut toán quay lui
end.
Thut toán dùng mt bin làm c u
, thut toán quay lui s trình tìm kim.
Mt sai lm d mc phi là ch t lnh dng thut toán quay lui trong phép th
if i = n then
begin
PrintResult;
Exit;
end;
Ny lnh Exit ch có tác dng trong th tc
, mu mt
dây chuy quy, cn phi thoát lin mt lot các th t quy:
t lnh Exit vào sau li g quy chính là
t lnh Exit cho c mt dây chuy quy mi khi tìm ra nghim.
Mt s ng lp trình có lnh dng c n
chúng ta có th dùng lnh Halt thay cho lnh Exitu thut toán quay lui ch là mt
phc hin thut toán s còn phi làm nhiu vic khác na,
nh nu kin c c phép.
t dãy Exit là mt cách làm chính th quy.
1.4. Kỹ thuật nhánh cận
Có mt lp t ra trong thc t yêu cu tìm ra mt nghim tho mãn mt s u
ki tt nht theo mt ch tiêu c th p bài toán t
(optimization). Nghiên cu li gii các lp bài toán tc v c quy hoch toán
hn phi nói rng trong nhing hp chúng ta ch xây dng
mt thut toán nào thc s hu hi gii bài toán, mà cho ti nay vic tìm nghim ca
chúng vn phi da trên mô hình lit kê toàn b các cu hình có th u
hình tt nht. Vicó tên gi là vét cn (exhaustive
search). Chính nh k thut này cùng vi s phát trin cn t mà nhiu bài
y li gii.
Vic lit kê cu hình có th t bt kê: Sinh tun t và tìm kim
quay lui. tìm hiu k ca thu gii thiu mt
n ch không gian duyt.
Mô hình thut toán quay lui là tìm kim trên mt cây phân cp. Nu gi thit rng mi nút
nhánh ca cây ch cao s có ti
nút lá, con s này lt
nhiu ln so vc d liu vào . Chính vì vy mà na
trong vic chn
thì s phi tr giá rt ln v chi phí thc thi thut toán bi quá trình tìm
kim lòng vòng vc chn k tip
,
t v t ra
là trong quá trình lit kê li gii ta cn tn dng nh loi b sm
nhc chn không phi t. K thui là k thu nhánh
cn (Branch-and-bound) trong tin trình quay lui.
1.4.1. Mô hình kỹ thuật nhánh cận
Da trên mô hình thut toán quay lui, ta xây dng mô hình sau:
procedure Init;
begin
«Khởi tạo một cấu hình bất kỳ best»;
end;
//Th tc này th chn cho x[i] tt c các giá tr nó có th nhn
procedure Attempt(i: Integer);
begin
for «Mọi giá trị v có thể gán cho x[i]» do
begin
«Thử đặt x[i] := v»;
if «Còn hi vọng tìm ra cấu hình tốt hơn best» then
if «x[i] là phần tử cuối cùng trong cấu hình» then
«Cập nhật best»
else
begin
«Ghi nhận việc thử x[i] := v nếu cần»;
Attempt(i + 1);
//G quy, chn tip x[i + 1]
«Bỏ ghi nhận việc đã thử cho x[i] := v (nếu cần)»;
end;
end;
end;
begin
Init;
Attempt(1);
«Thông báo cấu hình tối ưu best»;
end.
K thut nhánh cn thêm vào cho thut toán quay lui kh c, nu
tc th , giá tr th gán cho
không có hi vng tìm thy cu hình tu hình
thì th giá tr khác ngay mà không cn phi g quy tìm tip hay ghi nhn kt qu
na. Nghim ca bài toán s c làm tt dn, bi khi tìm ra mt cu hình mi t,
ta s cp nht bng cu hình mi vc.
kho sát mt vài k thun qua các bài toán c th.
1.4.2. Đồ thị con đầy đủ cực đại
th ci (Clique) là mt bài toán có rt nhiu ng dng trong
các mng xã hi, tin sinh hc, mng truyn thông, nghiên cu cu trúc phân t
phát biu bài toán mt cách hình th i và mi có quen bit mt s
i khác. Gi s quan h quen bit là quan h hai chiu, tc là ni i
i i c li. V là hãy chn ra mt tp gm nhii
nht trong s i bt k c chn phi quen bit nhau.
t nhiu nghiên cu v i ta vc
thut toán v phc tc. Ta s trình bày mt cách gii bài toán Clique bng thut
toán quay lui kt hp vi k thut nhánh cn.
Mô hình duyệt
Các quan h c biu din bi ma trn
nu
i i và
ni i . Theo gi thit
ca bài toán, ma trn là ma tri xng:
().
Rõ ràng vi mi bt k thì có hai kh c chn hoi
c chn. Vì vy mt nghim ca bài toán có th biu din bi dãy
trong
ni th c chn và
ni th c chn.
Gi là s c chng vi dãy , tc là s v trí
.
bi mng
, vi là s c chn
ng vi dãy n, ta khi to mng
bi giá tr và
và bin s c thay bng nht
t. Trên thc t có th khi to bng mt thut
toán g
Mô hình duyc thit k t kê các dãy nh phân bng thut toán quay lui:
Th hai giá tr True/False cho
, vi mi giá tr va th cho
li th hai giá tr ca
Gi
là s i quen ci và
là s i quen ci
c chn. Giá tr
nh ngay t u còn giá tr
s c cp nht
ngay lp tc mi khi ta th quynh chn hay không chn mi quen vi ().
Mng
và
c s dng trong hàm c hn ch bt không gian
duyt.
Hàm cận
Thuc thc hi quy thông qua th tc
: Th hai giá tr có
th gán cho
. Dây chuy c b u t th tc
và khi th tc
c gn trên tp nhi t 1 ti
và s c chn trong tp này là .
Trong nhi t ti , chc chn nu có chn thêm thì ta ch c phép chn nhng
i mà
và
gii thích:
i không quen vi ít nht mn; còn
là ni c ch c chc chc không th có nhi
i, không t hin có.
Nh thit lp hàm cn: Khi th tc
c gi, ta lc ra nhng
i trong phm vi t ti có
và
và lp gi thuyt rng
ng hp tt nht, tt c nhi này s c chn thêm. Gi thuyt này cho
ng cn trên ca s c ch vào dãy các quy nh
u giá tr cn trên này vn , có th kt lun ngay rng
dãy quynh
không th dn t cho dù ta
có th ht nhng kh ng có th ca
. Th tc
s không tin hành th
gán giá tr cho
na mà thoát ngay, dây chuy quy lùi l i dãy quynh
.
Ngoài ra, th tc
không nht thit phi th hai giá tr True/False gán cho
.
N
hoc
thì ch cn th
, vì trong
ng hp này nu chi th s b t vi nhng quynh chc hoc
không còn ti.
Cài đặt
Ta s t bài toán Clique vi khuôn d
Input
Dòng 1 cha s i và s quan h quen bit cách nhau ít nht mt du
cách
dòng tip theo, mi dòng cha hai s nguyên cách nhau ít nht mt du cách cho
bit v mt quan hi quen nhau
Output
ng án chn ra nhii nh i bt k u quen nhau.
Sample Input
Sample Output
6 10
1 2
1 3
2 3
2 4
2 6
3 4
3 6
4 5
4 6
5 6
Number of guests: 4
Guests to be invited: 2, 3, 4, 6,
CLIQUE_BB.PAS
{$MODE OBJFPC}
program Clique;
const
maxN = 1000;
var
2
4
3
6
1
5