Thuật toỏn quay lui

Một phần của tài liệu Giáo trình toán rời rạc đh sư phạm kỹ thuật nam định (Trang 59)

4.3.1. Giới thiệu thuật toỏn

Nội dung chớnh của thuật toỏn này là việc xõy dựng dần cỏc thành phần của cấu hỡnh bằng cỏch thử tất cỏc khả năng. Giả thiết cấu hỡnh cần tỡm được mụ tả bằng một bộ gồm n thành phần x1, x2,…, xn. Giả sử đó xỏc định được i -1 thành phần x1, x2,…, xi-1 (mà ta sẽ gọi là lời giải bộ phận cấp i- 1), bõy giờ ta xỏc định thành phần xi bằng cỏch duyệt tất cả cỏc khả năng cú thể đề cử cho nú (đỏnh số cỏc khả năng từ 1 đến ni ). Với mỗi khả năng j, kiểm tra xem j cú chấp nhận được khụng. Xảy ra hai trường hợp:

- Nếu chấp nhận j thỡ xỏc định xi theo j. Sau đú nếu i = n thỡ ta được một cấu hỡnh, cũn trỏi lại ta tiến hành xỏc định xi+1.

- 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 xi-1.

Điểm quan trọng của thuật toỏn là phải ghi nhớ tại mỗi bước đó đi qua những khả năng nào đó thử để trỏnh trựng lặp. Rừ ràng những thụng tin này cần được lưu trữ theo cơ cấu ngăn xếp (Stack- Vào sau ra trước). Vỡ thế thuật toỏn này rất phự hợp với việc lập trỡnh trờn một ngụn ngữ chophộp gọi đệ qui. Bước xỏc định xi cú thể diễn tả qua thủ tục được tổ chức đệ qui dưới đõy: Procedure Try( i: integer);

Var j: integer; Begin

For j := 1 to ni do If <chấp nhận j> then

<Xỏc định xi theo j>

if i = n then <ghi nhận một cấu hỡnh> else try(i+1);

end; end;

Phần quan trọng nhất trong thủ tục trờn là việc đưa ra một danh sỏch cỏc khả năng đề cử và việc xỏc định giỏ trị biểu thức logic <Chấp nhận j>

thụng thường giỏ trị này, ngoài việc phụ thuộc j, cũn phụ thuộc vào việc đó chọn cỏc khả năng tại i –1 bước trước. Trong những trường hợp như vậy, cần ghi nhớ trạng thỏi mới của quỏ trỡnh tỡm kiếm sau khi <xỏc định xi theo j> và trả lại trạng thỏi cũ sau lời gọi Try(i+1). Cỏc trạng thỏi này được ghi nhận nhờ một số biến tổng thể, gọi là biến trạng thỏi.

Sau khi xõy dựng thủ tục đệ qui Try, đoạn chương trỡnh chớnh giải bài toỏn liệt kờ cú dạng:

Begin Init; Try(1); End.

trong đú Init là thủ tục khởi tạo cỏc giỏ trị ban đầu (nhập cỏc giỏ trị tham số, của bài toỏn, khởi gỏn cỏc biến trạng thỏi, biến đếm, ...)

4.3.2. Cỏc vớ dụ

Vớ dụ 4.4: Liệt kờ cỏc dóy nhị phõn độ dài n.

Giải: Biểu diễn dóy nhị phõn dưới dạng b1, b2,…, bn, trong đú bi{0,1}. Thủ tục đệ qui Try(i) xỏc định bitrong đú cỏc giỏ trị đề cử là 0 và 1. Cỏc giỏ trị này mặc nhiờn được chấp nhận mà khụng phải thoả món điều kiện gỡ. Thủ tục init nhập giỏ trị n và thủ tục Result đưa ra dóy tỡm được.

Chương trỡnh minh hoạ

Var

b:array[1..30] of 0..1; procedure init; Begin write('n=');readln(n); end; procedure result; var i:integer; begin

for i:=1 to n do write(b[i]:2); writeln; end; procedure Try(i:integer); var j:integer; begin for j:= 0 to 1 do begin b[i]:=j;

if i=n then result else try(i+1); end; end; Begin init; try(1); readln; End.

