Ứng dụng của giải thuật Backtracking Để giải quyết các bài toán thỏa mãn ràng buộc constraint satisfaction problems như crosswords, verbal arithmetic, Sudoku, ... Ý tư
Trang 1Backtracking algorithm
Trang 2Nội dung
Tư tưởng giải thuật
Giải thuật tìm hoán vị
Giải thuật mã đi tuần
Giải thuật tám hậu
Trang 3Backtracking algorithm
Là 1 giải thuật chung để tìm tất cả lời giải
cho 1 bài toán, bằng cách xây dựng từng bước các ứng viên (candidate) cho lời
giải và loại bỏ ("backtracks") 1 ứng viên
nào đó ngay khi phát hiện ứng viên đó
không thể dẫn đến 1 lời giải hợp lệ
Trang 4Backtracking algorithm
Bài toán tiêu biểu:
Tám hậu eight queens puzzle: 1 ứng viên đáng kể cho bài toán là sắp xếp k hậu vào k hàng đầu tiên của bàn cờ trong những hàng và cột khác nhau sao cho không có 2 hậu nào tấn công nhau Bất kz lời giải nào mà chứa 2 hậu có thể tấn công nhau đều phải loại trừ ngay vì không thể nào đưa đến kết
quả cuối cùng được
Trang 5Ứng dụng của giải thuật Backtracking
Để giải quyết các bài toán thỏa mãn ràng buộc
(constraint satisfaction problems) như
crosswords, verbal arithmetic, Sudoku,
Để giải các bài toán tối ưu hóa tổ hợp
(combinatorial optimization problems) như
parsing, knapsack problem …
Trang 6Ý tưởng phương pháp
Có thể xem nghiệm bài toán là một vector x
= (x1, x2, ,xn) mà xi được chọn trong Ai
nào đó
Giả sử đã chọn được k-1 thành phần x1, x2, ., xk-1 của x
Kế đến chọn thành phần xk bằng cách duyệt mọi khả năng có thể (trong Ak) để đề cử cho x
Trang 7Ý tưởng phương pháp
Với mỗi khả năng j, kiểm tra xem có chấp nhận được không, có 2 trường hợp:
Nếu chấp nhận j thì xác định xk theo j, khi
k = n thì có một lời giải, ngược lại thì tiếp tục xác định xk+1
ƒNếu thử tất cả các khả năng xk∈ Ak mà không có khả năng nào được chấp nhận thì quay lui lại bước trước để xác định lại
Trang 8Ý tưởng phương pháp
Tại mỗi bước đi qua, khi xác định xk, cần phải ghi nhớ những khả năng nào đã được thử để tránh trùng lặp
Có thể sử dụng một stack để ghi nhớ
những khả năng đã được thử ⇒ dùng kỹ
thuật đệ qui để thiết kế thuật toán
Trang 9Lược đồ giải thuật
Trang 10Nhận xét về lược đồ giải thuật
Cần chỉ rõ tập khả năng {1, …, nk} và kiểm tra
<accepting j>
Nói chung, ngoài sự phụ thuộc vào j, các xi còn phụ thuộc vào việc chọn các thành phần ở các bước trước
Vì vậy, có thể phải ghi nhớ trạng thái của quá
trình tìm kiếm sau khi xác định xk theo j và trả lại trạng thái cũ sau lời gọi Back_Tracking(k+1)
Các trạng thái được ghi nhận bởi biến toàn cục
Trang 12Đặc điểm của giải thuật backtracking
“Các bước trong giải thuật đều hướng về lời giải đầy đủ và ghi lại thông tin mỗi bước mà
sau đó nó có thể bị tháo gỡ và xóa đi khi phát
hiện rằng bước này đã không dẫn đến lời giải
đầy đủ, tức là một bước đi dẫn đến “ tình thế
bế tắc ”(dead-end) (Hành vi này được gọi là
quay lui -bactracking.)
Trang 13 ƒpk nhận giá trị j =1, 2, , n và khác với p1, p2, , pk-1
Dùng biến logic bj (j =1, , n) để ghi nhận j đã được
gán cho một pi trong hoán vị
Các bj được khởi tạo là true và được gán bằng false nếu đã sử dụng j
Trang 14Ví dụ
Trang 15Knight’s Tour Problem
Trang 16Knight’s Tour Problem
Cho một bàn cờ n n với n 2 ô Quân mã – di
chuyển theo luật chơi cờ vua – được đặt trên bàn
cờ tại ô đầu tiên có tọa độ x0, y0
Cần tìm một lộ trình gồm n 2 –1 bước sao cho phủ
toàn bộ bàn cờ (mỗi ô được viếng đúng một lần)
Để tiến tới bài toán phủ n2 ô là xét bài toán:
Thực hiện bước đi kế tiếp, hay
Phát hiện rằng không kiếm được bước đi hợp lệ kế tiếp
Trang 17Ý tưởng giải thuật tìm bước đi kế tiếp
procedure try next move;
begin initialize selection of moves;
try next move;
if not successful then erase previous recording end
Trang 18Cách biểu diễn dữ liệu
• Biểu diễn bàn cờ bằng ma trận h
type index = 1 n ;var h: array[index, index] of integer;
• Biểu diễn trạng thái các ô cờ
h[x, y] = 0: ô <x,y> chưa hề được viếngh[x, y] = i: ô <x,y> đã được viếng tại bước
chuyển thứ i (1 i n2)
• Điều kiện “board not full” “i < n2”
• Gọi u, v: tọa độ của ô sẽ chuyển đến
•
Trang 19Tinh chỉnh giải thuật
procedure try(i: integer; x,y : index; var q: boolean);
var u, v: integer; q1 : boolean;
begin initialize selection for moves;
repeat let u, v be the coordinates of the next move ;
if (1un) (1vn) (h[u,v]=0) then
Trang 20Cho tọa độ của ô hiện hành <x, y>, có 8 khả năng để chọn ô kế tiếp <u, v> để đi tới Chúng được đánh số từ 1 đến 8 như sau:
Trang 21Sự tinh chế sau cùng
Cách đơn giản nhất để đạt được tọa độ u,
v từ x, y là bằng cách cộng độ sai biệt toạ
độ tại hai mảng a và b.
Và k được dùng để đánh số ứng viên
(candidate) kế tiếp Có tối đa 8 ứng
viên cho 1 lần di chuyển
Trang 22for j:=1 to n do
write(h[i,j]:5); writeln
end else writeln (‘NO
SOLUTION’)
Trang 23Giải thuật mã đi tuần
program knightstour (output);
const n = 5; nsq = 25;
type index = 1 n
var i,j: index; q: boolean;
s: set of index;
a,b: array [1 8] of integer;
h: array [index, index] of integer;
Trang 24procedure try (i: integer; x, y: index; var q:boolean);
var k,u,v : integer; q1: boolean;
try(i+1, u,v,q1);
if q1 then h[u,v]:=0 end
else q1:=true end
until q1 (k =8);
Trang 25Thủ tục đệ quy được khởi
động bằng lệnh gọi với tọa
độ khởi đầu x0, y0 , từ đó mã
bắt đầu đi tuần.
Trang 26Bài toán 8 con hậu
Eight queens puzzle
Bài toán này đã được C.F Gauss khảo sát năm
1850, nhưng ông ta không hoàn toàn giải quyết được
“Tám con hậu được đặt vào bàn cờ sao cho
không có con hậu nào có thể tấn công con hậu nào”.
Luật cờ: Một con hậu có thể tấn công các con
Trang 27Eight queens puzzle
Trang 28Cách biểu diễn dữ liệu
• Làm cách nào để diễn tả 8 con hậu trên bàn cờ?
var x: array[1 8] of integer;
a: array[1 8] of Boolean;
b: array[b1 b2] of Boolean;
c: array[c1 c2] of Boolean;
với
x[i] chỉ vị trí của con hậu trên cột thứ i;
a[j] cho biết có con hậu trên hàng thứ j hay không?
b[k] cho biết có con hậu trên đường chéo thứ k
Trang 29Giải thuật tổng quát
procedure try (i: integer);
try (i + 1);
if not successful then remove queen end
Trang 30Tinh chỉnh giải thuật
•Trên cùng một đường chéo chiều
Trang 31Tinh chỉnh giải thuật
• setqueen được tinh chế như sau:
x[i]:=j; a[j]:=false;
b[i+j]:=false;c[i-j]:=false;
• removequeen được tinh chế như sau :
a[j] = true; b[i+j] = true ; c[i-j] := true
Điều kiện safe được diễn tả như sau:
a[j] b[i+j] c[i-j]
Trang 32Giải thuật sau cùng
try (i+1, q);
if q then begin
a[j]:=true; b[i+j]:=true;
c[i-j]:=true
end end else q:=true
Trang 33Giải thuật sau cùng (tt)
begin
for i:= 1 to 8 do a[i]:=true;
for i:= 2 to 16 do b[i]:=true;
for i:= –7 to 7 do c[i]:=true;
Trang 34Sự mở rộng: Tìm tất cả các lời giải
Sự mở rộng là tìm không chỉ một lời giải
mà tất cả những lời giải của bài toán đã
cho
tìm thấy và ghi lại, ta tiếp tục xét ứng viên
kế trong quá trình chọn ứng viên một cách
Trang 35Giải thuật tổng quát
procedure try(i: integer);
Trang 36Giải thuật mở rộng
Để đơn giản hóa điều kiện dừng của quá trình
chọn, phát biểu repeat được thay thế bằng phát biểu for
Trang 37if a[j] b[i+j] c[i-j] then begin
Trang 38begin
for i:= 1 to 8 do a[i]:=true;
for i:= 2 to 16 do b[i]:=true;
for i:= –7 to 7 do c[i]:=true;
try(1);
end
Giải thuật mở rộng có thể sản sinh tất cả 92 lời giải
cho bài toán 8 con hậu
Nhưng thật ra chỉ có 12 lời giải thật sự khác biệt nhau
Trang 41Mười hai lời giải đó được liệt kê trong bảng sau: