Tải bản đầy đủ (.pdf) (334 trang)

Cấu trúc dữ liệu và giải thuật - Lê Minh Hoàng pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (6.87 MB, 334 trang )


L
L
Ê
Ê


M
M
I
I
N
N
H
H


HOÀ
HOÀ
N
N
G
G













(A.K.A DSAP Textbook)









i hc S phm Hà Ni, 1999-2002












Try not to become a man of success
but rather to become a man of value.


Albert Einstein

 i 

MC LC
PHN 1. BÀI TOÁN LIT KÊ 1
§1. NHC LI MT S KIN THC I S T HP 2
1.1. CHNH HP LP 2
1.2. CHNH HP KHÔNG LP 2
1.3. HOÁN V 2
1.4. T HP 3
§2. PHNG PHÁP SINH (GENERATION) 4
2.1. SINH CÁC DÃY NH PHÂN  DÀI N 5
2.2. LIT KÊ CÁC TP CON K PHN T 6
2.3. LIT KÊ CÁC HOÁN V 8
§3. THUT TOÁN QUAY LUI 12
3.1. LIT KÊ CÁC DÃY NH PHÂN  DÀI N 12
3.2. LIT KÊ CÁC TP CON K PHN T 13
3.3. LIT KÊ CÁC CHNH HP KHÔNG LP CHP K 15
3.4. BÀI TOÁN PHÂN TÍCH S 17
3.5. BÀI TOÁN XP HU 19
§4. K THUT NHÁNH CN 24
4.1. BÀI TOÁN TI U 24
4.2. S BÙNG N T HP 24
4.3. MÔ HÌNH K THUT NHÁNH CN 24
4.4. BÀI TOÁN NGI DU LCH 25
4.5. DÃY ABC 27
PHN 2. CU TRÚC D LIU VÀ GII THUT 33
§1. CÁC BC C BN KHI TIN HÀNH GII CÁC BÀI TOÁN TIN HC 34
1.1. XÁC NH BÀI TOÁN 34

1.2. TÌM CU TRÚC D LIU BIU DIN BÀI TOÁN 34
1.3. TÌM THUT TOÁN 35
1.4. LP TRÌNH 37
1.5. KIM TH 37
1.6. TI U CHNG TRÌNH 38
§2. PHÂN TÍCH THI GIAN THC HIN GII THUT 40
2.1. GII THIU 40
2.2. CÁC KÝ PHÁP  ÁNH GIÁ  PHC TP TÍNH TOÁN 40
2.3. XÁC NH  PHC TP TÍNH TOÁN CA GII THUT 42
2.4.  PHC TP TÍNH TOÁN VI TÌNH TRNG D LIU VÀO 45
2.5. CHI PHÍ THC HIN THUT TOÁN 46
 ii 

§3.  QUY VÀ GII THUT  QUY 50
3.1. KHÁI NIM V  QUY 50
3.2. GII THUT  QUY 50
3.3. VÍ D V GII THUT  QUY 51
3.4. HIU LC CA  QUY 55
§4. CU TRÚC D LIU BIU DIN DANH SÁCH 58
4.1. KHÁI NIM DANH SÁCH 58
4.2. BIU DIN DANH SÁCH TRONG MÁY TÍNH 58
§5. NGN XP VÀ HÀNG I 64
5.1. NGN XP (STACK) 64
5.2. HÀNG I (QUEUE) 66
§6. CÂY (TREE) 70
6.1. NH NGHA 70
6.2. CÂY NH PHÂN (BINARY TREE) 71
6.3. BIU DIN CÂY NH PHÂN 73
6.4. PHÉP DUYT CÂY NH PHÂN 74
6.5. CÂY K_PHÂN 76

6.6. CÂY TNG QUÁT 77
§7. KÝ PHÁP TIN T, TRUNG T VÀ HU T 79
7.1. BIU THC DI DNG CÂY NH PHÂN 79
7.2. CÁC KÝ PHÁP CHO CÙNG MT BIU THC 79
7.3. CÁCH TÍNH GIÁ TR BIU THC 79
7.4. CHUYN T DNG TRUNG T SANG DNG HU T 83
7.5. XÂY DNG CÂY NH PHÂN BIU DIN BIU THC 86
§8. SP XP (SORTING) 88
8.1. BÀI TOÁN SP XP 88
8.2. THUT TOÁN SP XP KIU CHN (SELECTIONSORT) 90
8.3. THUT TOÁN SP XP NI BT (BUBBLESORT) 91
8.4. THUT TOÁN SP XP KIU CHÈN (INSERTIONSORT) 91
8.5. SP XP CHÈN VI  DÀI BC GIM DN (SHELLSORT) 93
8.6. THUT TOÁN SP XP KIU PHÂN ON (QUICKSORT) 94
8.7. THUT TOÁN SP XP KIU VUN NG (HEAPSORT) 101
8.8. SP XP BNG PHÉP M PHÂN PHI (DISTRIBUTION COUNTING) 104
8.9. TÍNH N NH CA THUT TOÁN SP XP (STABILITY) 105
8.10. THUT TOÁN SP XP BNG C S (RADIX SORT) 106
8.11. THUT TOÁN SP XP TRN (MERGESORT) 111
8.12. CÀI T 114
8.13. ÁNH GIÁ, NHN XÉT 122
§9. TÌM KIM (SEARCHING) 126
9.1. BÀI TOÁN TÌM KIM 126
9.2. TÌM KIM TUN T (SEQUENTIAL SEARCH) 126
9.3. TÌM KIM NH PHÂN (BINARY SEARCH) 126
9.4. CÂY NH PHÂN TÌM KIM (BINARY SEARCH TREE - BST) 127
 iii 

9.5. PHÉP BM (HASH) 132
9.6. KHOÁ S VI BÀI TOÁN TÌM KIM 132