Vớ dụ 4.5. Liệt kờ cỏc hoỏn vị của tập n phần tử X = {1, 2, ..., n}.

Giải: Biểu diễn hoỏn vị dưới dạng a1, a2, …, an trong đú ai nhận giỏ trị từ 1 đến n và ai  aj với i  j. Cỏc giỏ trị từ 1 đến n được lần lượt đề cử cho ai,

nhớ đối với mỗi giỏ trị j xem nú đó được dựng hay chưa. Điều này được thực hiện nhờ một dóy biến logic bj, trong đú bj bằng true nếu j chưa được dựng. Sau khi xỏc định ai theo j cần gỏn giỏ trị false cho bj. Khi thực hiện xong Result hay Try(i+1) cần phải gỏn lại giỏ trị true cho bj.

Chương trỡnh minh hoạ

Var n:integer; a:array[1..30] of integer; b:array[1..30] of boolean; procedure init; var i:integer; Begin write('n=');readln(n);

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

procedure result; var i:integer; begin

for i:=1 to n do write(a[i]:2); writeln; end; procedure Try(i:integer); var j:integer; begin for j:= 1 to n do if b[j] then begin a[i]:=j; b[j]:=false;

b[j]:=true; end; end; begin init; try(1); readln; end.

Vớ dụ 4.6. Liệt kờ cỏc tập con gồm m phần tử của tập X = { 1, 2, ..., n }.

Giải: Mỗi tập con của X gồm m phần tử cú thể biểu diễn bởi bộ cú thứ tự gồm m thành phần a = (a1, a2, ... , am) thỏa món

1 a1 < a2 < .... <am  n

Từ đú suy ra cỏc giỏ trị đề cử cho ai là từ ai-1 đến n –m +i. Để điều này đỳng cho cả trường hợp i = 1 cần thờm vào a0 với a0 = 0. Cỏc giỏ trị đề cử này mặc nhiờn được chấp nhận.

Chương trỡnh minh hoạ

Var n, m:integer; a:array[1..30] of integer; procedure init; Begin write('n, m =');readln(n,m); a[0]:=0; end; procedure result; var i:integer; begin

for i:=1 to n do write(a[i]:2); writeln;

procedure Try(i:integer); var j:integer;

begin

for j:= a[i-1]+1 to n-m+i do begin

a[i]:=j;

if i=m then result else try(i+1); end; end; Begin init; try(1); readln; End.

Vớ dụ 4.7. (Bài toỏn xếp hậu). Liệt kờ tất cả cỏc cỏch xếp 8 quõn hậu trờn bàn

cờ sao cho chỳng khụng ăn được lẫn nhau.

Giải: Đỏnh số cột và số dũng của bàn cờ từ 1 đến 8. Mỗi dũng được xếp đỳng

một quõn hậu. Vấn đề là xem mỗi quõn hậu trờn mỗi hàng được xếp vào cột nào. Từ đú, ta cú thể biểu diễn một cỏch xếp bằng một bộ 8 thành phần (x1, x2, ..., x8) trong đú xi = j nghĩa là quõn hậu dũng i được xếp vào cột j. Cỏc giỏ trị đề cử cho xi là từ 1 đến 8. Giỏ trị j là được chấp nhận nếu ụ (i, j) chưa bị quõn hậu nào chiếu đến (quõn hậu cú thể ăn ngang, dọc và hai đường chộo). Để kiểm soỏt được điều này, ta cần phải ghi nhận trạng thỏi của bàn cờ trước cũng như sau khi xếp được một quõn hậu. Việc kiểm soỏt theo chiều ngang là khụng cần thiết vỡ mỗi dũng được xếp đỳng một quõn hậu. Việc kiểm soỏt chiều dọc được ghi nhận nhờ dóy biến logic aj với qui ước rằng aj bằng true nếu cột j cũn trống. Đối với 2 đường chộo, ta nhận thấy rằng một đường cú

Từ đú đường chộo thứ nhất được ghi nhận nhờ dóy biến logic bj (2 j 16) và đường chộo thứ hai nhờ nhờ dóy biến logic cj (-7 j  7) với qui ước cỏc đường này cũn trống nếu biến tương ứng cú giỏ trị true.

