1. Trang chủ
  2. » Trung học cơ sở - phổ thông

Chuyên đề quay lui

6 36 0

Đ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 6
Dung lượng 66,07 KB

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

Nội dung

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... Liệt kê các dãy nhị phân độ dài N.[r]

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;

Trang 2

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);

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';

Trang 3

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ụ

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

Trang 4

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:

Trang 5

 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';

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;

Trang 6

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: 06/03/2021, 04:00

TỪ KHÓA LIÊN QUAN

w