9.7. CÂY TÌM KIM S HC (DIGITAL SEARCH TREE - DST) 133
9.8. CÂY TÌM KIM C S (RADIX SEARCH TREE - RST) 136
9.9. NHNG NHN XÉT CUI CÙNG 141
PHN 3. QUY HOCH NG 143
§1. CÔNG THC TRUY HI 144
1.1. VÍ D 144
1.2. CI TIN TH NHT 145
1.3. CI TIN TH HAI 147
1.4. CÀI T  QUY 147
§2. PHNG PHÁP QUY HOCH NG 149
2.1. BÀI TOÁN QUY HOCH 149
2.2. PHNG PHÁP QUY HOCH NG 149
§3. MT S BÀI TOÁN QUY HOCH NG 153
3.1. DÃY CON N IU TNG DÀI NHT 153
3.2. BÀI TOÁN CÁI TÚI 158
3.3. BIN I XÂU 160
3.4. DÃY CON CÓ TNG CHIA HT CHO K 164
3.5. PHÉP NHÂN T HP DÃY MA TRN 169
3.6. BÀI TP LUYN TP 172
PHN 4. CÁC THUT TOÁN TRÊN  TH 177
§1. CÁC KHÁI NIM C BN 178
1.1. NH NGHA  TH (GRAPH) 178
1.2. CÁC KHÁI NIM 179
§2. BIU DIN  TH TRÊN MÁY TÍNH 181
2.1. MA TRN K (ADJACENCY MATRIX) 181
2.2. DANH SÁCH CNH (EDGE LIST) 182
2.3. DANH SÁCH K (ADJACENCY LIST) 183
2.4. NHN XÉT 184
§3. CÁC THUT TOÁN TÌM KIM TRÊN  TH 186
3.1. BÀI TOÁN 186

3.2. THUT TOÁN TÌM KIM THEO CHIU SÂU (DEPTH FIRST SEARCH) 187
3.3. THUT TOÁN TÌM KIM THEO CHIU RNG (BREADTH FIRST SEARCH) 189
3.4.  PHC TP TÍNH TOÁN CA BFS VÀ DFS 192
§4. TÍNH LIÊN THÔNG CA  TH 193
4.1. NH NGHA 193
4.2. TÍNH LIÊN THÔNG TRONG  TH VÔ HNG 194
 iv 

4.3.  TH Y  VÀ THUT TOÁN WARSHALL 194
4.4. CÁC THÀNH PHN LIÊN THÔNG MNH 197
§5. VÀI NG DNG CA DFS và BFS 208
5.1. XÂY DNG CÂY KHUNG CA  TH 208
5.2. TP CÁC CHU TRÌNH C S CA  TH 211
5.3. BÀI TOÁN NH CHIU  TH 211
5.4. LIT KÊ CÁC KHP VÀ CU CA  TH 215
§6. CHU TRÌNH EULER, NG I EULER,  TH EULER 219
6.1. BÀI TOÁN 7 CÁI CU 219
6.2. NH NGHA 219
6.3. NH LÝ 219
6.4. THUT TOÁN FLEURY TÌM CHU TRÌNH EULER 220
6.5. CÀI T 221
6.6. THUT TOÁN TT HN 223
§7. CHU TRÌNH HAMILTON, NG I HAMILTON,  TH HAMILTON 226
7.1. NH NGHA 226
7.2. NH LÝ 226
7.3. CÀI T 227
§8. BÀI TOÁN NG I NGN NHT 231
8.1.  TH CÓ TRNG S 231
8.2. BÀI TOÁN NG I NGN NHT 231
8.3. TRNG HP  TH KHÔNG CÓ CHU TRÌNH ÂM - THUT TOÁN FORD BELLMAN 233

8.4. TRNG HP TRNG S TRÊN CÁC CUNG KHÔNG ÂM - THUT TOÁN DIJKSTRA 235
8.5. THUT TOÁN DIJKSTRA VÀ CU TRÚC HEAP 238
8.6. TRNG HP  TH KHÔNG CÓ CHU TRÌNH - SP XP TÔ PÔ 241
8.7. NG I NGN NHT GIA MI CP NH - THUT TOÁN FLOYD 244
8.8. NHN XÉT 246
§9. BÀI TOÁN CÂY KHUNG NH NHT 251
9.1. BÀI TOÁN CÂY KHUNG NH NHT 251
9.2. THUT TOÁN KRUSKAL (JOSEPH KRUSKAL - 1956) 251
9.3. THUT TOÁN PRIM (ROBERT PRIM - 1957) 256
§10. BÀI TOÁN LUNG CC I TRÊN MNG 260
10.1. CÁC KHÁI NIM 260
10.2. MNG THNG D VÀ NG TNG LUNG 263
10.3. THUT TOÁN FORD-FULKERSON (L.R.FORD & D.R.FULKERSON - 1962) 266
10.4. THUT TOÁN PREFLOW-PUSH (GOLDBERG - 1986) 270
10.5. MT S M RNG 276
§11. BÀI TOÁN TÌM B GHÉP CC I TRÊN  TH HAI PHÍA 283
11.1.  TH HAI PHÍA (BIPARTITE GRAPH) 283
11.2. BÀI TOÁN GHÉP ÔI KHÔNG TRNG VÀ CÁC KHÁI NIM 283
11.3. THUT TOÁN NG M 284
11.4. CÀI T 285
 v 

§12. BÀI TOÁN TÌM B GHÉP CC I VI TRNG S CC TIU TRÊN  TH HAI
PHÍA - THUT TOÁN HUNGARI 291
12.1. BÀI TOÁN PHÂN CÔNG 291
12.2. PHÂN TÍCH 291
12.3. THUT TOÁN 292
12.4. BÀI TOÁN TÌM B GHÉP CC I VI TRNG S CC I TRÊN  TH HAI PHÍA 301
12.5. NÂNG CP 301
§13. BÀI TOÁN TÌM B GHÉP CC I TRÊN  TH 307

13.1. CÁC KHÁI NIM 307
13.2. THUT TOÁN EDMONDS (1965) 308
13.3. THUT TOÁN LAWLER (1973) 310
13.4. CÀI T 312
13.5.  PHC TP TÍNH TOÁN 316
TÀI LIU C THÊM 319


 vi 