Cỏc biến trạng thỏi aj, bj, cj được khởi gỏn giỏ trị true trong thủ tục Init. Như vậy giỏ trị j được chấp nhận khi và chỉ khi cả 3 biến ai, bi+j, ci-j cựng cú giỏ trị true. Cỏc biến này phải được gỏn lại giỏ trị false khi xếp xong quõn hậu thứ i và được trả lại giỏ trị true sau khi gọi Result hay Try(i+1).

Chương trỡnh minh hoạ

Var i:integer; x:array[1..8] of integer; a:array[1..8] of boolean; b:array[2..16] of boolean; c:array[-7..7] of boolean; procedure init; 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; end;

procedure result; begin

for i:=1 to n do write(x[i]:4); writeln; end; procedure Try(i:integer); var j:integer; begin for j:= 1 to 8 do

if a[i] and b[i+j] and c[i-j] then begin

x[i]:=j;

a[i]:=false;b[i+j]:=false;c[i-j]:=false; if i=n then result else try(i+1);

a[i]:=true;b[i+j]:=true;c[i-j]:=true; end; end; Begin init; try(1); readln; End.

Có 92 cách xếp và cách xếp đầu tiên mà ch- ơng trình tìm đ- ợc là x = (1, 5, 8, 6, 3, 7, 2, 4) 1 2 3 4 5 6 7 8 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x

BÀI TẬP CHƢƠNG 4

1. Tỡm hoỏn vị liền sau theo thứ tự từ điển của hoỏn vị 325461

2. Liệt kờ cỏc dóy nhị phõn độ dài n trong đú cú ớt nhất 3 số 1 đi liền nhau. 3. Liệt kờ cỏc dóy nhị phõn độ dài n mà khụng cú 2 số 0 đi liền nhau.

4. Liệt kờ cỏc tập con cú 3 phần tử của tập X = A, B, C, D, E, F

5. Cho một dóy số nguyờn a1, a2, …, an. và một số nguyờn S. Liệt kờ tất cả cỏc cỏch phõn tớch S = ai1 + ai2 + ... +aik

6. Liệt kờ cỏc hoỏn vị của tập n số nguyờn a1, a2, …, an.

7. Liệt kờ cỏc chỉnh hợp chập khụng lặp k của tập gồm n số nguyờn a1, a2, …, an.

8. Liệt kờ cỏc hoỏn vị của {1, 2, 3, 4, 5, 6 } sao cho tổng 3 số đầu bằng tổng 3 số cuối

9. Liệt kờ tất cả cỏc số cú 6 chữ số (cỏc số khỏc nhau) sao cho trong cỏc số đú thỡ tổng 3 chữ số đầu bằng tổng 3 chữ số cuối.

10. Cho lưới 3x3 ụ vuụng. Liệt kờ tất cả cỏc phương ỏn xếp cỏc số nguyờn từ 1 đến 9 vào cỏc ụ sao cho tổng cỏc số trong cỏc ụ theo hàng ngang, theo hàng dọc, theo đường chộo đều bằng nhau.

11. Liệt kờ tất cả cỏc cỏch xếp n quõn hậu trờn bàn cờ n x n sao cho chỳng khụng ăn được lẫn nhau.

Chương 5

BÀI TOÁN TỐI ƯU

5.1. Giới thiệu bài toỏn

Một dạng bài toỏn được quan tõm rất nhiều trong lĩnh vực toỏn rời rạc là bài toỏn tối ưu, tức là tỡm trong số cỏc phương ỏn thoả món cỏc điều kiện đó cho phương ỏn tốt nhất theo một nghĩa nào đú.

5.1.1. Phỏt biểu bài toỏn

Như trờn đó trỡnh bày để đỏnh giỏ, so sỏnh phương ỏn này với phương ỏn khỏc người ta phải lượng húa cỏc tiờu chuẩn, yờu cầu. Như vậy vấn đề quan trọng ở đõy là xõy dựng cỏc hàm lượng húa cú giỏ trị phụ thuộc vào phương ỏn được chọn. Như vậy một bài toỏn tối ưu thường mụ tả dạng:

Tỡm cực tiểu (min) hay cực đại (max ) giỏ trị của một hàm đỏnh giỏ F phụ thuộc vào cỏc phương ỏn cần xem xột

F(x)-> min(max) với điều kiện

