IẾP TỤC CHƯƠNG 1 CỦA MÔN TOÁN RỜI RẠC MÌNH SẼ GỬI DẾN D CÁC BẠN SLIDE BÀI GIẢNG CHƯƠNG 2.4 MÔN TOÁN RỜI RẠC CỦA TRƯỜNG ĐẠI HỌC MỎ ĐỊA CHẤT MONG RẰNG VỚI CÁC SLIDE NÀY SẼ GIÚP CÁC BẠN DỄ DÀNG CHINH PHỤC ĐƯỢC MÔN TOÁN RỜI RẠC NÀY
Trang 1CHƯƠNG 2: LÝ THUYẾT TỔ HỢP
Gv: Đặng Hữu Nghị
Trang 2NỘI DUNG
2.1 Sơ lƣợc về tổ hợp
2.2 Bài toán đếm 2.3 Bài toán tồn tại
2.4 Bài toán liệt kê
Trang 32.4.1 GIỚI THIỆU BÀI TOÁN
hợp có thể có, đƣợc gọi là hài toán liệt kê tổ
hợp
có thể xác định một thuật toán để theo đó có
Trang 42.4.2 PHƯƠNG PHÁP SINH
toán liệt kê tổ hợp đặt ra nếu nhƣ hai điều
kiện sau đƣợc thực hiệ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ể xác định
được cấu hình đầu tiên và cấu hình cuối cùng
trong thứ tự đã xác định
Xây dựng được thuật toán từ cấu hình chưa phải
là cuối cùng đang có, đưa ra cấu hình kế tiếp nó
4
Trang 5<Đưa ra cấu hình đang có>;
if (<cấu hình đang có chưa là cuối cùng>)
then <Sinh_kế_tiếp>
else Stop:= true;
end;
Trang 6LIỆT KÊ TẤT CẢ CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
Liệt kê tất cả các dãy nhị phân độ dài n: b1
b2 bn, trong đó bi {0, 1}
Xem mỗi dãy nhị phân b = b1b2 bn là
biểu diễn nhị phân của một số nguyên p(b)
Ta nói dãy nhị phân b = b1 b2 bn đi
trước dãy nhị phân b' = b'1 b'2 b'n trong
thứ tự tự nhiên và ký hiệu là b b' nếu
p(b) < p(b')
6
Trang 7LIỆT KÊ TẤT CẢ CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
Ví dụ: Khi n=3, các
dãy nhị phân độ dài 3
đƣợc liệt kê theo thứ
Trang 8LIỆT KÊ TẤT CẢ CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
Dãy đầu tiên sẽ là: 00 0
Dãy cuối cùng là: 11 1
Giả sử b1 b2 b n là dãy đang có
Nếu dãy này gồm toàn số 1, kết thúc,
Trái lại, dãy kế tiếp nhận đƣợc bằng cách cộng thêm 1
(theo modun 2, có nhớ) vào dãy hiện tại
Từ đó ta có qui tắc sinh dãy kế tiếp nhƣ sau:
Tìm i đầu tiên (theo thứ tự i=n, n-1, , 1) thoả mãn b i
= 0
Gán lại b i = 1 và b j = 0 với tất cả j > i Dãy mới thu
Trang 9LIỆT KÊ TẤT CẢ CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
Trang 10LIỆT KÊ TẤT CẢ CÁC DÃY NHỊ PHÂN ĐỘ DÀI N
void Next_Bit_String( )
/*Sinh xâu nhị phân kế tiếp theo thứ tự từ điển
của xâu đang có b1 b2 bn 1 1 1 */
Trang 12stop = 1;
else
b[i]= 1;
Trang 13int main()
{
Init();
while(stop==0) {
Trang 14LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
N PHẦN TỬ (SINH TỔ HỢP)
Bài toán đặt ra là: Cho X = {1, 2, , n}
Hãy liệt kê các tập con m phần tử của X
Mỗi tập con m phần tử của X có thể
biểu diễn bởi bộ có thứ tự gồm m
Trang 15LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
Ta nói tập con a = (a1, a2, , am) đi trước
tập con a' = (a'1, a'2, , a'm) trong thứ tự
từ điển và ký hiệu là a a', nếu tìm được
chỉ số k (1 k m) sao cho
a1 = a'1 , a2 = a'2, , ak-1 = a'k-1, ak < a'k 15
Trang 16LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
Trang 17LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
sau đối với tập đang có:
Tìm từ bên phải dãy a1, a2, , am phần tử ai n-m+i
Thay ai bởi ai + 1;
Thay aj bởi ai + j - i, với j = i+1, i+2, , m 17
Trang 18LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
N PHẦN TỬ (SINH TỔ HỢP)
Ví dụ: n = 6, m = 4
Giả sử đang có tập con (1, 2, 5, 6), cần
xây dựng tập con kế tiếp nó trong thứ tự từ
Trang 19LIỆT KÊ CÁC TẬP CON M PHẦN TỬ CỦA TẬP
Trang 21a[j] = a[i] + j - i;
Trang 22int main()
{
Init();
while(stop==0) {
Trang 23LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Bµi to¸n: Cho X = {1, 2, , n}, h·y liÖt kª
Trang 24LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Ta nói hoán vị a = (a1, a2, , an) đi trước
hoán vị a' = (a'1, a'2, , a'n) trong thứ tự
từ điển và ký hiệu là a a', nếu tìm được
chỉ số k (1 k n) sao cho:
a1 = a'1, a2 = a'2, , ak-1 = a'k-1, ak < a'k
24
Trang 25LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Trang 26LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Thuật toán sinh kế tiếp
Hoán vị đầu tiên: (1, 2, , n)
Hoán vị cuối cùng: (n, n-1, , 1)
Giả sử a = (a1, a2, , a n) là hoán vị chƣa phải cuối
cùng, khi đó hoán vị kế tiếp nó có thể xây dựng nhờ thực
hiện các biến đổi sau:
Trang 27LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Ví dụ
xây dựng hoán vị kế tiếp nó trong thứ tự từ
điển
Ta có chỉ số j = 3 (a3 =2 < a4 = 5)
phải của a3 là a5 = 4 Đổi chỗ a3 với a5 ta thu
đƣợc (3, 6, 4, 5, 2, 1),
Trang 28LIỆT KÊ CÁC HOÁN VỊ CỦA TẬP N PHẦN TỬ
Trang 29//Hoan vi gia tri cua 2 phan tu
void Swap(int &x, int &y)
{ int tg = x; x = y; y = tg; }
29
Trang 30void Next_Permutation()
{
stop = 1;
int j =n-1;
while(a[j] > a[j+1] && j > 1) j = j - 1;
/*Tim j là chi so lon nhat thoa aj < aj+1*/
if(a[j] < a[j+1])
stop =0;
int k =n; while (a[j] > a[k]) k = k - 1;
Swap(a[j], a[k]); /*doi cho aj voi ak*/
Trang 31int main()
{
Init();
while(stop==0) {
31
Trang 3232
C HƯƠNG 2.4 B ÀI TOÁN LIỆT KÊ
2.4.3 THUẬT TOÁN QUAY LUI Backtracking Algorithm
Trang 33NỘI DUNG
2.4.3.1 Sơ đồ thuật toán
2.4.3.2 Liệt kê các cấu hình tổ hợp cơ bản
Liệt kê xâu nhị phân độ dài n
Liệt kê tập con m phần tử của tập n phần tử
Liệt kê hoán vị
2.4.3.3 Bài toán xếp hậu
Trang 34SƠ ĐỒ THUẬT TOÁN
Thuật toán quay lui (Backtracking Algorithm) là một thuật toán cơ bản đƣợc áp dụng để giải quyết nhiều vấn
Trang 36Khi k = 0, lời giải bộ phận cấp 0 đƣợc ký hiệu
là ( ) và còn đƣợc gọi là lời giải rỗng
Nếu k = n, ta có lời giải đầy đủ hay đơn giản
là một lời giải của bài toán
Trang 37 Ký hiệu tập các UCV vào vị trí thứ nhất của lời giải
là S1 Lấy a1 S1, bổ sung nó vào lời giải rỗng đang
có ta thu đƣợc lời giải bộ phận cấp 1: (a1)
Trang 38BƯỚC TỔNG QUÁT
Tại bước tổng quát, giả sử ta đang có lời giải bộ phận
cấp k-1: (a1, a2, , ak-1)
Trên cơ sở tính chất P ta xác định được những phần tử
nào của tập Ak có thể chọn vào vị trí thứ k của lời giải
Những phần tử như vậy ta sẽ gọi là những ứng cử viên
(viết tắt là UCV) vào vị trí thứ k của lời giải khi k-1 thành phần đầu của nó đã được chọn là (a1, a2, , ak-1)
Ký hiệu tập các ứng cử viên này là Sk
Trang 39X ÉT HAI TÌNH HUỐNG
Tình huống 1: Sk ≠ Khi đó lấy ak Sk, bổ
sung nó vào lời giải bộ phận cấp k-1 đang có
(a1, a2, , ak-1)
ta thu đƣợc lời giải bộ phận cấp k:
(a1, a2, , ak-1, ak)
Khi đó
Nếu k = n thì ta thu đƣợc một lời giải,
Nếu k < n, ta tiếp tục đi xây dựng thành phần thứ k+1 của lời giải
Trang 40TÌNH HUỐNG NGÕ CỤT
Tình huống 2: S k= Điều đó có nghĩa là lời giải bộ
phận (a1, a2, , a k-1) không thể tiếp tục phát triển thành lời giải đầy đủ Trong tình huống này ta quay trở lại tìm
ứng cử viên mới vào vị trí thứ k-1 của lời giải
Nếu tìm thấy UCV như vậy, thì bổ sung nó vào vị trí thứ
k-1 rồi lại tiếp tục đi xây dựng thành phần thứ k
Nếu không tìm được thì ta lại quay trở lại thêm một bước
nữa tìm UCV mới vào vị trí thứ k-2, Nếu quay lại tận
lời giải rỗng mà vẫn không tìm được UCV mới vào vị trí thứ 1, thì thuật toán kết thúc
Trang 41THUẬT TOÁN QUAY LUI
procedure Bactrack(k: integer);
Trang 42HAI VẤN ĐỀ MẤU CHỐT
Để cài đặt thuật toán quay lui giải các bài toán tổ hợp cụ thể ta cần giải quyết hai vấn đề cơ bản sau:
Tìm thuật toán xây dựng các tập UCV Sk
Tìm cách mô tả các tập này để có thể cài đặt thao tác liệt kê các phần tử của chúng (cài đặt
vòng lặp qui ƣớc for y Sk do)
Hiệu quả của thuật toán liệt kê phụ thuộc vào việc ta có xác định đƣợc chính xác các tập UCV này hay không
Trang 43C HÚ Ý
Nếu chỉ cần tìm một lời giải thì cần tìm cách chấm dứt các thủ tục gọi đệ qui lồng nhau sinh bởi lệnh gọi Backtrack(1) sau khi ghi nhận đƣợc lời giải đầu tiên
Nếu kết thúc thuật toán mà ta không thu đƣợc một lời giải nào thì điều đó có nghĩa là bài toán không có lời giải
Trang 44C HÚ Ý
Thuật toán dễ dàng mở rộng cho bài toán liệt kê trong đó lời giải
có thể mô tả như là bộ (a1, a2, , a n , ) độ dài hữu hạn, tuy nhiên
giá trị của độ dài là không biết trước và các lời giải cũng không
nhất thiết phải có cùng độ dài
Khi đó chỉ cần sửa lại câu lệnh
if k = n then <Ghi nhận lời giải (a 1 , a 2 , , a k ) >
Trang 45CÂY LIỆT KÊ LỜI GIẢI
THEO THUẬT TOÁN QUAY LUI
Trang 46L IỆT KÊ XÂU NHỊ PHÂN ĐỘ DÀI N
Trang 47LIỆT Kấ XÂU NHỊ PHÂN ĐỘ DÀI N
Bài toán liệt kê xâu nhị phân độ dài n dẫn về việc liệt kê các phần
Để cài đặt vũng lặp liệt kờ cỏc phần tử của S k , dễ thấy là ta cú
thể sử dụng vũng lặp for
trờn PASCAL: for y:= 0 to 1 do
hoặc trờn C: for (y=0;y<=1;y++)
Trang 48LIỆT KÊ XÂU NHỊ PHÂN ĐỘ DÀI N
Cây liệt kê dãy nhị phân độ dài 3
48
Trang 49printf("Xau thu %2d ",count);
for(int i=1 ; i<= n ;i++)
printf("%d ", b[i]);
printf("\n");
}
void Xau(int i) {
for (int j = 0; j<=1; j++) { b[i] = j;
if (i==n) Ghinhan();
else Xau(i+1); } }
int main() {
printf("n = ");
scanf("%d",&n);
count = 0; Xau(1);
printf("Count = %d ", count); }
Trang 50CÂY LIỆT KÊ DÃY NHỊ PHÂN ĐỘ DÀI 3
Trang 51CÂY LIỆT KÊ DÃY NHỊ PHÂN ĐỘ DÀI 3
51
Trang 52CÂY LIỆT KÊ DÃY NHỊ PHÂN ĐỘ DÀI 3
52
Trang 53CÂY LIỆT KÊ DÃY NHỊ PHÂN ĐỘ DÀI 3
53
Trang 54L IỆT KÊ CÁC M - TẬP CON CỦA N - TẬP
Trang 55L IỆT KÊ CÁC M - TẬP CON CỦA N - TẬP
Bài toán: Liệt kê các tập con m phần tử
của tập N = {1, 2, , n}
tập:
Trang 56GIẢI QUYẾT 2 VẤN ĐỀ MẤU CHỐT
của PASCAL: for y:= a[k-1]+1 to n-m+k do
của C: for (y=a[k-1]+1;y<=n-m+k;y++)
Trang 57printf("Tap con thu %i ",count);
for (i=1 ; i<= m ;i++)
int main() { printf("n, m = ");
scanf("%i %i",&n, &m); printf("\n"); a[0]=0; count = 0; MSet(1);
printf(“Count = %d ", count);
getch();
}
Trang 58CÂY LIỆT KÊ S(5,3)
Trang 59LIỆT KÊ HOÁN VỊ
Trang 60LIỆT KÊ HOÁN VỊ
1, 2, , n lµ tËp
Bài toán: Liệt kê tất cả các phần
tử của n
Trang 61GIẢI QUYẾT 2 VẤN ĐỀ MẤU CHỐT
Râ rµng S1 = N Gi¶ sö ta ®ang cã ho¸n vÞ
Trang 62MÔ TẢ SK
Xây dựng hàm nhận biết UCV:
function UCV(j,k: integer): boolean;
Trang 64printf("Hoan vi thu %i ",count);
for (i=1 ; i<= n ;i++) {
}
Trang 65}
Trang 66CÂY LIỆT KÊ HOÁN VỊ CỦA 1, 2, 3
Trang 67T HE N -Q UEENS P ROBLEM
Trang 68THE N-QUEENS PROBLEM
Giả sử ta có 8 con hậu
và bàn cờ quốc tế
Trang 69THE N-QUEENS PROBLEM
Có thể xếp các con hậu
sao cho không có hai
con nào ăn nhau hay
không
?
Trang 70THE N-QUEENS PROBLEM
Hai con hậu bất kỳ không
đƣợc xếp trên cùng một
dòng
Trang 71THE N-QUEENS PROBLEM
Hai con hậu bất kỳ không
đƣợc xếp trên cùng một
cột
Trang 72THE N-QUEENS PROBLEM
Hai con hậu bất kỳ không
được xếp trên cùng một
đường chéo!
Trang 73THE N-QUEENS PROBLEM
n cột
Trang 74THE N-QUEENS PROBLEM
Xét bài toán xếp n con
hậu lên bàn cờ kích thước
n x n
Trang 75BÀI TOÁN XẾP HẬU
Liệt kê tất cả các cách xếp n quân Hậu trên bàn cờ nn
sao cho chúng không ăn được lẫn nhau, nghĩa là sao cho không có hai con nào trong số chúng nằm trên cùng một dòng hay một cột hay một đường chéo của bàn cờ
Trang 76BIỂU DIỄN LỜI GIẢI
Đánh số các cột và dòng của bàn cờ từ 1 đến n Một cách xếp hậu có thể biểu diễn bởi bộ có n thành phần (a1, a2 , , an), trong đó ai là toạ độ
cột của con Hậu ở dòng i
Các điều kiện đặt ra đối với bộ (a1, a2 , , an):
ai aj , với mọi i j (nghĩa là hai con hậu
ở hai dòng i và j không được nằm trên cùng
Trang 77PHÁT BIỂU BÀI TOÁN
Nhƣ vậy bài toán xếp Hậu dẫn về bài toán
liệt kê các phần tử của tập:
D={(a1, a2, , an) Nn:
ai ≠ aj và |ai – aj| ≠ |i – j|, i ≠ j}
Trang 78for (i=1; i<k; i++)
if ((j == a[i])||(fabs(j-a[i])== k-i)) return 0; return 1;
}
Trang 79count++; printf("%i ",count);
for (i=1; i<=n;i++) printf("%i ",a[i]); printf("\n");
}
int UCVh(int j, int k) {
int i;
for (i=1; i<k; i++)
if ((j==a[i])||(fabs(j-a[i])==k-i)) return 0; return 1;
}
Trang 80int Hau(int i){ int j;
Trang 8181
Toán rời rạc - NĐN
Trang 82CHÚ Ý
Rõ ràng là bài toán xếp hậu không phải là luôn có lời giải, chẳng hạn bài toán không
có lời giải khi n=2, 3 Do đó điều này cần
đƣợc thông báo khi kết thúc thuật toán
Thuật toán trình bày ở trên là chƣa hiệu quả Nguyên nhân là ta đã không xác định đƣợc chính xác các tập UCV vào các vị trí của lời giải
Trang 83THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 84THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
ROW 1, COL
1
Trang 85THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 86THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 87THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 88THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 89THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 90THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 91THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 92THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 93THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 94THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
4
Trang 95THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 96THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Đẩy con hậu ở
Trang 97THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 98THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 99THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 100THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 101THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 102THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 103THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 104THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 105THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 106THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 107THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 108THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 109THUẬT TOÁN LÀM VIỆC NHƢ THẾ NÀO
Trang 110M ỘT LỜI GIẢI CỦA BÀI TOÁN XẾP HẬU KHI N = 8