1. Trang chủ
  2. » Giáo án - Bài giảng

Bài giảng chuyên đề quay lui.

4 217 6

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 4
Dung lượng 100,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

ĐỆ QUY QUAY LUI DỄ HIỂU NHẤT. Có tài liệu còn gọi nó là ” Thử và sai”. đã là đệ quy quay lui thì trong thủ tục của nó là thủ tục đệ quy và có “quay lui”. Ta tìm hiểu quay lui ở đâu và như thế nào? Trước hết ta xét ví dụ: Một từ được gọi là chân chính loại M, N nếu nó được xây dựng từ tập hợp gồm M ký tự, có độ dài N và không có 2 từ con nào liên tiếp giống nhau. Giả sử tập M={‘1’, ‘2’, ‘3’} Ví dụ: 1232; 2123; 1231 là những từ chân chính loại 3,4; còn 1123;1212;1233 là những từ không phải là từ chân chính loại 3,4. Tất nhiên ở đây không phải là ta xây dựng tất cả các từ có độ dài N, sau đó loại trừ những từ không thoả mãn, mà ta lần lượt xây dựng các xâu. Khởi tạo ban đầu là xâu rỗng, ta tiến hành ghép các ký tự , tại mỗi bước ghép ta kiểm tra xem nó có thoả mãn điều kiện bài toán không( có hai từ con liền nhau giống nhau không). Nếu thoả mãn ta kiểm tra xem xâu có độ dài bằng N hay chưa. Nếu xâu đã có độ dài bằng N ta in kết quả, nếu chưa có độ dài bằng N ta ghép bước tiếp. Nếu tất cả các ký tự được chọn để ghép đều không thoả mãn điều kiện bài toán thì việc chọn ký tự trước đó sai, ta phải xoá ký tự trước đó đi và thay bởi ký tự khác để bước ghép tiếp được thành công. Việc xoá ký tự trước đó để tìm ký tự khác ghép vào người ta gọi là quay lui. Trong trường hợp xâu có độ dài bằng N( đã thoả mãn bài toán) thì ta được một kết quả. Để tìm kết quả khác, ta xoá ký tự cuối cùng này đi rồi tìm ký tự khác để ghép vào cũng gọi là quay lui.

Trang 1

THUẬT TOÁN QUAY LUI BACKTRACKING I/ Giới thiệu:

Thuật toán quay lui dùng để giải bài toán liệt kê các cấu hình Mỗi cấu hình được xây dựng bằng cách xây dựng từng phần tử, mỗi phần tử được chọn bằng cách thử tất cả các khả năng Giả sử cấu hình cần liệt kê có dạng x[1 n], khi đó thuật toán quay lui thực hiện qua các bước:

1) Xét tất cả các giá trị x[1] có thể nhận, thử cho x[1] nhận lần lượt các giá trị đó Với mỗi giá trị thử gán cho x[1] ta sẽ:

2) Xét tất cả các giá trị x[2] có thể nhận, lại thử cho x[2] nhận lần lượt các giá trị đó Với mỗi giá trị thử gán cho x[2] lại xét tiếp các khả năng chọn x[3] … cứ tiếp tục như vậy đến bước: …

n) Xét tất cả các giá trị x[n] có thể nhận, thử cho x[n] nhận lần lượt các giá trị đó, thông báo cấu hình tìm được <x[1], x[2], …, x[n]>

Trên phương diện quy nạp, có thể nói rằng thuật toán quay lui liệt kê các cấu hình n phần tử dạng x[1 n] bằng cách thử cho x[1] nhận lần lượt các giá trị có thể Với mỗi giá trị thử gán cho x[1] bài toán trở thành liệt kê tiếp cấu hình n - 1 phần tử x[2 n]

II/ Mô hình của thuật toán quay lui có thể mô tả như sau:

procedure Try(i: Integer);

begin

for <mọi giá trị V có thể gán cho x[i]> do

begin