HÌNH V
Hình 1: Cây tìm kim quay lui trong bài toán lit kê dãy nh phân 13
Hình 2: Xp 8 quân hu trên bàn c 8x8 19
Hình 3: ng chéo B-TN mang ch s 10 và đng chéo N-TB mang ch s 0 20
Hình 4: Lu đ thut gii (Flowchart) 36
Hình 5: Ký pháp Θ ln, Ο ln và Ω ln 41
Hình 6: Tháp Hà Ni 54
Hình 7: Cu trúc nút ca danh sách ni đn 59
Hình 8: Danh sách ni đn 59
Hình 9: Cu trúc nút ca danh sách ni kép 61
Hình 10: Danh sách ni kép 61
Hình 11: Danh sách ni vòng mt hng 61
Hình 12: Danh sách ni vòng hai hng 62
Hình 13: Dùng danh sách vòng mô t Queue 67
Hình 14: Di chuyn toa tàu 69
Hình 15: Di chuyn toa tàu (2) 69
Hình 16: Cây 70
Hình 17: Mc ca các nút trên cây 71
Hình 18: Cây biu din biu thc 71
Hình 19: Các dng cây nh phân suy bin 72

Hình 20: Cây nh phân hoàn chnh và cây nh phân đy đ 72
Hình 21: ánh s các nút ca cây nh phân đy đ đ biu din bng mng 73
Hình 22: Nhc đim ca phng pháp biu din cây bng mng 73
Hình 23: Cu trúc nút ca cây nh phân 74
Hình 24: Biu din cây bng cu trúc liên kt 74
Hình 25: ánh s các nút ca cây 3_phân đ biu din bng mng 76
Hình 26: Biu din cây tng quát bng mng 77
Hình 27: Cu trúc nút ca cây tng quát 78
Hình 28: Biu thc di dng cây nh phân 79
Hình 29: Vòng lp trong ca QuickSort 95
Hình 30: Trng thái trc khi gi đ quy 96
Hình 31: Heap 102
Hình 32: Vun đng 102
Hình 33: o giá tr k[1] cho k[n] và xét phn còn li 103
Hình 34: Vun phn còn li thành đng ri li đo tr k[1] cho k[n-1] 103
Hình 35: ánh s các bit 106
Hình 36: Thut toán sp xp trn 111
 vii 

Hình 37: Máy Pentium 4, 3.2GHz, 2GB RAM t ra chm chp khi sp xp 10
8
khoá ∈ [0 7.10
7
] cho dù nhng
thut toán sp xp tt nht đã đc áp dng 123
Hình 38: Cây nh phân tìm kim 128
Hình 39: Xóa nút lá  cây BST 129
Hình 40. Xóa nút ch có mt nhánh con trên cây BST 130
Hình 41: Xóa nút có c hai nhánh con trên cây BST thay bng nút cc phi ca cây con trái 130
Hình 42: Xóa nút có c hai nhánh con trên cây BST thay bng nút cc trái ca cây con phi 130

Hình 43: ánh s các bit 133
Hình 44: Cây tìm kim s hc 133
Hình 45: Cây tìm kim c s 136
Hình 46: Vi đ dài dãy bit z = 3, cây tìm kim c s gm các khoá 2, 4, 5 và sau khi thêm giá tr 7 137
Hình 47: RST cha các khoá 2, 4, 5, 7 và RST sau khi loi b giá tr 7 138
Hình 48: Cây tìm kim c s a) và Trie tìm kim c s b) 140
Hình 49: Hàm đ quy tính s Fibonacci 151
Hình 50: Tính toán và truy vt 154
Hình 51: Truy vt 163
Hình 52: Ví d v mô hình đ th 178
Hình 53: Phân loi đ th 179
Hình 54 182
Hình 55 183
Hình 56:  th và đng đi 186
Hình 57: Cây DFS 189
Hình 58: Cây BFS 192
Hình 59:  th G và các thành phn liên thông G1, G2, G3 ca nó 193
Hình 60: Khp và cu 193
Hình 61: Liên thông mnh và liên thông yu 194
Hình 62:  th đy đ 195
Hình 63: n đ th vô hng và bao đóng ca nó 195
Hình 64: Ba dng cung ngoài cây DFS 199
Hình 65: Thut toán Tarjan “b” cây DFS 201
Hình 66: ánh s li, đo chiu các cung và duyt BFS vi cách chn các đnh xut phát ngc li vi th t
duyt xong (th t 11, 10… 3, 2, 1) 206
Hình 67:  th G và mt s ví d cây khung T1, T2, T3 ca nó 210
Hình 68: Cây khung DFS (a) và cây khung BFS (b) (Mi tên ch chiu đi thm các đnh) 210
Hình 69: Phép đnh chiu DFS 213
Hình 70: Phép đánh s và ghi nhn cung ngc lên cao nht 215
Hình 71: Mô hình đ th ca bài toán by cái cu 219

Hình 72 220
Hình 73 220
Hình 74 226
 viii 

Hình 75: Phép đánh li ch s theo th t tôpô 241
Hình 76: Hai cây gc r
1
và r
2
và cây mi khi hp nht chúng 252
Hình 77: Mng vi các kh nng thông qua (1 phát, 6 thu) và mt lung ca nó vi giá tr 7 260
Hình 78: Mng G và mng thng d G
f
tng ng (ký hiu f[u,v]:c[u,v] ch lung f[u, v] và kh nng thông qua
c[u, v] trên cung (u, v)) 264
Hình 79: Mng thng d và đng tng lung 265
Hình 80: Lung trên mng G trc và sau khi tng 265
Hình 81: Mng gi ca mng có nhiu đim phát và nhiu đim thu 276
Hình 82: Thay mt đnh u bng hai đnh u
in
, u
out
277
Hình 83: Mng gi ca mng có kh nng thông qua ca các cung b chn hai phía 277
Hình 84:  th hai phía 283
Hình 85:  th hai phía và b ghép M 284
Hình 86: Mô hình lung ca bài toán tìm b ghép cc đi trên đ th hai phía 288
Hình 87: Phép xoay trng s cnh 292
Hình 88: Thut toán Hungari 295

Hình 89: Cây pha “mc” ln hn sau mi ln xoay trng s cnh và tìm đng 302
Hình 90:  th G và mt b ghép M 307
Hình 91: Phép chp Blossom 309
Hình 92: N Blossom đ dò đng xuyên qua Blossom 309

 ix 

