Tài liệu toán rời rạc - Dành cho ôn thi cao học hoặc sinh viên đại học cao đẳng
Trang 1PHẦN 1: KỸ THUẬT ĐẾM
CHƯƠNG 1
TỔ HỢP
1 Giới thiệu môn học toán rời rạc
- Toán rời rạc là một lĩnh vực của toán học, nghiên cứu các đối tuợng rời rạc Ví dụ tập các số nguyên, tập hợp các sinh viên trong một lớp là tập hợp các đối tượng rời rạc, tập hợp các số thực không phải là tập hợp các đối tượng rời rạc mà là tập các đối tượng liên tục
- Toán rời rạc là môn học quan trọng trong ngành tin học vì máy tính chỉ lưu trữ và xử lý các đối tương rời rạc nên việc tìm hiểu, nghiên cứu các tính chất của các đối tương rời rạc là rất cần thiết
- Toán rời rạc được chia thành hai phần: phần 1 trình bày các bài toán cơ bản của lý thuyết tổ hợp như là bài toán đếm, bài toán tồn tại, bài toán liệt kê, bài toán tối ưu; phần 2 trình bày lý thuyết đồ thị, đồ thị là một cấu trúc rời rạc được ứng dụng để giải nhiều bài toán trong tin học
2 Tập hợp
2.1 Các bài toán về tập hợp
Một cấu hình tập hợp là một cách phân bố các phần tử của một tập hợp theo những điều kiện xác định Ví dụ: một chỉnh hợp lặp hoặc không lặp, một hoán vị, một tổ hợp chặp k … gọi là một cấu hình tập hợp Có 4 bài toán cơ bản về tập hợp:
- Bài toán đếm: Đếm số cấu hình thoả mãn các điều kiện cho trước
- Bài toán liệt kê: Liệt kê tất cả các cấu hình thoả mãn các điều kiện cho trước
- Bài toán tối ưu: Tìm cấu hình tốt nhất theo một nghĩa nào đó
- Bài toán tồn tại: Có hay không các cấu hình thoả mãn các điều kiện cho trước
Ví dụ:
+ Bài toán đếm: Đếm số chỉnh hợp lặp chặp k của tập hợp có n phần tử: Đáp số = nk
+ Bài toán liệt kê: Liệt kê các hoán vị của tập hợp X={1,2,3}: (1,2,3); (1,3,2); (2,1,3); (2,3,1); (3,1,2); (3,2,1)
+ Bài toán tối ưu: Tìm tổ hợp chặp k của tập hợp X={1,2,3,…,n} sao cho tổng các phần tử của tổ hợp này là lớn nhất: (n-k+1, ,n)
2.2 Các phép toán trên tập hợp
- Phần bù của A trong X (X gọi là tập vũ trụ chứa A): là tập các phần tử thuộc X nhưng
không thuộc A , kí hiệu A
- Hợp của hai tập hợp A và B: là tập các phần tử thuộc A hay thuộc B, kí hiệu:
A∩B
A
B
A
Trang 2- Phủ định A: kí hiệu NOT A ⇔ A
- Tuyển của A và B: kí hiệu A OR B (A V B)⇔A∪B
- Hội của A và B: kí hiệu A AND B (A∧B) ⇔A∩B
Trang 33 Quan hệ tương đương
3.1 Định nghĩa
Tập hợp R⊆X2 gọi là một quan hệ tương đương trên X, nếu thoả các tính chất sau:
- Tính phản xạ: với mọi a ∈ X, a có quan hệ R với a
Cho X={1,2,3,4} Xét quan hệ “chia hết” R trên tập X; R={(a,b)| a chia hết cho b ; a,b ∈ X}.
R có là quan hệ tương đương trên X?
∀ a,b,c∈ X: (a,b), (b,c) ∈ R ⇒ a chia hết cho b, b chia hết cho c⇒a=k1b, b=k2c
⇒ a = (k1k2)c = kc ⇒ a chia hết cho c ⇒(a,c) ∈ R⇒ R có tính bắc cầu
Do không có tính đối xứng nên R không phải là quan hệ tương đương trên X
* Nhận xét: số quan hệ có thể xây dựng trên tập có n phần tử là 2n2
3.2 Lớp tương đương và phân hoạch
Một quan hệ tương đương trên tập X sẽ chia X thành các tập con gọi là các lớp tương đương sao cho hai phần tử ở cùng một lớp thì có quan hệ với nhau và hai phần tử khác lớp thì không có quan hệ với nhau Gọi X1,…,Xn là các lớp tương đương, ta có:
X= 1
n i
Tập hợp S= {Xi | i=1,…,n} thoả hai tính chất (1) và (2) gọi là một phân hoạch của tập X
Ngược lại với một phân hoạch bất kỳ trên X sẽ có quan hệ tương đương trên X sinh ra phân hoạch này Cách xây dựng qhtđ R từ phân hoạch {Xi} như sau: aRb ⇔ ∃Xi: a,b ∈Xi
Ví dụ:
Nếu a và b có cùng số dư khi chia cho k, kí hiệu là a≡b (mod k).
Cho X={1,2,…,m}, và k<m Xét quan hệ “đồng dư” R; R={(a,b)| a≡b (mod k) ; a,b ∈ X}
a) R có là quan hệ tương đương trên X?
b) Nếu R là quan hệ tương đương trên X, tìm phân hoạch S tương ứng với R
Trang 4∀ a, b, c∈X: (a,b), (b,c) ∈ R ⇒ a≡b (mod k), b≡c (mod k) ⇒
a≡c (mod k) ⇒(a,c) ∈ R⇒ R có tính bắc cầu
Do thoả cả ba điều kiện nên R là quan hệ tương đương trên X
c) Một số chia cho k chỉ có thể có số dư là 0, hoặc 1, …, hoặc k-1 nên các phần tử x∈ X chia
cho k dư là i (0, ,k-1) sẽ có quan hệ đồng dư R với nhau Gọi tập Xi gồm các phần tử chia cho
k dư là i
Xi ={x∈ X| x mod k =i}; i=0,…,k-1 Ta có:
X=
1 0
nên S= {Xi | i=1,…,n} là một phân hoạch của tập X
4 Công thức cộng và công thức nhân
a) Nếu mỗi thành phần xi của bộ có thứ tự (x1,…,xn) có ki khả năng chọn thì số bộ khác nhau
là tích của các khả năng này k1 k2 … kn
b) N(X1 x X2 x … x Xn) = N(X1) x N(X2) x …x N(Xn)
Ví dụ:
Trang 5Từ Hà Nội đến Huế có 3 cách đi: máy bay, ô tô, tàu hoả Từ Huế đến Sài Gòn có 4 cách đi: máy bay, ô tô, tàu hoả, tàu thủy Hỏi từ Hà Nội đến Sài Gòn (qua Huế) có bao nhiêu cách đi?
HD:
X1: tập hợp các cách đi từ Hà Nội đến Huế
X2: tập hợp các cách đi từ Huế đến Sài Gòn
X: tập hợp các cách đi từ Hà Nội đến Sài Gòn (qua Huế)
Gọi X là tập các biến cần tìm Phân hoạch X thành hai tập:
X1 là tập các biến bắt đầu bằng AAA và X2 là tập các biến bắt đầu bằng ABA
Phần tử thuộc X1 có dạng (AAAx4x5…x10), mỗi xi có hai khả năng là A hoặc B
nên N(X1)=27=128 (công thức nhân)
Trang 6Một tập con A của tập X có thể biểu diễn bằng một dãy nhị phân n phần tử Vị trí thứ i = 1 nghĩa là
A có phần tử xi, vt(i)= 0 là không có xi ví dụ: A={x3, x1} biểu diễn là (1,0,1,0,…0) Do số dãy nhị phân chiều dài n là 2n ⇒số tập con là 2n
b) Chỉnh hợp không lặp:
Một chỉnh hợp không lặp chặp k của tập hợp có n phần tử là một bộ có thứ tự gồm k phần tử lấy
từ n phần tử đã cho, các phần tử không được lặp lại
Để xây dựng một chỉnh hợp không lặp, ta xây dựng dần từ thành phần đầu tiên, thành phần này
có n khả năng chọn Mỗi thành phần tiếp theo, số khả năng chọn giảm đi 1 so với thành phần đứng trước Theo công thức nhân:
Ví dụ: Có 3 người xếp thành hàng ngang để chụp ảnh Hỏi có thể bố trí bao nhiêu kiểu?
HD: Mỗi kiểu là một hoán vị ⇒ số kiểu = 3!=6
Trang 7- Số tổ hợp chặp k của tập A có n phần tử, kí hiệu là
k n
k n
k n
C − (n>k>0) (công thức đệ qui)d) (x+y)n =
C − xy n-1 +
n n
C = !( ! )!
n
k n k−
Trang 8C bằng tam giác Pascal như sau:
+ 4 bút cùng màu: 4 bút cùng xanh, hoặc cùng đỏ hoặc cùng vàng => số cách = 3
+ 3 bút cùng màu: 3 bút cùng xanh, hoặc cùng đỏ hoặc cùng vàng; bút còn lại chọn một trong hai màu còn lại => số cách= 3*2=6
+ 2 bút cùng màu, 2 bút còn lại khác màu: 2 bút cùng xanh, hoặc cùng đỏ hoặc cùng vàng; hai bút còn lại chọn một trong hai màu còn lại => số cách= 3
- Nếu liệt kê như cách làm trên sẽ rất khó mở rộng cho trường hợp có nhiều bút và nhiều màu
để chọn Ta có thể giải bằng cách khác tổng quát hơn như sau:
Biểu diễn mỗi trường hợp bởi 4 dấu “+” và 2 dấu “–“ đặt liên tiếp trên một đường thẳng: số dấu
“+” bên trái dấu “-“ đầu tiên là số bút xanh, số dấu “+” giữa hai dấu “-” là số bút đỏ và số dấu cộng
ở bên phải dấu “-” cuối cùng là số bút vàng Ví dụ:
Trang 9Như thế mỗi cách chọn tương ứng với việc chọn 2 vị trí trong số 6 vị trí để làm dấu “-” Nên mỗi cách chọn là một tổ hợp không lặp chặp 2 của 6 phần tử=>số cách =
2 6
C =15 cách
vậy số cách chọn k bút từ n màu = số tổ hợp lặp chặp k của tập n phần tử = số tổ hợp không lặp chặp n-1 của tập k+n-1 phần tử, nên:
Ví dụ:
1/ Có k vật đồng chất nhau, hỏi có bao nhiêu cách chia chúng vào n hộp phân biệt nhau?
Ví dụ: có 3 vật chia vào 2 hộp thì có các cách chia sau: 111,222,112, 221
vậy mỗi cách chia là một tổ hợp lặp chặp 3 của tập hai phần tử {1,2}
Trang 10CHƯƠNG 2
BÀI TOÁN ĐẾM
1 Giới thiệu bài toán đếm
+ Bài toán đếm: là đếm số cấu hình tập hợp thoả các điều kiện cho trước
Trang 11Lấy x ∈ X1∪X2 ∪…Xm ta cm x chỉ được đếm một lần theo công thức b.
G/s x thuộc vào giao của k tập nào đó, theo công thức b, số lần x được đếm như sau:
X1={các dãy bắt đầu bởi 00}; X2={các dãy kết thúc bởi 11}
X={các dãy bắt đầu bởi 00 hoặc kết thúc bởi 11}
Trang 12Ví dụ:
Cho X={1,2,…,10000}, có bao nhiêu số không chia hết cho bất cứ số nào trong 3 số 3,4,7
HD:
Xi={ x ∈ X | x chia hết cho i}; i=3,4,7
Y={ x ∈ X | x không chia hết cho bất cứ số nào trong 3 số 3,4,7}
Ví dụ: Bài toán bỏ thư
Có n lá thư và n phong bì ghi sẵn địa chỉ Bỏ ngẫu nhiên các lá thư vào các phong bì Hỏi xác xuất
để xảy ra không một lá thư nào bỏ đúng địa chỉ là bao nhiêu?
C
⇒ Nk = Ck nx (n-k)! = !!
n k
Ví dụ: có 5 lá thư và 5 phong bì (n=5), thư i phải bỏ vào phong bì i Xét trường hợp 2 thư bỏ đúng địa chỉ (k=2), có
2 5
C trường hợp như vậy.
12! -…+
⇒ n! cách bỏ thư có N(Y) cách bỏ sao cho không lá nào đúng địa chỉ
⇒ Xác xuất để không một lá thư nào bỏ đúng địa chỉ là
:(1-11! +
12! -…+
12!-…+
Trang 133.1 Khái niệm
Trong nhiều trường hợp, việc tìm công thức f(n) tính trực tiếp số cấu hình theo tham số n là khó hoặc không thể được Khi đó ta có thể tìm công thức tính f(n) theo các giá trị của hàm f trước đó f(n-1), f(n-2),…Công thức này gọi là công thức truy hồi hay công thức đệ qui Khi xây dựng công thức truy hồi cần phải biết một số giá trị ban đầu của hàm f (biết f(0),f(1)…)
Trong một số trường hợp từ công thức truy hồi ta có thể suy ra công thức trực tiếp Công thức truy hồi rất thích hợp để cài đặt bằng phương pháp đệ qui trên máy tính
Ví dụ: Xây dưng công thức truy hồi tính số mất thứ tự Dn
Đánh số thư và phong bì từ 1 đến n, thư i gởi đúng địa chỉ nếu bỏ vào phong bì i Một cách bỏ thư
là một hoán vị (a1,…,an) của tập {1,2,…,n}, ai là thư Một cách bỏ thư không thư nào đúng địa chỉ
là 1 hoán vị (a1,…,an) sao cho ai ≠i, ∀i;
G/s n=5 , hoán vị (a1, a2, a3, a4, a5) = (2,5,1,3,4) là một cách bỏ thư không thư nào đúng địa chỉ
Xét a1 : a1 có n-1 giá trị k=2,…,n Với một giá trị k của a1 , có hai trường hợp của ak
+ ak=1: số cách bỏ thư không thư nào đúng địa chỉ là Dn-2 (do a1, ak đã sai địa chỉ)
+ ak≠1: số cách bỏ thư không thư nào đúng địa chỉ là Dn-1 (do a1 sai địa chỉ, ak chưa biết)
⇒ Một trường hợp của a1 = k có Dn-2 + Dn-1 cách bỏ thư không thư nào đúng địa chỉ,mà k có n-1 giá trị nên tổng số cách bỏ thư không thư nào đúng địa chỉ là:
Công thức này gọi là công thức truy hồi, có thể suy ra công thức trực tiếp như sau:
12! -…+
Trang 14Ví dụ: Xây dưng công thức truy hồi tính tổ hợp chặp k của n phần tử
k n
C −−
X2= {các tổ hợp chặp k sao cho các tổ hợp này không chứa a} ⇒N(X2)= 1
k n
C −− =
2 4
C =6
X2= { {1,3,4}; {1,3,5}; {1,4,5}; {3,4,5} }⇒N(X2)= 1
k n
C − =
3 4
C =4
⇒ N(X)= N(X1) + N(X2) = 6+4=10
3.2 Giải công thức truy hồi (khử đệ qui)
Giải công thức truy hồi là chuyển công thức truy hồi về công thức trực tiếp Chỉ một vài dạng công thức truy hồi đặc biệt mới có thể chuyển sang trực tiếp
an được tính dựa vào k số hạng liên tiếp ngay trước an ( …, a n-k , …, a n-1, an, … )
Cần phải biết trước k số hạng đầu tiên: a0, …,ak-1
Ví dụ : an = 2an-1 – 3an-2 (n≥2) ;với a0=1, a1= 2
là công thức truy hồi tuyến tính thuần nhất hệ số hằng bậc 2
Ta tìm an có dạng an = rn Thay an vào (1) ta được:
C = 1
1
k n
C −− + 1
k n
Trang 15B2: Giải ptđt, suy ra dạng tổng quát của an (dạng 5)
B3: Tính các hệ số của an dựa vào các điều kiện ban đầu Suy ra công thức trực tiếp
Trang 16n
k k
Trang 17− =1+ x + x2+
3
1
x x
− +….= 1+x+x2+…+xn+…= 0
i i
m
k k
+
m k k
n n+k-1 0
n n+k-1 0
(C n) n n
Trang 189
0
n n n
x x
−
1(1−x) =
n n+1 0
B1: Xây dựng công thức giải tích của hàm sinh, dựa vào công thức đệ qui
B2: Chuyển công thức giải tích về công thức lũy thừa (hàm sinh) : 0
n n n
Trang 19g(x)= 0
n n
n n
n n n
n n n
n n n
n n n
n n n
Trang 20CHƯƠNG 3
BÀI TOÁN TỒN TẠI
5 Giới thiệu bài toán
+ Bài toán tồn tại: Xét xem có hay không có một cấu hình thoả điều kiện cho trước, nếu có thì chỉ
ra cách xây dựng một cấu hình Nhiều khi việc xây dựng cấu hình cụ thể là khó hoặc không thể, khi đó ta chỉ cần chứng minh là có hoặc không có cấu hình
+ Phương pháp giải bài tóan tồn tại
- Phương pháp phản chứng
- Nguyên lý Dirichlet
6 Phương pháp phản chứng
Để chứng minh mệnh đề p ⇒ q, ta có thể chứng minh mệnh đề tương đương là q⇒ p Hay nói
cách khác là gỉa sử kết luận (q) là sai , từ đó dẫn đến mâu thuẫn với giả thiết (p)
C = 5; và các cách xếp là: 1111,1112, 1122,
1222, 2222
* Ví dụ:
Trong số 367 người bao giờ cũng tìm được hai người có ngày sinh nhật giống nhau
Xếp vật vào hộp, nếu số vật nhiều hơn số hộp thì tồn tại một hộp chứa ít
nhất 2 vật.
Trang 21A0 ={ các người có tuổi chia 16 dư 0}
A1 ={ các người có tuổi chia 16 dư 1 hoặc dư 15}
…
A7 ={ các người có tuổi chia 16 dư 7 hoặc dư 9}
A8 ={ các người có tuổi chia 16 dư 8}
2 người thuộc Ai sẽ có tổng số tuổi chia hết cho 16 hoặc hiệu số tuổi chia hết cho 16
Cần có ít nhất bao nhiêu bộ có thứ tự gồm 2 số nguyên (a,b) sao cho chắc chắn tìm được trong
số đó hai bộ (c,d) và (e,f) sao cho c-e và d-f là các số có chữ số tận cùng bằng 0?
Trang 22Giả sử A là một tập con có 6 phần tử của tập {1,2,…,14} Chứng minh rằng trong số các tập con khác rỗng của tập A, có tối đa 5 phần tử thì có ít nhất hai tập con mà tổng của các phần tử là như nhau.
HD:
Giả sử B là một tập con khác rỗng bất kỳ của A, SB là tổng các phần tử của B Ta có :
1≤ SB ≤ 10+…+14=60
Hộp: là các số từ 1 đến 60 => số hộp=60
Vật : là các tập con khác rỗng có tối đa 5 phần tử của A =>số vật=26 -2=62
số vật >số hộp => có ít nhất hai tập con mà tổng của các phần tử là như nhau
8 Nguyên lý Direchlet tổng quát
* Ví dụ: bài 7/68
17 nhà bác học đôi một viết thư trao đổi với nhau về 3 chủ đề, mỗi cặp chỉ trao đổi với nhau về một chủ đề Chứng minh rằng luôn tìm được 3 nhà bác học đôi một viết thư trao đổi với nhau về cùng một chủ đề
Nếu xếp k vật vào n hộp thì tồn tại một hộp chứa ít nhất [k/n] vật.
( [k/n] là số nguyên dương nhỏ nhất mà lớn hơn hay bằng k/n).
Trang 24CHƯƠNG 4
BÀI TOÁN LIỆT KÊ
1 Giới thiệu bài toán
Việc liệt kê cụ thể tất các cấu hình thoả một số điều kiên cho trước gọi là bài toán liệt kê Có nhiều cách liệt kê nhưng không được bỏ sót hoặc lặp lại một cấu hình
Có hai thuật toán thường sử dụng để giải bài tóan liệt kê là thuật toán sinh và thuật toán quay lui
Vì có nhiều thuật toán để giải một bài toán nên ta cần có phương pháp để đánh giá một thuật toán tốt hay xấu
2 Thuật toán(Algorithms)
2.1 Khái niệm thuật toán
- Thuật toán là dãy các thao tác mà máy tính cần thực hiện theo trình tự xác định để giải quyết một vấn đề nào đó
- Khi viết chương trình, ta phải xây dựng cấu trúc dữ liệu và Thuật toán Cấu trúc dữ liệu và Thuật toán có quan hệ chặt chẽ với nhau: nếu chọn một cấu trúc dữ liệu phù hợp, Thuật toán sẽ đơn giản, dễ mở rộng và ngược lại nếu chọn một cấu trúc dữ liệu không phù hợp, Thuật toán sẽ phức tạp, khó mở rộng
Công thức:
Ví dụ:
a) Tìm số lớn nhất trong 3 số cho trước.
- CTDL: sử dụng cấu trúc lưu trữ dữ liệu là 4 biến a, b, c, max (max chứa số lớn nhất)
- Thuật toán:
B0: nhập a,b,c
B1: gán max=a
B2: so sánh b với max: nếu b>max thì lưu b vào max
B3: so sánh c với max: nếu c>max thì lưu c vào max
B4: in biến max
- Nhận xét:
Với CTDL là các biến nguyên rời rạc a,b,c, chương trình sẽ không thể mở rộng trong trường hợp tìm số lớn cho n số (n là số do người sử dụng nhập vào) Ta cần xây dựng lại ctdl và Thuật toán như sau:
b) Tìm số lớn nhất trong n số cho trước (n <=100)
- CTDL: int a[100] (mảng tĩnh chứa tối đa 100 số nguyên), int max
- Thuật toán:
B0: nhập n, nhập dãy n số nguyên a[0], a[1],…,a[n-1]
B1: max=a[0]; i=1;
B2: Trong khi i<n lặp lại các bước sau:
B2.1: Nếu a[i]>max thì max=a[i];
c) Tìm số lớn nhất trong n số cho trước (n không bị giới hạn trước)
CẤU TRÚC DỮ LIỆU + GIẢI THUẬT = CHƯƠNG
TRÌNH
Trang 25- CTDL: sử dụng mảng động, int max
- Thuật toán:
B0: nhập n, cấp phát mảng động n phần tử, nhập dãy n số nguyên a[0], a[1],…,a[n-1]
B1,B2, B3: giống câu b
cap phat mang dong n phan tu: int *a=new int(n);
- Nhận xét: Thuật toán khi sử dụng ctdl là mảng động với Thuật toán khi sử dụng ctdl là mảng tĩnh xem như không đổi nhưng nếu dùng ctdl là danh sách liên kết thì Thuật toán sẽ thay đổi
2.2 Yêu cầu của một Thuật toán
- Tính đúng: Thuật toán phải cho kết quả đúng trong mọi trường hợp
- Tính dừng: Thuật toán phải dừng sau một số hữu hạn bước thực hiện
- Tính tổng quát: Thuật toán phải giải quyết được một lớp các bài toán tương tự
- Tính đơn giản: Thuật toán phải dễ đọc, dễ sửa lỗi, dễ nâng cấp
- Thực hiện nhanh và tiết kiệm tài nguyên máy tính
2.3 Lưu đồ của Thuật toán:
Là hình vẽ biểu diễn các bước thực hiện của Thuật toán Có các qui ước vẽ hình sau:
nếu đúng thực hiện lệnh theo hướng mũi tên đúng, nếu sai, thực hiện lệnh theo hướng mũi tên sai
Lệnh thực hiện việc tính toán, lệnh gán
Lệnh gọi chương trình con
Bắt đầu hay kết thúc Thuật toán
Ví dụ: Lưu đồ của thuật toán tìm số lớn nhất trong n số cho trước
nhập dãy a n
Bắt đầu max=a[0]; i=1;
i<n Đ
S
xuất max
a[i]>max Đ
Trang 26Kết thúc
2.4 Đánh giá thuật toán
- Thuật toán được đánh giá qua thời gian thực hiện, nhưng thời gian này lại phụ thuộc vào tốc độ máy tính, phụ thuộc vào ngôn ngữ lập trình, phụ thuộc vào trình biên dịch… Do đó cần có phương pháp đánh giá Thuật toán độc lập với các yêu tố kể trên
- Thuật toán được đánh gía dựa vào các trường hợp của dữ liệu: tốt nhất, trung bình, xấu nhất Thường Thuật toán được đánh giá trong trường hợp dữ liệu đưa vào là “xấu nhất”, nghĩa là trường hợp với tập dữ liệu đó, Thuật toán thực hiện chậm nhất Trường hợp “trung bình” ứng với tập dữ liệu ngẫu nhiên và thường rất khó đánh giá, trường hợp “tốt nhất” thường không quan tâm
- Khi lượng dữ liệu nhỏ, thời gian thực hiện của các Thuật toán là như nhau, do đó chỉ đánh gía Thuật toán khi dữ liệu đưa vào là rất lớn
- Do thời gian thực hiện của mỗi lệnh là rất bé nên ta có thể xem thời gian thực hiện của mỗi lệnh là bằng nhau
- Với các nhận xét trên, cách đánh giá Thuật toán như sau:
+ Với số lượng dữ liệu vào là n, đếm tổng số lần thực hiện các lệnh trong trường hợp dữ liệu “xấu nhất”
+ Tổng số lệnh thực hiện là hàm f(n), giả sử thời gian thực hiện của 1 lệnh là t thì thời gian thực hiện của thuật toán là T = f(n)*t
+ Cho n-> vô cực thì f(n)->g(n): kí hiệu là O(g(n)) gọi là độ phức tạp của thuật toán
- O(g(n)) thường là các hàm được sắp theo thứ tự “tốt” như sau:
Hàm hằng O(a), O(log(n)), O(n), O(nlog(n)), O(n2), O(n3),O(2n), O(n!), O(nn)
Trang 27Nhìn vào đồ thị, ta thấy khi n->vc thì n3 lớn rất nhanh, do đó những thuật toán có độ phức tạp
là O(n3),O(2n), O(n!), O(nn) thường không sử dụng được khi n rất lớn
Ví dụ 1:Xây dựng và đánh giá Thuật toán tìm số lớn nhất của n số
- Thuật toán:
B0: nhập n, sau đó nhập dãy n số nguyên a[0], a[1],…,a[n-1]
B1: max=a[0]; i=1;
B2: Trong khi i<n lặp lại các bước sau:
B2.1: Nếu a[i]>max thì max=a[i];
B2.2: i=i+1;
B3: In max
- Đánh giá: trường hợp xấu nhất là dãy sắp giảm dần
Trang 28Cho n->vc thì f(n)->n Vậy độ phức tạp của thuật toán là O(n).
Ví dụ 2: Xây dựng và đánh giá Thuật toán sắp xếp dãy n số nguyên tăng dần
B3: In dãy a[0], a[1],…,a[n-1]
- Đánh giá: trường hợp xấu nhất là dãy sắp giảm dần
- Nếu một vòng lặp thì độ phức tạp là O(n), hai vòng lặp lồng nhau là O(n2)
3 Thuật toán sinh
Ý tưởng:
Trang 29- Xây dựng một thứ tự trên tập các cấu hình cần liệt kê và suy ra cấu hình đầu tiên, cấu hình cuối cùng
- Xây dựng thuật toán sinh cấu hình thứ i từ cấu hình thứ i-1 (gọi là thuật tóan sinh cấu hình kế tiếp)
Từ thuật toán sinh và biết cấu hình 1 sẽ tìm được cấu hình 2, biết cấu hình 2 lại theo thuật toán sinh tìm được cấu hình 3, vv… lặp lại cho đến khi tìm được cấu hình cuối cùng thì ngừng
Nhận xét:
Các bài toán liệt kê cấu hình chỉ áp dụng được thuật toán sinh khi ta xây dựng đuợc một “thứ tự” trên tập các cấu hình cần liệt kê và xây dựng được thuật toán “sinh cấu hình kế tiếp”
Dạng tổng quát của thuật toán
//cac bien toan cuc
int stop;
void init() //ham khoi tao
{
stop=0; //false
//cac lenh gan tri ban dau cho cac bien toan cuc
//các lệnh xây dựng cấu hình đầu tiên;
//cac lenh tao cau hinh ke tiep
//neu la cau hinh cuoi thi gan stop=1 (true) de ngung liet ke
}
void enumerate() //ham liet ke cac cau hinh
{
init(); //khoi tao cac bien toan cuc, tao cau hinh dau tien
while(!stop)//trong khi chua liet ke den cau hinh cuoi
{
output(); //xuất cấu hình hiện tại generate(); //sinh cau hinh ke tiep}
}
* Các ví dụ:
Ví dụ 1: liệt kê các dãy nhị phân có độ dài n
HD:
- Xây dựng một thứ tự các dãy np cần liệt kê
Gọi a, b là hai dãy nhị phân và p(a), p(b) là số nguyên tương ứng với a, b Ta xây dựng một thứ tự như sau:
a<b ⇔ p(a)<p(b)
Suy ra dãy np đầu tiên là 0…0 (n số 0) và dãy np cuối cùng là 1…1 (n số 1)
- Xây dựng thuật toán sinh dãy np kế tiếp:
Do dãy kế sẽ có giá trị thập phân lớn hơn dãy hịên tại 1 đơn vị nên ta có cách xây dựng dãy np
kế như sau: Gọi b1 bn là dãy np hiện tại
Nếu bi =1, ∀i=1…n thì đây là dãy np cuối, gán stop=1
Ngược lại
+ Tìm bi đầu tiên từ phải qua trái sao cho bi=0
Trang 30+ Gán bi=1 và gán các bi+1=…=bn=0
Ví dụ: n=4, xét dãy np 1011 thì dãy np kế là 1100
#include <stdio.h>
#include <conio.h>
//cac bien toan cuc
int b[20], n, count, stop;
void init()//ham khoi tao
{
//gan tri ban dau cho bien toan cuc
count=0; stop=0;//bien count de dem so day, stop dung de ngung liet ke
printf("n="); scanf("%d",&n); //n la chieu dai day
//xay dung day dau tien la day n so 0
for(int i=0;i<n;i++) b[i]=0;
init();//khoi tao cac bien toan cuc, tao day dau tien
while (!stop) //trong khi chua liet ke toi day cuoi
Trang 31}
Ví dụ 2: Liệt kê tất cả các tập con m phần tử của tập n phần tử {1,2,…,n}
HD:
- Xây dựng một thứ tự các tập con cần liệt kê
Một tập con m phần tử có thể biểu diễn bởi một bộ có thứ tự a=(a1, a2,…, am) tăng sao cho 1≤a1≤
a2≤…≤am≤n
Gọi a, b là hai tập con m phần tử Ta xây dựng một thứ tự như sau:
a<b ⇔ ∃k: a1=b1,…, ak-1=bk-1, ak<bk
Ví dụ: n=6, m=4; (1,2,3,6)<(1,2,4,5)
Suy ra tập con đầu tiên là (1,2,…,m) và tập con cuối cùng là (n-m+1,…,n)
- Xây dựng thuật toán sinh tập con kế tiếp:
Do ai lớn nhất là n-m+i ta có thuật toán sinh tập con kế tiếp như sau: Gọi a=(a1, a2,…, am) là tập con hiện tại
Nếu a= (n-m+1,…,n) thì đây là tập con cuối cùng , gán stop=1
Ngược lại
+ Tìm ai đầu tiên từ phải qua trái sao cho ai < n-m+i
+ Gán ai=ai+1 và gán ak= ai +k – i, ∀k=i+1,…,m (nghĩa là gán ai+1=ai+1, ai+2=ai+2,…, am=ai+m-i);
Ví dụ: n=6, m=4; xét tập con a=(1,2,5,6) ⇒ ai=2, tập con kế là (1,3,4,5)
#include <stdio.h>
#include <conio.h>
//cac bien toan cuc
int a[20], n,m, count, stop;
void init()//ham khoi tao
{
//gan tri ban dau cho bien toan cuc
count=0; stop=0;//bien count de dem so tap con, stop dung de ngung liet ke
printf("n,m="); scanf("%d%d",&n,&m); //m la spt cua tap con
//xay dung tap con dau tien la tap (1,2,…,m)
Trang 32}
void enumerate()//ham liet ke tat ca cac tap con
{
init();//khoi tao cac bien toan cuc, tao tap con dau tien
while (!stop) //trong khi chua liet ke toi tap con cuoi cung
- Xây dựng một thứ tự các hoán vị cần liệt kê
Một hoán vị có thể biểu diễn bởi một bộ có thứ tự a=(a1, a2,…, an) : ai ∈ {1,2,…,n} và ai ≠aj ,∀i≠j.Gọi a, b là hai tập con n phần tử Ta xây dựng một thứ tự như sau:
a<b ⇔ ∃k: a1=b1,…, ak-1=bk-1, ak<bk Ví dụ: n=4, (2,1,4,3) < (2,3,1,4)
Suy ra hoán vị đầu tiên là (1,2,…,n) và hoán vị cuối cùng là (n,n -1,…,1)
- Xây dựng thuật toán sinh hoán vị kế tiếp:
Gọi a=(a1, a2,…, an) là hoán vị hiện tại
Nếu a= (n, n-1,…,1) thì đây là hoán vị cuối, gán stop=1
Ngược lại
+ Tìm ai đầu tiên từ phải qua trái sao cho ai < ai+1
+ Tìm ak là số nhỏ nhất trong các số bên phải ai mà ak>ai
+ Hoán vị ai với ak
+ Đảo ngược dãy con từ ai+1 đến an
Ví dụ: n=6; xét hoán vị a=(3,6,2,5,4,1) ⇒ ai =2, ak =4, hoán vị kế là (3,6,4,1,2,5)
#include <stdio.h>
#include <conio.h>
int a[20], n, count, stop;
void init()//ham kkhoi tao
{ //khoi tao cac bien toan cuc
Trang 33//Tìm ai đầu tiên từ phải qua trái sao cho ai < ai+1
while (i>=0 && a[i]>a[i+1]) i ;
if (i<0) stop=1;//a= (n, n-1,…,1) thì đây là hoán vị cuối
else
{ //tìm ak là số nhỏ nhất trong các số bên phải ai mà ak>ai
int k=n-1;
while (a[i]>a[k]) k ;
swap(a[i],a[k]); //Hoán vị ai với ak
//Đảo ngược dãy con từ ai+1 đến an-1
int r=n-1, s=i+1;
while (r>s){
swap(a[r],a[s]); r ; s++;
}}
số ngược lại tiếp tục xác định xi+1 Khi đã xét tất cả các khả năng có thể của xi , ta lần ngược lại bước trước để xác định một khả năng kế tiếp của xi-1
Dạng tổng quát của thuật toán
Trang 34void tim(int i) //xac dinh xi
Cây lời giải :
Quá trình tìm kiếm lời giải có thể mô tả bởi cây tìm kiếm lời giải dạng sau:
+ Hai yếu tố quyết định thời gian thực hiện của thuật toán là :
- Xác định danh sách “các khả năng của xi“ sao cho ít khả năng nhất
- Xác định điều kiện “chấp nhận khả năng j”: điều kiện này cần đơn giản nhất nếu có thể Nếu điều kiện này phụ thuộc vào dãy x1, x2, …,xi-1 đã chọn trước đó thì cần các biến toàn cục (còn gọi là các biến trạng thái) để ghi nhận lại việc đã chọn các x1, x2, …,xi-1 và cần trả lại trạng thái cũ sau lời gọi tim(i+1) và sau khi ghi nhận một đáp số
+ Ở một mức nào đó, nhánh nào không thể cho đáp số cần ngừng lại, để tránh trường hợp
Trang 35- Ghi nhận 1 đáp số: xuất dãy xi.
* Cây lời giải với n=3
int n,x[20]; //mang x chua day nhi phan
//ham khoi tao
if (i==n-1) //da tim du n thanh phan
xuat(); //xuat day npelse
tim(i+1); //tim x[i+1]
}
}
void main()
Trang 36- Ghi nhận 1 đáp số: xuất dãy xi.
//liet ke tat ca cac hoan vi cua tap {1,2, ,n}
printf("\nNhap n="); scanf("%d",&n);//n la cd day np
for (int i=0;i<n;i++) b[i]=0;//0 la chua su dung gia tri i
if (i==n-1) //neu tim du n thanh phan
xuat(); //xuat hoan vielse
tim(i+1); // tim x[i+1]
b[j]=0; //bo chon j}
Trang 37* Cây lời giải với n=3
Ví dụ 3: Liệt kê các tổ hợp chặp m của {1,2,…,n} (moi to hop la mot tap con)
- Ghi nhận 1 đáp số: xuất dãy xi
Cây liệt kê trường hợp n=4, m=3: n!/(m!*(n-m)!)=4!/(3!*1!)=4
Trang 38//liet ke cac tap con cua tap {1,2, ,n} bang pp lan nguoc
//xet cac kha nang cua xi: x[i-1]+1, ,n-m+i
for (int j=x[i-1]+1; j<=n-m+i; j++)
{
x[i]=j;//tinh x[i];
if (i==m) //neu tim du m phan tu xuat(); //xuat tap con m phan tu else tim(i+1);// tim x[i+1]
ở hàng 4,…Khi đó khả năng sap cho hau thu j là từ hàng i=1 đến i=n
- Hàng i được chấp nhận nếu ô (i,j) chưa bị các quân hậu trước chiếu đến Để kiểm soát hàng i,
ta dùng mảng a với a[i]=1 là hàng i còn trống Ta nhận xét đường chéo phụ có phương trình
Trang 39i+j= const , để kiểm soát đc phụ này ta dùng mảng b[k] (k=2,…,8); đường chéo chính trên có
pt j-i=const, để kiểm soát đc chính trên ta dùng mảng c[k] (k=0,…,3); đường chéo chính dưới
có pt i-j=const, để kiểm soát đc chính dưới ta dùng mảng d[k] (k=1,…,3) Khả năng chấp nhận hàng i là nếu ( a[i] && b[i+j] && ( ((j>=i)&&c[j-i]) || ((j<i)&&d[i-j]) ) ) Khi đặt hậu vào hàng i cần gán 0 cho ba biến a[i], b[i+j], c[j-i] hoặc d[i-j] và sau khi gọi xuất hay tìm(i+1) cần trả lại 1
for (i=1;i<=n;i++) a[i]=1; //tat ca hang ai, i=1, ,n hop le
for (i=2;i<=2*n;i++) b[i]=1; //tat ca duong cheo phu bi, i=2,…,2n la hop le
for (i=0;i<=n-1;i++) c[i]=1;//tat ca duong cheo chinh phia tren ci, i=0,…,n-1 la hop le
for (i=1;i<=n-1;i++) d[i]=1;//duong cheo chinh phia duoi di, i=1,…,n-1 la hop le
{ //xet cac kn i cua x[j] (cac kn co the xep con hau thu j)
for (int i=1; i<=n; i++)//hau o cot j co the sap vao hang i=1,…,n
{//neu hang i, duong cheo phu thu i, dc chinh tren hoac dc chinh duoi hop le
if ( a[i] && b[i+j] && ( ((j>=i)&&c[j-i]) || ((j<i)&&d[i-j]) ) )
Trang 40x[j]=i; //dat con hau thu j o cot j hang ia[i]=0; //ghi nhan hang i da co haub[i+j]=0; //ghi nhan duong cheo phu thu i+j da co hau//ghi nhan duong cheo chinh j-i hoac i-j da co hau
if (j>=i) c[j-i]=0; else d[i-j]=0;
if (j==n) xuat(); //neu da sap duoc con hau cuoi cung thi xuat dap soelse tim(j+1);//tim cach sap cho hau j+1
a[i]=1; b[i+j]=1; //tra lai hang i cot j chua co hau
if (j>=i) c[j-i]=1; else d[i-j]=1;
}}
x x x
i
i i
n) : , , , 1 , 2 , , , ,
, (
1 2