<Thử cho x[i] := V>;

if <x[i] là phần tử cuối cùng trong cấu hình> then

<Thông báo cấu hình tìm được>

else

begin

<Ghi nhận việc cho x[i] nhận giá trị V (nếu cần)>;

Try(i + 1); {Gọi đệ quy để chọn tiếp x[i+1]}

<Nếu cần, bỏ ghi nhận việc thử x[i] := V để thử giá trị khác>; end;

end;

end;

Thuật toán quay lui sẽ bắt đầu bằng lời gọi Try(1)

III/ Một số ví dụ:

1/ Viết chương trình in ra tất cả các hoán vị của n số tự nhiên đầu tiên (0<N<10) N nhập từ bàn phím.

Const

MaxN=100;

fi='hoanvi.inp';{chua so N}

fo='hoanvi.out';{moi dong chua mot hoan vi}

Var

x:array[1 MaxN] of integer;

b:array[1 MaxN] of boolean;

n:integer; f:text;

procedure Init;

var i:integer;

Begin

assign(f,fi);reset(f);

read(f,n);

for i:=1 to n do b[i]:=true;

close(f);

assign(f,fo);rewrite(f);

End;

Procedure PrintResult;

var i:integer;

Begin

for i:=1 to n do write(f,' ',x[i]); writeln(f);

End;

Procedure Try(i:integer);

Trang 2

Var j:integer;

Begin

for j:=1 to n do

if b[j] then

begin

x[i]:=j;

if i=n then PrintResult else

begin

b[j]:=false;

try(i+1);

b[j]:=true;

end;

end;

End;

BEGIN

Init;

Try(1);

Close(f);

END.

2 Liệt kê các dãy nhị phân độ dài N

Biểu diễn dãy nhị phân độ dài N dưới dạng x[1 n] Ta sẽ liệt kê các dãy này bằng cách thử dùng các giá trị {0, 1} gán cho x[i] Với mỗi giá trị thử gán cho x[i] lại thử các giá trị có thể gán cho x[i+1].Chương trình liệt kê bằng thuật toán quay lui có thể viết:

program BinaryStrings;

const

InputFile = 'BSTR.INP';

OutputFile = 'BSTR.OUT';

max = 30;

var x: array[1 max] of Integer;

n: Integer; f: Text;

procedure PrintResult; {In cấu hình tìm được, do thủ tục tìm đệ quy Try gọi khi tìm ra một cấu hình}

var i: Integer;

begin

for i := 1 to n do Write(f, x[i]);

WriteLn(f);

end;

procedure Try(i: Integer); {Thử các cách chọn x[i]}

var j: Integer;

begin

for j := 0 to 1 do {Xét các giá trị có thể gán cho x[i], với mỗi giá trị đó}

begin

x[i] := j; {Thử đặt x[i]}

if i = n then PrintResult {Nếu i = n thì in kết quả}

else Try(i + 1); {Nếu i chưa phải là phần tử cuối thì tìm tiếp x[i+1]}

end;

end;

begin

Assign(f, InputFile); Reset(f);

ReadLn(f, n); {Nhập dữ liệu}

Close(f);

Assign(f, OutputFile); Rewrite(f);

Try(1); {Thử các cách chọn giá trị x[1]}

Close(f);

end.

Vẽ cây ví dụ

Trang 3

3 Liệt kê các tập con k phần tử

Để liệt kê các tập con k phần tử của tập S = {1, 2, …, n} ta có thể đưa về liệt kê các cấu hình x[1 n],

ở đây các x[i] ∈ S và x[1] < x[2] < … < x[k] Ta có nhận xét:

x[k-1] ≤ x[k] - 1 ≤ n - 1

x[i] ≤ n - k + i

x[1] ≤ n - k + 1

Từ đó suy ra x[i-1] + 1 ≤ x[i] ≤ n - k + i (1 ≤ i ≤ k) ở đây ta giả thiết có thêm một số x[0] = 0 khi xét