CHNG TRÌNH
P_1_02_1.PAS * Thut toán sinh lit kê các dãy nh phân đ dài n 6
P_1_02_2.PAS * Thut toán sinh lit kê các tp con k phn t 8
P_1_02_3.PAS * Thut toán sinh lit kê hoán v 9
P_1_03_1.PAS * Thut toán quay lui lit kê các dãy nh phân đ dài n 12
P_1_03_2.PAS * Thut toán quay lui lit kê các tp con k phn t 14
P_1_03_3.PAS * Thut toán quay lui lit kê các chnh hp không lp chp k 16
P_1_03_4.PAS * Thut toán quay lui lit kê các cách phân tích s 18
P_1_03_5.PAS * Thut toán quay lui gii bài toán xp hu 21
P_1_04_1.PAS * K thut nhánh cn dùng cho bài toán ngi du lch 26
P_1_04_2.PAS * Dãy ABC 28
P_2_07_1.PAS * Tính giá tr biu thc RPN 81
P_2_07_2.PAS * Chuyn biu thc trung t sang dng RPN 84
P_2_08_1.PAS * Các thut toán sp xp 114
P_3_01_1.PAS * m s cách phân tích s n 145
P_3_01_2.PAS * m s cách phân tích s n 146
P_3_01_3.PAS * m s cách phân tích s n 146
P_3_01_4.PAS * m s cách phân tích s n 147
P_3_01_5.PAS * m s cách phân tích s n dùng đ quy 147
P_3_01_6.PAS * m s cách phân tích s n dùng đ quy 148
P_3_03_1.PAS * Tìm dãy con đn điu tng dài nht 154
P_3_03_2.PAS * Ci tin thut toán tìm dãy con đn điu tng dài nht 156
P_3_03_3.PAS * Bài toán cái túi 159

P_3_03_4.PAS * Bin đi xâu 163
P_3_03_5.PAS * Dãy con có tng chia ht cho k 165
P_3_03_6.PAS * Dãy con có tng chia ht cho k 167
P_3_03_7.PAS * Nhân ti u dãy ma trn 171
P_4_03_1.PAS * Thut toán tìm kim theo chiu sâu 187
P_4_03_2.PAS * Thut toán tìm kim theo chiu rng 190
P_4_04_1.PAS * Thut toán Warshall lit kê các thành phn liên thông 197
P_4_04_2.PAS * Thut toán Tarjan lit kê các thành phn liên thông mnh 204
P_4_05_1.PAS * Lit kê các khp và cu ca đ th 216
P_4_06_1.PAS * Thut toán Fleury tìm chu trình Euler 221
P_4_06_2.PAS * Thut toán hiu qu tìm chu trình Euler 224
P_4_07_1.PAS * Thut toán quay lui lit kê chu trình Hamilton 227
P_4_08_1.PAS * Thut toán Ford-Bellman 234
P_4_08_2.PAS * Thut toán Dijkstra 236
P_4_08_3.PAS * Thut toán Dijkstra và cu trúc Heap 239
 x 

P_4_08_4.PAS * ng đi ngn nht trên đ th không có chu trình 242
P_4_08_5.PAS * Thut toán Floyd 245
P_4_09_1.PAS * Thut toán Kruskal 253
P_4_09_2.PAS * Thut toán Prim 257
P_4_10_1.PAS * Thut toán Ford-Fulkerson 268
P_4_10_2.PAS * Thut toán Preflow-push 273
P_4_11_1.PAS * Thut toán đng m tìm b ghép cc đi 286
P_4_12_1.PAS * Thut toán Hungari 298
P_4_12_2.PAS * Cài đt phng pháp Kuhn-Munkres O(k
3
) 303
P_4_13_1.PAS * Phng pháp Lawler áp dng cho thut toán Edmonds 313




BNG CÁC KÝ HIU C S DNG

x
⎢⎥
⎣⎦

Floor of x: S nguyên ln nht ≤ x
x
⎡⎤
⎢⎥

Ceiling of x: S nguyên nh nht ≥ x
nk
P
S chnh hp không lp chp k ca n phn t =
n!
(n k)!−

n
k
⎛⎞
⎜⎟
⎝⎠

Binomial coefficient: H s ca hng t
k
x trong đa thc
()

n
x1+
= S t hp chp k ca n phn t =
()
n!
k! n k !−

()
O.

Ký pháp ch O ln
()

Ký pháp Θ ln
()
.Ω
Ký pháp Ω ln
()
o.
Ký pháp ch o nh
()

ký pháp ω nh
[
]
ai j
Các phn t trong mng a tính t ch s i đn ch s j
n!
n factorial: Giai tha ca n = 1.2.3…n
ab↑

b
a
ab↑↑
m
a

a
b
copies of a
a
a
log x
Logarithm to base a of x: Logarithm c s a ca x (
b
a
log a b
=
)
lg x

Logarithm nh phân (c s 2) ca x
ln x
Logarithm t nhiên (c s e) ca x
*
a
log x S ln ly logarithm c s a đ thu đc s ≤ 1 t x (
*
a
log (a b) b↑↑ = )
*

lg x
*
2
log x
*
ln x
*
e
log x



P
P
H
H


N
N


1
1
.
.


B
B

À
À
I
I


T
T
O
O
Á
Á
N
N


L
L
I
I


T
T


K
K
Ê
Ê



Có mt s bài toán trên thc t yêu cu ch rõ: trong mt tp các đi
tng cho trc có bao nhiêu đi tng tho mãn nhng điu kin nht
đnh. Bài toán đó gi là bài toán đm.
Trong lp các bài toán đm, có nhng bài toán còn yêu cu ch rõ nhng
cu hình tìm đc tho mãn điu kin đã cho là nhng cu hình nào. Bài
toán yêu cu đa ra danh sách các cu hình có th có gi là bài toán lit
kê.
 gii bài toán lit kê, cn phi xác đnh đc mt thut toán đ có th
theo đó ln lt xây dng đc tt c các cu hình đang quan tâm. Có
nhiu phng pháp lit kê, nhng chúng cn phi đáp ng đc hai yêu
cu di đây:
• Không đc lp li mt cu hình
• Không đc b sót mt cu hình
Có th nói rng, phng pháp lit kê là phng k cui cùng đ gii
đc mt s bài toán t hp hin nay. Khó khn chính ca phng pháp
này chính là s bùng n t hp dn ti s đòi hi ln v không gian và
thi gian thc hin chng trình. Tuy nhiên cùng vi s phát trin ca
máy tính đin t, bng phng pháp lit kê, nhiu bài toán t hp đã tìm
thy li gii. Qua đó, ta cng nên bit rng ch nên dùng phng pháp
lit kê khi không còn mt phng pháp nào khác tìm ra li gii.
Chính nhng n lc gii quyt các bài toán thc t không dùng phng
pháp lit kê đã thúc đy s phát trin ca nhiu ngành toán hc.

 2  Chuyên đ

