Nếu thử tất cả các khả năng mà không có khả năng nào chấp nhận được thì quay lại bước trước xác định lại ai-1.. Nội dung của thuật toán này rất phù hợp với việc gọi đệ quy.[r]
(1)Thuật toán quay lui ứng dụng
Giả thiết cấu hình cần tìm mơ tả phận gồm n thành phần a1, a2, an Giả sử tìm i - thành phần a1, a2, ai-1, ta tìm thành phần thứ i cách duyệt tất khả Với khả j kiểm tra xem có chấp nhận khơng Xảy rahai trường hợp
nhận xác định theo j kiểm tra xem i = n chưa, i = n ta ghi nhận cấu hình, cịn i < ta gọi tiến hành xác định ai+1
Nếu thử tất khả mà khả chấp nhận quay lại bước trước xác định lại ai-1
Nội dung thuật toán phù hợp với việc gọi đệ quy Ta có thủ tục đệ quy sau đây: Procedure Try (i:tinteger);
Var j:integer; Begin
For j:=1 to n if chấp nhận j then begin
xác nhận aj theo j if i=n then
else try(i+1); end;
end;
Để minh hoạ cho thuật toán ta áp dụng giải toán xếp hậu:
Nội dung toán: Liệt kê tất cách xếp hậu bàn cờ NxN cho chúng không ăn
Giải: Ta xếp n hậu n dòng, Theo nguyên lý nhân ta có nn cách xếp thoả mãn
điều kiện đầu bải Để làm điều ta dùng thủ tục đệ quy mô tả để giải Ta đánh ghi số cột dòng bàn cờ từ đến n, cách xếp ứng với gồm a1,a2, ,an với
= j (j=1,2, ,n) có nghĩa hậu thứ i đặt vào cột j Giả sử ta chọn i-1 hậu cách duyệt tất khả
Quan trọng ta tìm điều kiện chấp nhận j, hậu đứng ô bàn cờ có nhiều bốn hướng đi(đường dọc, đường ngang hai đường chéo)
Vậy điều kiện chấp nhận thứ i thoả mãn không nằm đường tất i-1 hậu xếp Bởi n hậu xếp hàng nên đường ngang chúng khơng chiến nhau, chọn hậu thư i cần kiểm tra xem đường chéo đường dọc chúng có chiếu vào hậu xếp khơng? Để kiểm tra điều đường ta dùng biến trạng thái
* Đường dọc kiểm soát biến b[j],(j=1,2, ,n)
* Một đường chéo kiểm soát biến c[i+j],i+j={2, ,2n} * Cịn đường chéo kiểm sốt biến d[i-j],i-j={1-n, ,n-1}
(2)biến gán giá trị False xếp xong hậu thứ i, trả lại giá trị true sau gọi Result hay Try(i+1) Ta có chương trình Pascal sau :
Program XepHau; Uses crt;
var
n : integer;
a:array[1 30] of integer; b:array[1 30] of boolean; c:array[2 60]of boolean; count,d:word; Procedure Init; Var i:integer; Begin
Write('Cho rong ban co n= '); Readln(n);
Count:=0; d:=0;
For i:=1 to n b[i]:=true; For i:=2 to 2*n c[i]:=true; For i:=1-n to n-1 d[i]:=true; End; Procedure Result; Var i:integer; Begin d:=d+1; count:=count+1;
Write('Cach xep thu',count:5,'.'); for i:=1 to n write(a[i]:2); Writeln;
if d = 24 then begin readln; d : = 0; end; end; Procedure try(i:integer); Var
j : integer; Begin
For j:=1 to n do
If (b[j]) and (c[i + j]) and (d[i - j]) then Begin
(3)Write ('An Enter de ket thuc:'); Readln;
End.
Để hiểu sâu sắc thuật toán này, mời bạn đọc làm số toán sau: Bài 1: Hãy viết chương trình liệt kê tất dãy nhị phân có độ dài n Bài 2: Hãy viết chương trình liệt kê hốn vị {1,2, ,n}
Bài 3: Hãy viết chương trình liệt kê tổ hợp chập m {1,2, ,n} Bài 4: Hãy viết chương trình liệt kê tất chu trình Haminton đồ thị