xD

Mụ hỡnh trờn đựơc gọi là mụ hỡnh tổng quỏt của bài toỏn tối ưu, cỏc thuật toỏn và phương phỏp giải quyết đều được dựa trờn mụ hỡnh này.

Hàm F(x) được gọi là hàm mục tiờu của bài toỏn, tập D gọi là tập phương ỏn chấp nhận được của bài toỏn, mỗi phần tử x  D đựơc gọi là một phương ỏn, trong tài liệu này ta chỉ xột cỏc bài toỏn với D là tập hữu hạn. Thụng thường tập D được mụ tả như là tập cỏc cấu hỡnh tổ hợp thoả món một số tớnh chất cho trước nào đú.

Phương ỏn x*  D đem lại giỏ trị nhỏ nhất( lớn nhất) cho hàm mục tiờu được gọi là phương ỏn tối ưu, khi đú giỏ trị F = F(x*) được gọi là giỏ trị tối - ưu của bài toỏn.

5.1.2. Đƣa bài toỏn tối ƣu về dạng tổng quỏt

phỳ. Bước đầu tiờn tiến hành giải bài toỏn là cần phải đưa về dạng tổng quỏt. Ta xột một vài vớ dụ điển hỡnh sau:

Vớ dụ 5.1. Bài toỏn người du lịch

Một người du lịch muốn đi tham quan n thành phố T1, T2, …, Tn. Xuất phỏt từ một thành phố nào đú người du lịch muốn đi qua tất cả cỏc thành phố cũn lại, mỗi thành phố đỳng một lần, rồi quay trở lại thành phố xuất phỏt. Biết cij

là chi phớ đi từ thành phố Tiđến thành phố Tj( i, j = 1, 2,…, n), hóy tỡm hành trỡnh (một cỏch đi thoả món điều kiện đặt ra) với tổng chi phớ là nhỏ nhất.

Phõn tớch bài toỏn. Với nội dung như vậy của bài toỏn rất khú hỡnh dung mụ hỡnh của nú, ta sẽ phõn tớch và đưa về dạng tổng quỏt. Cú hai yếu tố cần phải xỏc định và chỉ ra: Tập D và hàm mục tiờu F(x).

Ta cú thể thiết lập tương ứng 1-1 giữa hành trỡnh T(1) -> T(2) ->…-> T(n)-> T(1)