HSPHN 1999-2004
§1.


NHC LI MT S KIN THC I S T HP
Cho S là mt tp hu hn gm n phn t và k là mt s t nhiên.
Gi X là tp các s nguyên dng t 1 đn k: X = {1, 2, …, k}
1.1.

CHNH HP LP
Mi ánh x f: X → S. Cho tng ng vi mi i ∈ X, mt và ch mt phn t f(i) ∈ S.
c gi là mt chnh hp lp chp k ca S.
Nhng do X là tp hu hn (k phn t) nên ánh x f có th xác đnh qua bng các giá tr f(1),
f(2), …, f(k).
Ví d: S = {A, B, C, D, E, F}; k = 3. Mt ánh x f có th cho nh sau:
i 1 2 3
f(i) E C E
Vy có th đng nht f vi dãy giá tr (f(1), f(2), …, f(k)) và coi dãy giá tr này cng là mt
chnh hp lp chp k ca S. Nh ví d trên (E, C, E) là mt chnh hp lp chp 3 ca S. D
dàng chng minh đc kt qu sau bng quy np hoc bng phng pháp đánh giá kh nng
la chn:
S chnh hp lp chp k ca tp gm n phn t là
k
n
1.2.

CHNH HP KHÔNG LP
Khi f là đn ánh có ngha là vi ∀i, j ∈ X ta có f(i) = f(j) ⇔ i = j. Nói mt cách d hiu, khi
dãy giá tr f(1), f(2), …, f(k) gm các phn t thuc S khác nhau đôi mt thì f đc gi là mt
chnh hp không lp chp k ca S. Ví d mt chnh hp không lp (C, A, E):
i 1 2 3
f(i) C A E
S chnh hp không lp chp k ca tp gm n phn t là:
nk

n!
P n(n 1)(n 2) (n k 1)
(n k)!
=−− −+=


1.3.

HOÁN V
Khi k = n. Mt chnh hp không lp chp n ca S đc gi là mt hoán v các phn t ca S.
Ví d: mt hoán v: 〈A, D, C, E, B, F〉 ca S = {A, B, C, D, E, F}
i 1 2 3 4 5 6
f(i) A D C E B F
Bài toán lit kê  3 

Lê Minh Hoàng
 ý rng khi k = n thì s phn t ca tp X = {1, 2, …, n} đúng bng s phn t ca S. Do
tính cht đôi mt khác nhau nên dãy f(1), f(2), …, f(n) s lit kê đc ht các phn t trong S.
Nh vy f là toàn ánh. Mt khác do gi thit f là chnh hp không lp nên f là đn ánh. Ta có
tng ng 1-1 gia các phn t ca X và S, do đó f là song ánh. Vy nên ta có th đnh ngha
mt hoán v ca S là mt song ánh gia {1, 2, …, n} và S.
S hoán v ca tp gm n phn t = s chnh hp không lp chp n = n!
1.4.

T HP
Mt tp con gm k phn t ca S đc gi là mt t hp chp k ca S.
Ly mt tp con k phn t ca S, xét tt c k! hoán v ca tp con này. D thy rng các hoán
v đó là các chnh hp không lp chp k ca S. Ví d ly tp {A, B, C} là tp con ca tp S
trong ví d trên thì: 〈A, B, C〉, 〈C, A, B〉, 〈B, C, A〉, … là các chnh hp không lp chp 3 ca
S. iu đó tc là khi lit kê tt c các chnh hp không lp chp k thì mi t hp chp k s

đc tính k! ln. Vy s t hp chp k ca tp gm n phn t là
n
n!
k
k!(n k)!
⎛⎞
=
⎜⎟

⎝⎠

 4  Chuyên đ

HSPHN 1999-2004
§2.

PHNG PHÁP SINH (GENERATION)
Phng pháp sinh có th áp dng đ gii bài toán lit kê t hp đt ra nu nh hai điu kin
sau tho mãn:
 Có th xác đnh đc mt th t trên tp các cu hình t hp cn lit kê. T đó có th bit
đccu hình đu tiên và cu hình cui cùng trong th t đó.
 Xây dng đc thut toán t mt cu hình cha phi cu hình cui, sinh ra đc cu hình
k tip nó.
Phng pháp sinh có th mô t nh sau:
〈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〉;
Th t t đin
Trên các kiu d liu đn gin chun, ngi ta thng nói ti khái nim th t. Ví d trên
kiu s thì có quan h: 1 < 2; 2 < 3; 3 < 10; …, trên kiu ký t Char thì cng có quan h 'A' <
'B'; 'C' < 'c'…
Xét quan h th t toàn phn “nh hn hoc bng” ký hiu “≤“ trên mt tp hp S, là quan h
hai ngôi tho mãn bn tính cht:
Vi ∀a, b, c ∈ S
 Tính ph bin: Hoc là a ≤ b, hoc b ≤ a;
 Tính phn x: a ≤ a
 Tính phn đi xng: Nu a ≤ b và b ≤ a thì bt buc a = b.
 Tính bc cu: Nu có a ≤ b và b ≤ c thì a ≤ c.
Trong trng hp a ≤ b và a ≠ b, ta dùng ký hiu “<” cho gn, (ta ngm hiu các ký hiu nh
≥, >, khi phi đnh ngha)
Ví d nh quan h “≤” trên các s nguyên cng nh trên các kiu vô hng, lit kê là quan h
th t toàn phn.
Trên các dãy hu hn, ngi ta cng xác đnh mt quan h th t:
Xét a[1 n] và b[1 n] là hai dãy đ dài n, trên các phn t ca a và b đã có quan h th t “≤”.
Khi đó a ≤ b nu nh
Hoc a[i] = b[i] vi ∀i: 1 ≤ i ≤ n.
Hoc tn ti mt s nguyên dng k: 1 ≤ k < n đ:
a[1] = b[1]
a[2] = b[2]
Bài toán lit kê  5 