i = 1

Như vậy ta sẽ xét tất cả các cách chọn x[1] từ 1 (=x[0] + 1) đến n - k + 1, với mỗi giá trị đó, xét tiếp tất cả các cách chọn x[2] từ x[1] +1 đến n - k + 2, … cứ như vậy khi chọn được đến x[k] thì

ta có một cấu hình cần liệt kê Chương trình liệt kê bằng thuật toán quay lui như sau:

program Combination;

const InputFile = 'SUBSET.INP';

OutputFile = 'SUBSET.OUT'; max = 30;

var x: array[0 max] of Integer;

n, k: Integer; f: Text;

procedure PrintResult; (*In ra tập con {x[1], x[2], …, x[k]}*)

var i: Integer;

begin

Write(f, '{');

for i := 1 to k - 1 do Write(f, x[i], ', ');

WriteLn(f, x[k], '}');

end;

procedure Try(i: Integer); {Thử các cách chọn giá trị cho x[i]}

var j: Integer;

begin

for j := x[i - 1] + 1 to n - k + i do

begin

x[i] := j;

if i = k then PrintResult

else Try(i + 1);

end; end;

begin

Assign(f, InputFile); Reset(F);

ReadLn(f, n, k); Close(f);

Assign(f, OutputFile); Rewrite(f);

x[0] := 0; Try(1); Close(f);

end.

4.Bài toán cái túi (Câu 3 đề thi cấp tỉnh V1 năm 2011-2012)

Một nhà thám hiểm cần đem theo một cái túi có trọng lượng không quá b Có n đồ vật cần đem theo Đồ vật thứ j có trọng lượng là aj và giá trị sử dụng là cj (j = 1, 2, 3, ,n) Hỏi rằng nhà thám hiểm cần đem theo các đồ vật nào để cho tổng giá trị sử dụng của các đồ vật đem theo là lớn nhất?

Input: Vào từ file văn bản CAITUI.INP:

• Dòng đầu ghi 2 số nguyên dương n và b (n < 100)

• Dòng thứ hai ghi các số nguyên không âm a1, a2, ,an

• Dòng thứ ba ghi các số nguyên không âm c1, c2, ,cn

Output: Ghi ra file CAITUI.OUT:

• Dòng đầu ghi tổng giá trị các đồ vật đem theo ứng với phương án tìm được

• Ghi chỉ số của các đồ vật đem theo

4 8

5 3 2 4

10 5 3 6

15

1 2

uses crt;

const fi='caitui1.inp';

Trang 4

fo='caitui.out';

var x,a,c,bestconfig:array[1 100] of integer;

n,best,sum,val,b:integer;

procedure input;

var f:text;

i,j,k:integer;

begin

assign(f,fi);reset(f);

readln(f,n,b);

for i:=1 to n do read(f,a[i]);

readln(f);

for i:=1 to n do read(f,c[i]);

close(f);

end;

procedure update;

begin

if val>=best then

begin

best:=val;

bestconfig:=x;

end;

end;

procedure try(i:integer);

var j:integer;

begin

for j:= 0 to 1 do

if sum+j*a[i]<=b then

begin

x[i]:=j;

sum:=sum+x[i]*a[i];

val:=val+x[i]*c[i];

if i=n then update

else try(i+1);

sum:=sum-x[i]*a[i];

val:=val-x[i]*c[i];

end;

end;

procedure init;

begin

best:=-32767;

sum:=0;

val:=0;

end;

procedure xuat;

var i:integer;

begin

writeln('Gia tri lon nhat la ',best);

for i:=1 to n do if bestconfig[i]=1 then write(i,' ');

end;

begin

clrscr;

input;

init;

try(1);

xuat;

readln

end.

4 8

5 3 2 4

10 5 3 6

5 15

5 6 2 7 10

6 8 8 8 10

Ngày đăng: 08/09/2019, 13:07

TỪ KHÓA LIÊN QUAN

w