• Biết sử dụng giải thuật quay lui để giải một số bài toán... • Dùng để giải quyết bài toán liệt kê của lý thuyết... 8.2.3- Thuật toán sinh tổng quát.Procedure Generate Begin c = Initia
Trang 1Chương 8 Phương pháp sinh
và Thuật toán quay lui.
Trang 2Mục tiêu
• Giải thích được sinh dữ liệu là gì
• Biết sử dụng một số giải thuật sinh
• Biết sử dụng giải thuật quay lui để giải một
số bài toán
Trang 4Ôn tập
• Hàm đệ quy là hàm mà trong thân hàm lại gọi chính nó
• Hàm đệ quy kém hiệu qủa vì: tốn bộ nhớ
va gọi hàm qúa nhiều lần Tuy nhiên viết hàm đệ quy rất ngắn gọn.Tuy nhiên nhiều giải thuật vẫn phải dùng kỹ thuật đệ quy vì việc khử đệ quy không dễ dàng
• Vòng lặp và stack là những kỹ thuật giúp
Trang 58.1- Bài toán tổ hợp
• Có n biến x1, x2, x3, , xn
• Mỗi biến xi có thể mang trị thuộc về 1 tập hợp Pi
Miền của bài toán là tập tích
P1 x P2 x P3 x x Pn
• Phép gán trị (assignment): Là một bộ trị
a1, a2, a3, , an
Trong đó a1 ai ∈ Pi
• Một lời giải của bài toán là 1 phép gán trị.
• Một phép gán trị được gọi là một cấu hình.
Trang 6Bài toán tổ hợp
• Ví dụ: Có 3 nhân viên bảo vệ
làm 3 ca sáng, chiều tối Trong
Miền trị của 3 biến là
{ a,b,c } mô tả cho 3 bảo vệ.
3*2*1 = 3! = 6.
Trang 7Độ phức tạp: n m với n: số phần tử trung bình của mỗi miền trị,
m: là số miền trị
Trang 98.2- Phương pháp sinh
(Generating)
Trang 108.2.1- Định nghĩa
• Sinh: Tạo ra dữ liệu.
• Phương pháp sinh: Từ dữ liệu ban đầu, sinh ra
dữ liệu kế tiếp cho đến khi kết thúc.
• Dùng để giải quyết bài toán liệt kê của lý thuyết
Trang 11Thứ tự từ điển
• S1 < S2 nếu có 1 vị trí i tại đó S1[ i ] < S2[ i ]
Trang 128.2.2- Một ví dụ
Bài toán:Tìm số chuỗi có
độ dài 3 ký tự xyz với
Cách sinh:Lấy trị kết tiếp của
mỗi miền trị theo cơ chế
vòng tròn
Dùng thứ
tự từ điển
để so sánh các phép gán trị
Ví dụ: adm < adn
Trang 138.2.3- Thuật toán sinh tổng quát.
Procedure Generate
Begin
c = InitialConfigure; //cấu hình ban đầu
Process (c); // xử lý cấu hình đang có
if c=LastConfigure then Stop:=true
else stop := false;
while (not stop) do
Begin
//Sinh cấu hình kế tiếp từ cấu hình đang có
c=getNextConfigure(c);
Process (c); // xử lý cấu hình này
if c= LastConfigure then stop = true;
End;
End;
Trang 148.2.4- Bài toán chuỗi 3 ký tự
Trang 15Bài toán chuỗi 3 ký tự
Trang 16Bài toán chuỗi 3 ký tự
Trang 178.2.5- Bài toán liệt kê các tập con
• Với tập cha là 4 phần tử X={ a, b, c, d }, có thể dùng
mảng “0111” mô tả cho tập con { b,c,d }
Mỗi tập con được biểu diễn là một chuỗi (xâu) nhị phân.
• Trạng thái khởi tạo: “0000” mang ý nghĩa tập trống.
• Trạng thái kết thúc: “1111” mang ý nghĩa là tập cha.
Trang 18Bài toán liệt kê các tập con
• Với tập cha gồm 4 phần tử, có 2 4 tập con b với các biểu diễn:
Trang 19Bài toán liệt kê các tập con
• Cách cộng thêm 1 vào chuỗi nhị phân:
Trang 20Bài toán liệt kê các tập con
Trang 21Bài toán liệt kê các tập con
Thêm dòng: delete[ ] vars;
Thêm dòng:
Stop = LastConfigure(vars,n);
Trang 22Bài toán liệt kê các tập con
Trang 23Bài toán liệt kê các tập con
• Nhận xét: Có thể tối ưu lại chương trình
để bớt đi các vòng lặp
Trang 24Bài toán liệt kê các tập con
Kết hợp việc tìm cấu hình kế với việc kiểm tra
ngưng lặp
Trang 25Bài toán liệt kê các tập con
Thêm dòng: delete[ ] vars;
Trang 278.2.6- Bài toán tập con k-phần tử
• Liệt kê các tập con k phần tử của tập n phần tử.
Tổ hợp n chập k
Trang 28Bài toán tập con k-phần tử
• Ánh xạ tập hợp bất kỳ n phần tử vào tập X={ 1,2 n }
• Một tập con k phần tử của X là một bộ có thứ tự a1 a2 a3 ak với
1≤ a1< a2 < a3 < < ak ≤ n
Trang 29Bài toán tập con k-phần tử
• Tập con đầu: { 1,2,3, ,k }
Ví dụ { 1,2,3 } với k=3, n=5
• Tập con cuối:{ (n-k+1), (n-k+2) , , n }
Ví dụ: { 3,4,5 } với k=3, n=5
Trang 30Cách sinh tập con kế tiếp từ tập con đã có
a 1 a 2 a 3 a 4 a k , chỉ số ở đây đi từ 1
(1) Tìm vị trí đầu tiên từ bên
phải 1 vị trí i sao cho a[i] ≠
n-k+i
i=k;
while (a[i]==n-k+i) i ;
(2) Thay a[i] bằng a[i] +1
Trang 31Bài toán tập con k-phần tử
Trang 32Bài toán tập con k-phần tử
Thêm dòng: delete[ ] result;
Trang 33Bài tập
• Tạo tập tin văn bản có tên Tapcon.in
chứa nội dung : 10 4
• Ý nghĩa: số đầu: số phần tử của tập, số kế tiếp là số phần tử của tập con
• Dùng kỹ thuật sinh, viết chương trình ghi các tập con của tập này lên file
Tapcon.out
Trang 348.2.7-Bài toán hoán vị tập n phần tử
A = (a1, a2, ,ak-1, a k, an ) là hoán vị trước của
A’= (a’1, a’2, ,a’k-1, a’ k, a’n ) nếu tìm được vị trí k sao cho
a k < a’ k
• Ví dụ : 1234567 là hoán vị trước của
1234657
Trang 35hoán vị a[j], a[k]
Đảo mảng con từ a[j+1] đến a[n]
chỉ số đi từ 1
Trang 36Giải thuật tìm hoán vị kế tiếp
• trạng thái trước {1,3,4,2} trạng thái sau: {1,4,2,3}
Trang 37Bài toán hoán vị
{1,2,3,4,5, , n} {n, , 5,4,3,2,1}
Trang 38Bài toán hoán vị Tìm chỉ số lớn
nhất j mà aj<aj+1
từ phía phải vì đây là phần tử sẽ
bị hoán vị.
Tìm vị trí đầu tiên
k đi ngược từ cuối tập trị với a[k] > a[j]
Hoán vị a[j], a[k] Đảo ngược nhóm trị
a[j+1], a[n]
Trang 39Bài toán hoán vị
Thêm dòng: delete[ ] vars;
Trang 40Bài toán hoán vị - Kết qủa
4!= 24 hoán vị
Trang 428.2.8- Bài toán chia 1 số nguyên thành
Trang 43Bài toán chia số nguyên
n= 20 , trạng thái k=15
5 4 1 1 1 1 1 1 1 1 1 1 1 1 1
//số phải giảm là 4, số đầu tiên >1 từ bên phải, vị trí
i=2 với chỉ số đi từ 1, giảm trị này 1 đơn vị
5 3 // số trị phải chia lại là 14 = số trị 1 bên phải +1=
k-i+1=15-2+1=14
Số sẽ chia ra đi từ a[2]=3, 14/3 được 4 lần trị thêm
vào là 3, dư 2
5 3 3 3 3 3 ( k=i+SốLầnBằngTrị)
5 3 3 3 3 3 2 //thêm phần dư vào cuối (k++)
Đây chính là trạng thái kế tiếp- xong
Trang 44Bài toán chia số nguyên
Trang 45Bài toán chia số nguyên
Trang 46Bài toán chia số nguyên
Trang 47Bài toán chia số nguyên
Thêm dòng: delete[ ] vars;
Trang 48Bài toán chia số nguyên
Trang 498.3-Thuật toán quay lui
• Với bài toán liệt kê phức tạp, thuật toán
backtracking được áp dụng
Trang 50backtracking- Ý tưởng
• Tập biến x1 x2 x3 xn có thứ tự
• Mỗi biến có thể có 1 miền trị riêng
hợp
• Nếu tìm được trị phù hợp thì tiếp tục sang biến xi+1
Trang 51Backtracking- Nhận xét
• Phải ghi nhớ các bước đã đi qua để có thể lùi về trạng thái trước đó Cơ chế stack Kỹ thuật đệ quy rất phù hợp
• Nếu lưu trữ được các khả năng (trị của miền trị) đã được thử thì sẽ tránh được những việc lặp không cần thiết
Trang 52Backtracking- Giải thuật tổng quát
if (i==n) Process (CấuHìnhCủa X)
else Try (i+1, X, n)
Trang 53Giải thuật tổng quát
x 1 x 2 x 3 x 4
Bắt đầu
D 1 D 2 D 3 D 4
for j= TrịĐầu TrịCuối của
D i
Trang 54
Giải thuật tổng quát
Trang 558.3.1-Bài toán chuỗi bit
• Tập biến: char vars[], int n bit
• Nhận xét: Miền trị chung D={‘0’, ‘1’}
• Bit nào cũng được chấp nhận Không
Trang 56Bài toán chuỗi bit
Trang 57Bài toán chuỗi 4 bit
Trang 588.3.2-Bài toán liệt kê tập con k phần tử
của tập n phần tử
Thêm dòng: delete[ ] result;
Trang 598.3.3- Bài toán hoán vị
• Liệt kê các hoán vị của một tập n phần tử
• Một hoán vị được biểu diễn dạng p1p2p3 pnvới pi ≠pj với i ≠ j, mỗi pi sẽ nhận trị từ 1 n
được dùng Cần quản lý trị j này đã
dùng hay chưa mảng B, n phần tử B[j]
mang trị TRUE mô tả rằng trị j chưa được
dùng Ban đầu mọi B[j]= TRUE
Trang 60Bài toán hoán vị
B[j]=FALSE
• Sau khi thực hiện xong một lời giải (i==n) (
để đi hết tập biến) phải trả lại B[j]= TRUE
để dùng cho lần sau
Trang 61Bài toán hoán vị
Trang 62Bài toán hoán vị
Trang 63Bài tập
• Làm lại các bài mẫu về giải thuật quay lui nhưng ghi kết qủa lên file
Trang 65Bài tập
• Gọi hàm:
Trang 67Tóm tắt
• Giải thuật hồi quy- backtracking
(1) Tại 1 thời điểm, chỉ xét biến thứ i của tập biến (2) Với mọi trị j trong miền trị của biến này
Trang 68Tóm tắt
với n là số biến, m là số phần tử trung
bình của các miền trị của các biến
• Với n,m lớn, nếu phải xét hết mọi khả
năng thì bài toán khó khả thi bằng máy
tính vì chi phí qúa cao