Lê Minh Hoàng

a[k-1] = b[k-1]
a[k] = b[k]

a[k+1] < b[k+1]
Trong trng hp này, ta có th vit a < b.
Th t đó gi là th t t đin trên các dãy đ dài n.
Khi đ dài hai dãy a và b không bng nhau, ngi ta cng xác đnh đc th t t đin. Bng
cách thêm vào cui dãy a hoc dãy b nhng phn t đc bit gi là phn t ∅ đ đ dài ca a
và b bng nhau, và coi nhng phn t ∅ này nh hn tt c các phn t khác, ta li đa v xác
đnh th t t đin ca hai dãy cùng đ dài. Ví d:
〈1, 2, 3, 4〉 < 〈5, 6〉
〈a, b, c〉 < 〈a, b, c, d〉
'calculator' < 'computer'
2.1.

SINH CÁC DÃY NH PHÂN  DÀI N
Mt dãy nh phân đ dài n là mt dãy x[1 n] trong đó x[i] ∈ {0, 1} (∀i : 1 ≤ i ≤ n).
D thy: mt dãy nh phân x đ dài n là biu din nh phân ca mt giá tr nguyên p(x) nào đó
nm trong đon [0, 2
n
- 1]. S các dãy nh phân đ dài n = s các s t nhiên ∈ [0, 2
n
- 1] = 2
n
.
Ta s lp chng trình lit kê các dãy nh phân theo th t t đin có ngha là s lit kê ln
lt các dãy nh phân biu din các s nguyên theo th t 0, 1, …, 2
n
-1.
Ví d: Khi n = 3, các dãy nh phân đ dài 3 đc lit kê nh sau:
p(x) 0 1 2 3 4 5 6 7
x 000 001 010 011 100 101 110 111
Nh vy dãy đu tiên s là 00…0 và dãy cui cùng s là 11…1. Nhn xét rng nu dãy x =

x[1 n] là dãy đang có và không phi dãy cui cùng cn lit kê thì dãy k tip s nhn đc
bng cách cng thêm 1 ( theo c s 2 có nh) vào dãy hin ti.
Ví d khi n = 8:
Dãy đang có: 10010000 Dãy đang có: 10010111
cng thêm 1: + 1 cng thêm 1: + 1

⎯⎯⎯⎯

⎯⎯⎯⎯
Dãy mi: 10010001 Dãy mi: 10011000

Nh vy k thut sinh cu hình k tip t cu hình hin ti có th mô t nh sau: Xét t cui
dãy v đu (xét t hàng đn v lên), tìm s 0 gp đu tiên
 6  Chuyên đ

HSPHN 1999-2004
 Nu thy thì thay s 0 đó bng s 1 và đt tt c các phn t phía sau v trí đó bng 0.
 Nu không thy thì thì toàn dãy là s 1, đây là cu hình cui cùng
D liu vào (Input): nhp t file vn bn BSTR.INP cha s nguyên dng n ≤ 100
Kt qu ra (Output): ghi ra file vn bn BSTR.OUT các dãy nh phân đ dài n.
BSTR.INP
3

BSTR.OUT
000
001
010
011
100
101

110
111

P_1_02_1.PAS * Thut toán sinh lit kê các dãy nh phân đ dài n
{$MODE DELPHI} (*This program uses 32-bit Integer [-2
31
2
31
- 1]*)
program Binary_Strings;
const
InputFile = 'BSTR.INP';
OutputFile = 'BSTR.OUT';
max = 100;
var
x: array[1 max] of Integer;
n, i: Integer;
f: Text;
begin
Assign(f, InputFile); Reset(f);
ReadLn(f, n);
Close(f);
Assign(f, OutputFile); Rewrite(f);
FillChar(x, SizeOf(x), 0); {Cu hình ban đu x=00 0}
repeat {Thut toán sinh}
for i := 1 to n do Write(f, x[i]); {In ra cu hình hin ti}
WriteLn(f);
i := n; {x[i] là phn t cui dãy, lùi dn i cho ti khi gp s 0 hoc khi i = 0 thì dng}
while (i > 0) and (x[i] = 1) do Dec(i);
if i > 0 then {Cha gp phi cu hình 11…1}

begin
x[i] := 1; {Thay x[i] bng s 1}
FillChar(x[i + 1], (n - i) * SizeOf(x[1]), 0); {t x[i+1] = x[i+2] = … = x[n] := 0}
end;
until i = 0; {ã ht cu hình}
Close(f);
end.
2.2.

LIT KÊ CÁC TP CON K PHN T
Ta s lp chng trình lit kê các tp con k phn t ca tp {1, 2, …, n} theo th t t đin
Ví d: vi n = 5, k = 3, ta phi lit kê đ 10 tp 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 vy tp con đu tiên (cu hình khi to) là {1, 2, …, k}.
Cu hình kt thúc là {n - k + 1, n - k + 2, …, n}.
Nhn xét: Ta s in ra tp con bng cách in ra ln lt các phn t ca nó theo th t tng dn.
Biu din mi tp con là mt dãy x[1 k] trong đó x[1] < x[2] < … < x[k]. Ta nhn thy gii
Bài toán lit kê  7 

Lê Minh Hoàng
hn trên (giá tr ln nht có th nhn) ca x[k] là n, ca x[k-1] là n - 1, ca x[k-2] là n - 2…
Tng quát: gii hn trên ca x[i] = n - k + i;
Còn tt nhiên, gii hn di ca x[i] (giá tr nh nht x[i] có th nhn) là x[i-1] + 1.
Nh vy nu ta đang có mt dãy x đi din cho mt tp con, nu x là cu hình kt thúc có
ngha là tt c các phn t trong x đu đã đt ti gii hn trên thì quá trình sinh kt thúc, nu
không thì ta phi sinh ra mt dãy x mi tng dn tho mãn va đ ln hn dãy c theo ngha
không có mt tp con k phn t nào chen gia chúng khi sp th t t đin.
Ví d: n = 9, k = 6. Cu hình đang có x = 〈1, 2, 6, 7, 8, 9
〉. Các phn t x[3] đn x[6] đã đt ti