với một hoỏn vị  = ((1), (2) ,…, (n)) của n số tự nhiờn 1, 2, …, n. Đặt F() = c(1,(2) + ... + c(n-1),(n) + c(n),(1)

và ký hiệu D là tập tất cả cỏc hoỏn vị  = ((1), (2),…, (n)) của n số tự nhiờn 1, 2, …, n. Khi đú bài toỏn được đưa về dạng tổng quỏt như sau:

min { F() :   D }.

Vớ dụ 5.2. Bài toỏn cỏi tỳi

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ú thể đem theo. Đồ vật thứ j cú trọng lượng là aj và giỏ trị sử dụng làcj(j=1, 2,…, 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?

Phõn tớch bài toỏn. Một phương ỏn đem đồ vật của nhà thỏm hiểm cú thể biểu diễn bởi vectơ nhị phõn độ dài n: x = (x1, x2,…, xn), trong đú xj =1 cú nghĩa là đồ vật thứ j được đem theo và xj= 0 cú nghĩa trỏi lại. Với phuơng ỏn x, giỏ trị đồ vật mang theo (hàm mục tiờu của bài toỏn) là:

F(x) =   n j j jx c 1

và tổng trọng lượng đồ vật đem theo là g(x) =   n j j jx a 1

Từ đú tập chấp nhận được D được biểu diễn như sau: D = { x: g(x)  b}

và bài toỏn cỏi tỳi cú thể đưa về dạng tổng quỏt như sau: min{ F(x): x  D}

Vớ dụ 5.3. Bài toỏn cho thuờ mỏy

Một ụng chủ cú một cỏi mỏy để cho thuờ. Đầu thỏng ụng ta nhận được yờu cầuthuờ mỏy của m khỏch hàng. Mỗi khỏch hàng i sẽ cho biết tập Ni ngày trong thỏng cần sử dụng mỏy( i= 1, 2, …, m). ễng chủ chỉ cú quyền hoặc là từ chối yờu cầu của khỏch hàng i, hoặc là nếu nhận thỡ phải bố trớ mỏy phục vụ khỏch hàng i theo đỳng những ngày mà khỏch hàng này yờu cầu. Hỏi rằng ụng chủ phải tiếp nhận cỏc yờu cầu của khỏch như thế nào để cho tổng số ngày sử dụng mỏy là lớn nhất.

Phõn tớch bài toỏn. Ký hiệu I= {1, 2,…, m}là tập chỉ số khỏch hàng, S là tập hợp cỏc tập con của I. Khi đú tập hợp tất cả cỏc phương ỏn cho thuờ mỏy là

D = { J  S: Nk  Np = ,  k  p, k, p  J }. và với mỗi phương ỏn J D

F (J) =

J j

j

N

sẽ là tổng số ngày sử dụng mỏy theo phương ỏn đú. Bài toỏn đặt ra cú thể phỏt biểu dưới dạng bài toỏn tối ưu tổng quỏt sau:

Vớ dụ 5.4. Bài toỏn phõn cụng

Cú n cụng việc và n thợ. Biết ci j là chi phớ cần trả để thợ i hoàn thành cụng việc j (i, j = 1, 2, …, n). Cần phải thuờ thợ sao cho cỏc cụng việc đều hoàn thành và mỗi thợ chỉ thực hiện một cụng việc. Hóy tỡm cỏch thuờ sao cho tổng chi phớ thuờ thợ là nhỏ nhất.

Phõn tớch bài toỏn. Rừ ràng mỗi một phương ỏn bố trớ thợ thực hiện cỏc cụng việc Cụng việc Thợ thực hiện 1 (1) 2 (2) … … n (n)

tương ứng với một hoỏn vị  = ((1), (2), …, (n)) của n số tự nhiờn 1, 2, …, n. Như vậy tập cỏc phương ỏn chấp nhận được D chớnh là tập cỏc hoỏn vị. Chi phớ theo phương ỏn bố trớ trờn là

F()= c(1), 1 + c(2), 2 +… + c(n),n

Bài toỏn được đưa về dạng tổng quỏt là: min { f() :   D}

Vớ dụ 5.5. Bài toỏn lập lịch

Mỗi một chi tiết trong số n chi tiết D1, D2,…, Dn cần phải được lần lượt gia cụng trờn m mỏy M1, M2,…, Mm. Thời gian gia cụng chi tiết Di trờn mỏy Mj là tij. Hóy tỡm lịch (trỡnh tự gia cụng) cỏc chi tiết trờn cỏc mỏy sao cho việc hoàn thành gia cụng tất cả cỏc chi tiết là sớm nhất.

Phõn tớch bài toỏn. Ta sẽ xột bài toỏn trờn với thờm giả thiết là cỏc chi tiết phải được gia cụng một cỏch liờn tục, nghĩa là quỏ trỡnh gia cụng mỗi chi tiết

cho phộp cú khoảng thời gian dừng khi chuyển từ mỏy này sang mỏy khỏc. Tỡnh huống như vậy rất hay gặp trong quỏ trỡnh sản xuất cụng nghiệp. Chẳng hạn, trong cụng nghiệp luyện thộp, vật liệu cần phải được gia cụng một cỏch liờn tục vỡ sự giỏn đoạn sẽ dẫn đến sự giảm nhiệt độ của vật liệu và điều đú cản trở việc gia cụng tiếp theo. Tỡnh huống tương tự cũng cú thể xảy ra trong một số nghành của cụng nghiệp húa chất.

Rừ ràng một lịch gia cụng cỏc chi tiết trờn cỏc mỏy trong tỡnh huống như vậy sẽ tương ứng với một hoỏn vị = ((1),(2),…,(n)) của n số tự nhiờn 1,

2,…, n. Vậy tập cỏc phương ỏn chấp nhận được D là tập cỏc hoỏn vị từ n phần tử. Thời gian hoàn thành theo lịch trờn được tớnh bởi hàm số

Một phần của tài liệu Giáo trình toán rời rạc đh sư phạm kỹ thuật nam định (Trang 59)

Tải bản đầy đủ (PDF)

(195 trang)