gii hn trên nên đ sinh cu hình mi ta không th sinh bng cách tng mt phn t trong s
các x[6], x[5], x[4], x[3] lên đc, ta phi tng x[2] = 2 lên thành x[2] = 3. c cu hình mi
là x = 〈1, 3, 6, 7, 8, 9〉. Cu hình này đã tho mãn ln hn cu hình trc nhng cha tho
mãn tính cht va đ ln mun vy ta li thay x[3], x[4], x[5], x[6] bng các gii hn di
ca nó. Tc là:
x[3] := x[2] + 1 = 4
x[4] := x[3] + 1 = 5
x[5] := x[4] + 1 = 6
x[6] := x[5] + 1 = 7
Ta đc cu hình mi x = 〈1, 3, 4, 5, 6, 7
〉 là cu hình k tip. Nu mun tìm tip, ta li nhn
thy rng x[6] = 7 cha đt gii hn trên, nh vy ch cn tng x[6] lên 1 là đc x = 〈1, 3, 4,
5, 6, 8〉.
Vy k thut sinh tp con k tip t tp đã có x có th xây dng nh sau:
Tìm t cui dãy lên đu cho ti khi gp mt phn t x[i] cha đt gii hn trên n - k + i.
 Nu tìm thy:
Tng x[i] đó lên 1.
t tt c các phn t phía sau x[i] bng gii hn di.
 Nu không tìm thy tc là mi phn t đã đt gii hn trên, đây là cu hình cui cùng
Input: file vn bn SUBSET.INP cha hai s nguyên dng n, k (1 ≤ k ≤ n ≤ 100) cách nhau
ít nht mt du cách
Output: file vn bn SUBSET.OUT các tp con k phn t ca tp {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}

 8  Chuyên đ

HSPHN 1999-2004
P_1_02_2.PAS * Thut toán sinh lit kê các tp con k phn t
{$MODE DELPHI} (*This program uses 32-bit Integer [-2
31
2
31
- 1]*)
program Combination;
const
InputFile = 'SUBSET.INP';
OutputFile = 'SUBSET.OUT';
max = 100;
var
x: array[1 max] of Integer;
n, k, i, j: Integer;
f: Text;
begin
Assign(f, InputFile); Reset(f);
ReadLn(f, n, k);
Close(f);
Assign(f, OutputFile); Rewrite(f);

for i := 1 to k do x[i] := i; {Khi to x := (1, 2, …, k)}
repeat
{In ra cu hình hin ti}
Write(f, '{');
for i := 1 to k - 1 do Write(f, x[i], ', ');
WriteLn(f, x[k], '}');
{Sinh tip}
i := k; {Xét t cui dãy lên tìm x[i] cha đt gii hn trên n - k + i}
while (i > 0) and (x[i] = n - k + i) do Dec(i);
if i > 0 then {Nu cha lùi đn 0 có ngha là cha phi cu hình kt thúc}
begin
Inc(x[i]); {Tng x[i] lên 1, t các phn t đng sau x[i] bng gii hn di ca nó}
for j := i + 1 to k do x[j] := x[j - 1] + 1;
end;
until i = 0; {Lùi đn tn 0 có ngha là tt c các ph
n t đã đt gii hn trên - ht cu hình}
Close(f);
end.
2.3.

LIT KÊ CÁC HOÁN V
Ta s lp chng trình lit kê các hoán v ca {1, 2, …, n} theo th t t đin.
Ví d vi n = 4, ta phi lit kê đ 24 hoán v:
1.1234 2.1243 3.1324 4.1342 5.1423 6.1432
7.2134 8.2143 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 vy hoán v đu tiên s là 〈1, 2, …, n〉. Hoán v cui cùng là 〈n, n-1, …, 1〉.
Hoán v s sinh ra phi ln hn hoán v hin ti, hn th na phi là hoán v va đ ln hn
hoán v hin ti theo ngha không th có mt hoán v nào khác chen gia chúng khi sp th t.

Gi s hoán v hin ti là x = 〈3, 2, 6, 5, 4, 1
〉, xét 4 phn t cui cùng, ta thy chúng đc xp
gim dn, điu đó có ngha là cho dù ta có hoán v 4 phn t này th nào, ta cng đc mt
hoán v bé hn hoán v hin ti. Nh vy ta phi xét đn x[2] = 2, thay nó bng mt giá tr
khác. Ta s thay bng giá tr nào?, không th là 1 bi nu vy s đc hoán v nh hn, không
th là 3 vì đã có x[1] = 3 ri (phn t sau không đc chn vào nhng giá tr mà phn t trc
đã chn). Còn li các giá tr 4, 5, 6. Vì cn mt hoán v va đ ln hn hin ti nên ta chn
x[2] = 4. Còn các giá tr (x[3], x[4], x[5], x[6]) s ly trong tp {2, 6, 5, 1}. Cng vì tính va
Bài toán lit kê  9 

Lê Minh Hoàng
đ ln nên ta s tìm biu din nh nht ca 4 s này gán cho x[3], x[4], x[5], x[6] tc là 〈1, 2,
5, 6〉. Vy hoán v mi s là 〈3, 4, 1, 2, 5, 6〉.
Ta có nhn xét gì qua ví d này: on cui ca hoán v hin ti đc xp gim dn, s x[5] =
4 là s nh nht trong đon cui gim dn tho mãn điu kin ln hn x[2] = 2. Nu đi ch
x[5] cho x[2] thì ta s đc x[2] = 4 và đon cui vn đc sp xp gim dn. Khi đó mun
biu din nh nht cho các giá tr trong đon cui thì ta ch cn đo ngc đon cui.
Trong trng hp hoán v hin ti là 〈2, 1, 3, 4〉 thì hoán v k tip s là 〈2, 1, 4, 3〉. Ta cng
có th coi hoán v 〈2, 1, 3, 4〉 có đon cui gim dn, đon cui này ch gm 1 phn t (4)
Vy k thut sinh hoán v k tip t hoán v hin ti có th xây dng nh sau:
Xác đnh đon cui gim dn dài nht, tìm ch s i ca phn t x[i] đng lin trc đon cui
đó. iu này đng ngha vi vic tìm t v trí sát cui dãy lên đu, gp ch s i đu tiên tha
mãn x[i] < x[i+1].
 Nu tìm thy ch s i nh trên
Trong đon cui gim dn, tìm phn t x[k] nh nht tho mãn điu kin x[k] > x[i]. Do
đon cui gim dn, điu này thc hin bng cách tìm t cui dãy lên đu gp ch s k
đu tiên tho mãn x[k] > x[i] (có th dùng tìm kim nh phân).
o giá tr x[k] và x[i]
Lt ngc th t đon cui gim dn (t x[i+1] đn x[k]) tr thành tng dn.
 Nu không tìm thy tc là toàn dãy đã sp gim dn, đây là cu hình cui cùng

Input: file vn bn PERMUTE.INP cha s nguyên dng n ≤ 100
Output: file vn bn PERMUTE.OUT các hoán v ca 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

P_1_02_3.PAS * Thut toán sinh lit kê hoán v
{$MODE DELPHI} (*This program uses 32-bit Integer [-2
31
2
31
- 1]*)
program Permutation;
const
InputFile = 'PERMUTE.INP';
OutputFile = 'PERMUTE.OUT';
max = 100;
var
n, i, k, a, b: Integer;
x: array[1 max] of Integer;
f: Text;

procedure Swap(var X, Y: Integer); {Th tc đo giá tr hai tham bin X, Y}

var
Temp: Integer;
begin
Temp := X; X := Y; Y := Temp;
end;
 10  Chuyên đ

HSPHN 1999-2004

begin
Assign(f, InputFile); Reset(f);
ReadLn(f, n);
Close(f);
Assign(f, OutputFile); Rewrite(f);
for i := 1 to n do x[i] := i; {Khi to cu hình đu: x[1] := 1; x[2] := 2; …, x[n] := n}
repeat
for i := 1 to n do Write(f, x[i], ' '); {In ra cu hình hoán v hin ti}
WriteLn(f);
i := n - 1;
while (i > 0) and (x[i] > x[i + 1]) do Dec(i);
if i > 0 then {Cha gp phi hoán v cui (n, n-1, …, 1)}
begin
k := n; {x[k] là phn t cui dãy}
while x[k] < x[i] do Dec(k); {Lùi dn k đ tìm gp x[k] đu tiên ln hn x[i]}
Swap(x[k], x[i]); {i ch x[k] và x[i]}
a := i + 1; b := n; {Lt ngc đon cui gim dn, a: đu đon, b: cui đon}
while a < b do
begin
Swap(x[a], x[b]); {o giá tr x[a] và x[b]}
Inc(a); {Tin a và lùi b, tip tc cho ti khi a, b chm nhau}

Dec(b);
end;
end;
until i = 0; {Toàn dãy là dãy gim dn - không sinh tip đc - ht cu hình}
Close(f);
end.
Bài tp:
Bài 1
Các chng trình trên x lý không tt trong trng hp tm thng, đó là trng hp n = 0
đi vi chng trình lit kê dãy nh phân cng nh trong chng trình lit kê hoán v, trng
hp k = 0 đi vi chng trình lit kê t hp, hãy khc phc điu đó.
Bài 2
Lit kê các dãy nh phân đ dài n có th coi là lit kê các chnh hp lp chp n ca tp 2 phn
t {0, 1}. Hãy lp chng trình:
Nhp vào hai s n và k, lit kê các chnh hp lp chp k ca {0, 1, …, n -1}.
Hng dn: thay h c s 2 bng h c s n.
Bài 3
Hãy lit kê các dãy nh phân đ dài n mà trong đó cm ch s “01” xut hin đúng 2 ln.
Bài 4.
Nhp vào mt danh sách n tên ngi. Lit kê tt c các cách chn ra đúng k ngi trong s n
ngi đó.
Bài 5
Lit kê tt c các tp con ca tp {1, 2, …, n}. Có th dùng phng pháp lit kê tp con nh
trên hoc dùng phng pháp lit kê tt c các dãy nh phân. Mi s 1 trong dãy nh phân
tng ng vi mt phn t đc chn trong tp. Ví d vi tp {1, 2, 3, 4} thì dãy nh phân
Bài toán lit kê  11 

Lê Minh Hoàng
1010 s tng ng vi tp con {1, 3}. Hãy lp chng trình in ra tt c các tp con ca {1,
2, …, n} theo hai phng pháp.

Bài 6
Nhp vào danh sách tên n ngi, in ra tt c các cách xp n ngi đó vào mt bàn
Bài 7
Nhp vào danh sách n bn nam và n bn n, in ra tt c các cách xp 2n ngi đó vào mt bàn
tròn, mi bn nam tip đn mt bn n.
Bài 8
Ngi ta có th dùng phng pháp sinh đ lit kê các chnh hp không lp chp k. Tuy nhiên
có mt cách khác là lit kê tt c các tp con k phn t ca tp hp, sau đó in ra đ k! hoán v
ca nó. Hãy vit chng trình lit kê các chnh hp không lp chp k ca {1, 2, …, n} theo c
hai cách.
Bài 9
Lit kê tt c các hoán v ch cái trong t MISSISSIPPI theo th t t đin.
Bài 10
Lit kê tt c các cách phân tích s nguyên dng n thành tng các s nguyên dng, hai cách
phân tích là hoán v ca nhau ch tính là mt cách.

Cui cùng, ta có nhn xét, mi phng pháp lit kê đu có u, nhc đim riêng và phng
pháp sinh cng không nm ngoài nhn xét đó. Phng pháp sinh không th sinh ra đc cu
hình th p nu nh cha có cu hình th p - 1, chng t rng phng pháp sinh t ra u đim
trong trng hp lit kê toàn b mt s lng nh cu hình trong mt b d liu ln thì li có
nhc đim và ít tính ph dng trong nhng thut toán duyt hn ch. Hn th na, không
phi cu hình ban đu lúc nào cng d tìm đc, không phi k thut sinh cu hình k tip
cho mi bài toán đu đn gin nh trên (Sinh các chnh hp không lp chp k theo th t t
đin chng hn). Ta sang mt chuyên mc sau nói đn mt phng pháp lit kê có tính ph
dng cao hn, đ gii các bài toán lit kê phc tp hn đó là: Thut toán quay lui (Back
tracking).

×