1. Trang chủ
  2. » Giáo Dục - Đào Tạo

CHUYÊN ĐỀ BỒI DƯỠNG HSG TIN HỌC THUẬT TOÁN QUAY LUI VA QUY HOẠCH ĐỘNG

91 505 3

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 91
Dung lượng 857 KB

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

Nội dung

Là tài liệu được trình bày từ cơ bản đến nâng cao về thuật toán quay lui, quy hoạch động, tham lam trong việc giải các bài toán thi học sinh giỏi Tin học. Có các bài tập minh họa và hướng dẫn cách giải từ đề thi HSG tỉnh, Quốc gia các năm

Trang 1

CHUYÊN ĐỀ 4 THIẾT KẾ THUẬT TOÁN

I Chia để trị và giải thuật đệ quy

Khi nào một bài toán có thể tìm được thuật giải bằng phương pháp chia để trị? Có thểtìm thấy câu trả lời qua việc giải đáp các câu hỏi sau:

Có thể định nghĩa được bài toán dưới dạng phối hợp của những bài toán cùngloại nhưng nhỏ hơn hay không? Khái niệm “nhỏ hơn” là thế nào? ( Xác định quy tắc phân

rã bài toán)

Trường hợp đặc biệt nào của bài toán có thể coi là đủ nhỏ để có thể giải trực tiếp được?( Xác định các bài toán cơ sở)

2 Giải thuật đệ quy

Trong các ngôn ngữ lập trình, các giải thuật đệ quy thường được cài đặt bằng các chươngtrình con đệ quy Trong Pascal, ta đã thấy nhiều ví dụ của các hàm và thủ tục có chứa lờigọi tới chính nó, đó gọi là đệ quy Một chương trình con đệ quy gồm hai phần:

Phần neo (anchor): Phần này được thực hiện khi mà công việc quá đơn giản, có thể giảitrực tiếp chứ không cần phải nhờ đến một bài toán con nào cả

Phần đệ quy: Trong trường hợp bài toán chưa thể giải được bằng phần neo, ta xác địnhnhững bài toán con và gọi đệ quy giải những bài toán con đó

Trang 2

if n = 0 then Result := 1 //Phần neo

else Result := n * Factorial(n - 1); //Phần đệ quy

Bài toán : Dãy số Fibonacci bắt nguồn từ bài toán cổ về việc sinh sản của các cặp thỏ.

Bài toán đặt ra như sau:

Các con thỏ không bao giờ chết

Hai tháng sau khi ra đời, mỗi cặp thỏ mới sẽ sinh ra một cặp thỏ con (một đực, một cái) Khi đã sinh con rồi thì cứ mỗi tháng tiếp theo chúng lại sinh được một cặp con mớiGiả sử từ đầu tháng 1 có một cặp mới ra đời thì đến giữa tháng thứ sẽ có bao nhiêu cặp

Ví dụ n = 5, ta thấy:

Giữa tháng thứ 1: 1 cặp (ab) (cặp ban đầu)

Giữa tháng thứ 2: 1 cặp (ab) (cặp ban đầu vẫn chưa đẻ)

Giữa tháng thứ 3: 2 cặp (AB)(cd) (cặp ban đầu đẻ ra thêm 1 cặp con)

Giữa tháng thứ 4: 3 cặp (AB)(cd)(ef) (cặp ban đầu tiếp tục đẻ)

Giữa tháng thứ 5: 5 cặp (AB)(CD)(ef)(gh)(ik) (cả cặp (AB) và (CD) cùng đẻ)

Bây giờ, ta xét tới việc tính số cặp thỏ ở tháng thứ n : f(n)

Nếu ta đang ở tháng n-1 và tính số thỏ ở tháng n thì:

Trang 3

Số tháng tới = Số hiện có + Số được sinh ra trong tháng tới

Mặt khác, với tất cả các cặp thỏ ≥ 1 tháng tuổi thì sang tháng sau, chúng đều ≥ 2 thángtuổi và đều sẽ sinh Tức là:

Số được sinh ra trong tháng tới = Số tháng trước

Vậy:

Số tháng tới = Số hiện có + Số tháng trước

f(n) = f(n-1) + f(n-2)Vậy có thể tính được f(n) theo công thức sau:

1, n 2( )

if n ≤ 2 then Result := 1 //Phần neo

else Result := f(n - 1) + f(n - 2); //Phần đệ quy

Trang 4

1, n=0

( ) , n>0; n mod 2=0( ) *x, n>0; n mod 2 0

Result := Power(x, n div 2);

Result := Result * Result;

if n mod 2 = 1 then Result := Result * x;

end;

end;

b Tháp hà nội

Bài toán : Đây là một bài toán mang tính chất một trò chơi, tương truyền rằng tại ngôi

đền Benares có ba cái cọc kim cương Khi khai sinh ra thế giới, thượng đế đặt 64 cái đĩabằng vàng chồng lên nhau theo thứ tự giảm dần của đường kính tính từ dưới lên, đĩa tonhất được đặt trên một chiếc cọc

Các nhà sư lần lượt chuyển các đĩa sang cọc khác theo luật:

Khi di chuyển một đĩa, phải đặt nó vào vị trí ở một trong ba cọc đã cho

Mỗi lần chỉ có thể chuyển một đĩa và phải là đĩa ở trên cùng của chồng đĩa

Trang 5

Tại một vị trí, đĩa nào mới chuyển đến sẽ phải đặt lên trên cùng

Đĩa lớn hơn không bao giờ được phép đặt lên trên đĩa nhỏ hơn (hay nói cách khác: mộtđĩa chỉ được đặt trên cọc hoặc đặt trên một đĩa lớn hơn)

Ngày tận thế sẽ đến khi toàn bộ chồng đĩa được chuyển sang một cọc khác

Thuật toán :

Giả sử chúng ta có n đĩa

Nếu n=1 thì ta chuyển đĩa duy nhất đó từ cọc 1 sang cọc 2 là xong

Nếu ta có phương pháp chuyển được n-1 đĩa từ cọc 1 sang cọc 2, thì tổng quát,cách chuyển n-1 đĩa từ cọc x sang cọc y (1≤x,y≤3) cũng tương tự

Giả sử ta có phương pháp chuyển được n-1 đĩa giữa hai cọc bất kỳ Để chuyển n đĩa từcọc x sang cọc y, ta gọi cọc còn lại là z (=6-x-y) Coi đĩa to nhất là … cọc, chuyển đĩacòn lại từ cọc x sang cọc z, sau đó chuyển đĩa to nhất đó sang cọc y và cuối cùng lại coiđĩa to nhất đó là cọc, chuyển n-1 đĩa còn lại đang ở cọc z sang cọc y chồng lên đĩa to nhất.Như vậy để chuyển n đĩa (bài toán lớn), ta quy về hai phép chuyển n-1 đĩa (bài toán nhỏ)

và một phép chuyển 1 đĩa (bài toán cơ sở) Cách làm đó được thể hiện trong thủ tục đệquy dưới đây:

procedure Move(n, x, y: Integer);

Trang 6

Có một số bài toán trên thực tế yêu cầu chỉ rõ: trong một tập các đối tượng cho trước cóbao nhiêu đối tượng thoả mãn những điều kiện nhất định và đó là những đối tượng nào.Bài toán này gọi là bài toán liệt kê hay bài toán duyệt.

Nếu ta biểu diễn các đối tượng cần tìm dưới dạng một cấu hình các biến số thì để giảibài toán liệt kê, cần phải xác định được một thuật toán để có thể theo đó lần lượt xây dựngđược tất cả các cấu hình đang quan tâm Có nhiều phương pháp liệt kê, nhưng chúng cầnphải đáp ứng được hai yêu cầu dưới đây:

Không được lặp lại một cấu hình

Không được bỏ sót một cấu hình

Trước khi nói về các thuật toán liệt kê, chúng ta giới thiệu một số khái niệm cơ bản:

- Khi đó số cách làm công việc A là m + n cách

Ví dụ 1 : An có 3 áo tay dài, 2 áo tay ngắn vậy để chọn một áo bất kì thì có mấy cách?

Ví dụ 2 : Có bao nhiêu xâu nhị phân độ dài N bit không có hai bit 1 liền kề.

Ta có hệ thức truy hồi : an = an-1 + an-2

b Nguyên lí nhân

- Giả sử làm công việc A có 2 bước

Bước 1 có m cách làm

Bước 2 có n cách làm

- Khi đó số cách làm công việc A là m * n cách

Ví dụ 1 : Từ A tới B có 3 con đường, từ B tới C có 2 con đường vậy để đi từ A tới C thì

có mấy cách?

c Chỉnh hợp lặp

Trang 7

- Xét tập hữu hạn gồm n phần tử A = {a1, a2, , an}

- Một chỉnh hợp lặp chập k của n phần tử (k có thể lớn hơn n) là một bộ có thứ tự gồm kphần tử của A, các phần tử có thể lặp lại

- Theo nguyên lí nhân, số tất cả các chỉnh hợp lặp chập k của n sẽ là nk

- Để xây dựng một chỉnh hợp không lặp, ta xây dựng dần từ thành phần đầu tiên Thànhphần này có n khả năng lựa chọn Mỗi thành phần tiếp theo, khả năng lựa chọn giảm đi 1,theo nguyên lí nhân, số chỉnh hợp không lặp chập k của n sẽ là n(n -1) (n-k + 1)

Ví dụ 1: Có bao nhiêu số tự nhiên năm chữ số được tạo bởi các số 1, 2, 3, 4, 5.

f Tổ hợp

- Một tổ hợp chập k của n phần tử (k < n) là một bộ không kể thứ tự gồm k thành phầnkhác nhau lấy từ n phần tử của tập đã cho

Ví dụ 1 Có 6 đội thi đấu vòng tròn một lượt Hỏi phải tổ chức bao nhiêu trận đấu?

Ví dụ 2 : Có bao nhiêu tập con k phần tử của tập S = {1, 2, 3, 4}.

Kết quả chính là tổ hợp chập k của n phần tử

3 Thuật toán quay lui

a Tổng quan : Thuật toán vét cạn dùng để giải bài toán liệt kê các cấu hình theo cách:

Trang 8

- 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 x1 n, khi đó thuật toán quay lui sẽ xét tất cả các giá trị x1 có thể nhận, thử cho x1 nhận lần lượt các giá trị đó Với mỗi giá trị thử gán cho x1, thuậttoán sẽ xét tất cả các giá trị x2 có thể nhận, lại thử cho x2 nhận lần lượt các giá trị đó Vớimỗi giá trị thử gán cho x2 lại xét tiếp các khả năng chọn x3, cứ tiếp tục như vậy… Mỗi khi

ta tìm được đầy đủ một cấu hình thì liệt kê ngay cấu hình đó

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

Attempt(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 Attempt(1)

Tên gọi thuật toán quay lui là dựa trên cơ chế duyệt các cấu hình: Mỗi khi thử chọn mộtgiá trị cho xi, thuật toán sẽ gọi đệ quy để tìm tiếp xi+1, … và cứ như vậy cho tới khi tiếntrình duyệt xét tìm tới phần tử cuối cùng của cấu hình Còn sau khi đã xét hết tất cả khảnăng chọn, tiến trình sẽ lùi lại thử áp đặt một giá trị khác cho xi-1

c Một số ví dụ

Bài toán 1 : Liệt kê dãy nhị phân độ dài n.

Trang 9

Biểu diễn dãy nhị phân độ dài n dưới dạng dãy x1 n Ta sẽ liệt kê các dãy này bằng cáchthử dùng các giá trị {0,1} gán cho xi Với mỗi giá trị thử gán cho xi lại thử các giá trị

có thể gán cho xi+1 …

procedure Attempt(i: Integer); //Thử các cách chọn x[i]

var j: AnsiChar;

begin

for j := '0' to '1' do //Xét các giá trị j có thể gán cho x[i]

begin //Với mỗi giá trị đó

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

if i = n then WriteLn(x) //Nếu i = n thì in kết quả else Attempt(i + 1); //Nếu x[i] chưa phải phần tử cuối thì tìm tiếp x[i + 1] end;

end;

Ví dụ khi n=3 ta có thể vẽ cây đệ quy như sau :

Bài toán 2 : Liệt kê tập con có k phần tử.

Bài toán liệt kê các tập con k phần tử của tập S = {1, 2, …, n} có thể quy về bài toán liệt

kê các dãy k phần tử x1 k, trong đó 1≤x1<x2<…<xk≤n Nếu sắp xếp các dãy này theothứ tự từ điển, ta nhận thấy:

Tập con đầu tiên (cấu hình khởi tạo) là : {1, 2, …, k}

Tập con cuối cùng (cấu hình kết thúc) là : {n-k+1, n-k+2,…,n}

Như vậy giới hạn trên của xi là : n-k+i

Trang 10

Giới hạn dưới của xi là : xi-1 + 1

(Giả thiết rằng có thêm một số x0 = 0)

Thuật toán quay lui sẽ xét tất cả các cách chọn x1 từ 1 (=x0 + 1) đến n-k+1, với mỗi giá trị đó, xét tiếp tất cả các cách chọn x2 từ x1 + 1đến n-k+2, … cứ như vậy khi chọn được đến xk thì ta có một cấu hình cần liệt kê

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

end;

end;

Bài toán 3 : Liệt kê chỉnh hợp không lặp chập k.

Để liệt kê các chỉnh hợp không lặp chập k của tập S = {1, 2,…,n} ta có thể đưa về liệt kêcác cấu hình x1 k, các xi khác nhau đôi một

Thủ tục Attempt (i) – xét tất cả các khả năng chọn xi – sẽ thử hết các giá trị từ 1đến n

chưa bị các phần tử đứng trước x1… xi-1 chọn Muốn xem các giá trị nào chưa được chọn

ta sử dụng kỹ thuật dùng mảng đánh dấu: Khởi tạo một mảng Free[1 n] mang kiểu logicboolean Ở đây Free[j] cho biết giá trị j có còn tự do hay đã bị chọn rồi Ban đầu khởi tạotất cả các phần tử mảng Free[j] là True có nghĩa là các giá trị từ 1 đến n đều tự do

Tại bước chọn các giá trị có thể của xi ta chỉ xét những giá trị j còn tự do

Trước khi gọi đệ quy Attempt (i+1) để thử chọn tiếp xi+1 : ta đặt giá trị j vừa gán cho

xi là “đã bị chọn” (Free[j] = False) để các thủ tục Attempt (i+1), Attempt (i+2)… gọi sau này không chọn phải giá trị j đó nữa

Sau khi gọi đệ quy Attempt (i+1) : có nghĩa là sắp tới ta sẽ thử gán một giá trị khác cho

xi thì ta sẽ đặt giá trị j vừa thử cho xi thành “tự do” (Free[j] = True), bởi khi xi đã

nhận một giá trị khác rồi thì các phần tử đứng sau (xi+1 k) hoàn toàn có thể nhận lại

Trang 11

giá trị j đó

Tất nhiên ta chỉ cần làm thao tác đánh dấu/bỏ đánh dấu trong thủ tục Attempt (i) có

i≠k, bởi khi i=k thì tiếp theo chỉ có in kết quả chứ không cần phải chọn thêm phần

Bài toán 4 : Liệt kê các cách phân tích số

Cho một số nguyên dương n, hãy tìm tất cả các cách phân tích số n thành tổng của các sốnguyên dương, các cách phân tích là hoán vị của nhau chỉ tính là 1 cách và chỉ được liệt

kê một lần

Ta sẽ dùng thuật toán quay lui để liệt kê các nghiệm, mỗi nghiệm tương ứng với một dãy

x, để tránh sự trùng lặp khi liệt kê các cách phân tích, ta đưa thêm ràng buộc: dãy x phải

có thứ tự không giảm: x1 ≤ x2 ≤……

Trang 12

Thuật toán quay lui được cài đặt bằng thủ tục đệ quy Attempt (i) : thử các giá trị có thể

nhận của xi, mỗi khi thử xong một giá trị cho xi, thủ tục sẽ gọi đệ quy Attempt (i+1)

để thử các giá trị có thể cho xi+1 Trước mỗi bước thử các giá trị cho xi, ta lưu trữ m làtổng của tất cả các phần tử đứng trước xi : x1 n và thử đánh giá miền giá trị mà xi có thểnhận Rõ ràng giá trị nhỏ nhất mà xi có thể nhận chính là xi-1 vì dãy có thứ tự khônggiảm (Giả sử rằng có thêm một phần tử x0=1, phần tử này không tham gia vào việc liệt

kê cấu hình mà chỉ dùng để hợp thức hoá giá trị cận dưới của x1)

Nếu xi chưa phải là phần tử cuối cùng, tức là sẽ phải chọn tiếp ít nhất một phần tử nữa màviệc chọn thêm không làm cho tổng vượt quá n Ta có:

n = m + xi + xi+1 ≥ m + 2xi

Tức là nếu xi chưa phải phần tử cuối cùng (cần gọi đệ quy chọn tiếpxi+1) thì giá trị lớnnhất xi có thể nhận là [(n-m)/2], còn dĩ nhiên nếu xi là phần tử cuối cùng thì bắt buộcphải bằng n-m

Với giá trị khởi tạo x0=1 và m=0, thuật toán quay lui sẽ được khởi động bằng lời gọi

Attempt (1) và hoạt động theo cách sau: Với mỗi giá trị j : xi-1≤j≤[(n-m)/2], thử gán

xi=j, cập nhật m=m+j, sau đó gọi đệ quy tìm tiếp, sau khi đã thử xong các giá trị có thểcho xi+1, biến m được phục hồi lại như cũ m=m+l trước khi thử gán một giá trị khác cho xi

procedure Attempt(i: Integer); //Thuật toán quay lui

m := m - j; //Phục hồi tổng m end;

x[i] := n - m; //Nếu x[i] là phần tử cuối thì nó bắt buộc phải là n-m

PrintResult(i); //In kết quả

end;

Trang 13

4 Thuật toán nhánh cận

a Tổng quan : Trong thực tế, có nhiều bài toán yêu cầu tìm ra một phương án thoả mãn

một số điều kiện nào đó, và phương án đó là tốt nhất theo một tiêu chí cụ thể Các bàitoán như vậy được gọi là bài toán tối ưu Có nhiều bài toán tối ưu không có thuật toán nàothực sự hữu hiệu để giải quyết, mà cho đến nay vẫn phải dựa trên mô hình xem xét toàn

bộ các phương án, rồi đánh giá để chọn ra phương án tốt nhất

- Tư tưởng của phương pháp nhánh và cận như sau: Giả sử, đã xây dựng được k thànhphần (x1, x2, , xk) của nghiệm và khi mở rộng nghiệm (x1, x2, , xk+1, ), nếu biết rằng tất

cả các nghiệm mở rộng của nó (x1, x2, , xk+1, ) đều không tốt bằng nghiệm tốt nhất đãbiết ở thời điểm đó, thì ta không cần mở rộng từ (x1, x2, , xk) nữa Như vậy, với phươngpháp nhánh và cận, ta không phải duyệt toàn bộ các phương án để tìm ra nghiệm tốt nhất

mà bằng cách đánh giá các nghiệm mở rộng, ta có thể cắt bỏ đi những phương án (nhánh)không cần thiết

if «Còn hi vọng tìm ra cấu hình tốt hơn best» then

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

«Cập nhật best»

else begin

«Ghi nhận việc thử x[i] := v nếu cần»;

Attempt(i + 1); //Gọi đệ quy, chọn tiếp x[i + 1]

«Bỏ ghi nhận việc đã thử cho x[i] := v (nếu cần)»;

end;

end;

end;

Trang 14

c Một số ví dụ

Bài toán 1 Máy rút tiền tự động ATM : Một máy ATM hiện có n (n < 20) tờ tiền có giá

t1; t2, , tn Hãy tìm cách trả ít tờ nhất với số tiền đúng bằng S

Dữ liệu vào từfile “ATM.INP” có dạng:

- Dòng đầu là 2 số n và S

- Dòng thứ 2 gồm n số tl, t2, ,tn

Kết quả ra file “ATM.OUT” có dạng: Nếu có thể trả tiền đúng bằng S thì đưa ra số tờ ít

nhất cần trả và đưa ra cách trả, nếu không ghi -1

Hướng dẫn : Như ta đã biết, nghiệm của bài toán là một dãy nhị phân độ dài n, giả sử đã

xây dựng được k thành phần (x1, x2, ,xk), đã trả được sum và sử dụng c tờ Để đánh giáđược các nghiệm mở rộng của (x1, x2, ,xk), ta nhận thấy:

- Còn phải trả S - sum Gọi tmax[k] là giá cao nhất trong các tờ tiền còn lại :

(tmax[k] = max{tk+1, , tn}) thì ít nhất cần sử dụng thêm (S - sum)/tmax[k] tờ nữa

- Do đó, nếu mà c + (s-sum)/tmax[i] lớn hơn hoặc bằng số tờ của cách trả tốt nhất hiện cóthì không cần mở rộng các nghiệm của (x1; x2, , xk) nữa

Procedure Attempt (i:longint);

Trang 15

Bài toán 2 Bài toán người du lịch : Cho n thành phố từ 1 đến n và các tuyến đường

giao thông hai chiều giữa chúng, mạng giao thông này được cho bởi mảng C[1 n,1 n], ởđây Cij = Cji là chi phí đi đoạn đường trực tiếp từ thành phố i đến thành phố j

Một người du lịch xuất phát từ thành phố 1, muốn đi thăm tất cả các thành phố còn lạimỗi thành phố đúng 1 lần và cuối cùng quay lại thành phố 1 Hãy chỉ ra cho người đóhành trình với chi phí ít nhất

Dữ liệu vào trong file “TSP.INP” có dạng:

- Dòng đầu chứa số n(1<n<20), là số thành phố

- n dòng tiếp theo, mỗi dòng n số mô tả mảng C

Kết quả ra file “TSP.OUT” có dạng:

- Duyệt quay lui: x2 có thể chọn một trong các thành phố mà x1 có đường đi trực tiếp tới,với mỗi cách thử chọn x2 như vậy thì x3 có thể chọn một trong các thành phố mà x2 cóđường đi tới (ngoài x1) Tổng quát: xi có thể chọn 1 trong các thành phố chưa đi qua mà từxi-1 có đường đi trực tiếp tới (2 < i < n)

- Nhánh cận: Khởi tạo cấu hình BestSolution có chi phí = +oo Với mỗi bước thử chọn xixem chi phí đường đi cho tới lúc đó có nhỏ hơn chi phí của cấu hình BestSolution không?Nếu không nhỏ hơn thì thử giá trị khác ngay bởi có đi tiếp cũng chỉ tốn thêm

Trang 16

Khi thử được một giá trị xn ta kiểm tra xem xn có đường đi trực tiếp về 1 không? Nếu cóđánh giá chi phí đi từ thành phố 1 đến thành phố xn cộng với chi phí từ xn đi trực tiếp về 1,nếu nhỏ hơn chi phí của đường đi BestSolution thì cập nhật lại BestSolution bằng cách đimới.

Procedure update;

Begin

if (sum+c[x[n],x[1]] < min) then begin

min:= sum+c[x[n],x[1]]; best:=x; end;

sum + minC*(n-i+1) < min

Nếu nhỏ hơn thì tìm tiếp còn không thì quay lui sớm tìm cấu hình khác

Trang 17

III Quy hoạch động

1 Tổng quan

Trong chiến lược chia để trị, người ta phân bài toán cần giải thành các bài toán con Cácbài toán con lại được tiếp tục phân thành các bài toán con nhỏ hơn, cứ thế tiếp tục cho tớikhi ta nhận được các bài toán con có thể giải được dễ dàng Tuy nhiên, trong quá trìnhphân chia như vậy, có thể ta sẽ gặp rất nhiều lần cùng một bài toán con Ví dụ như bàitoán Fibonaci :

Ta đã biết cách giải bằng phương pháp chia để trị và đệ quy :

Function Fibo(n: longint): int64;

Trang 18

Bây giờ ta xét một cách khác để tiếp cận bài toán như sau : Ta sử dụng mảng F[1 N], vớiF[i] để tính số Fibonacci thứ i.

F[1] := 1; F[2]:= 1;

for i := 3 to n do

F[i] := F[i-1] + F[i-2];

Ta nhận thấy, mỗi bài toán con chỉ được giải đúng một lần Phương pháp này được gọi làquy hoạch động: Khi không biết cần phải giải quyết những bài toán con nào, ta sẽ đi giảiquyết tất cả các bài toán con và lưu trữ những lời giải hay đáp số của chúng với mục đích

sử dụng lại theo một sự phối hợp nào đó để giải quyết những bài toán tổng quát hơn màkhông cần phải giải lại các bài toán con

3 Cách nhận diện bài toán quy hoạch động

Một bài toán có thể giải bằng quy hoạch động thường có 3 tính chất sau :

Bài toán lớn có thể phân rã thành những bài toán con đồng dạng, những bài toán con đó

có thể phân rã thành những bài toán nhỏ hơn nữa …(recursive form)

Lời giải tối ưu của các bài toán con có thể sử dụng để tìm ra lời giải tối ưu của bàitoán lớn (optimal substructure)

Hai bài toán con trong quá trình phân rã có thể có chung một số bài toán conkhác (overlapping subproblems)

Tính chất thứ nhất và thứ hai là điều kiện cần của một bài toán quy hoạch động Tínhchất thứ ba nêu lên đặc điểm của một bài toán mà cách giải bằng phương pháp quy hoạchđộng hiệu quả hơn hẳn so với phương pháp giải đệ quy thông thường

Với những bài toán có hai tính chất đầu tiên, chúng ta thường nghĩ đến các thuật toán chia

để trị và đệ quy: Để giải quyết một bài toán lớn, ta chia nó ra thành nhiều bài toán conđồng dạng và giải quyết độc lập các bài toán con đó

Khác với thuật toán đệ quy, phương pháp quy hoạch động thêm vào cơ chế lưu trữnghiệm hay một phần nghiệm của mỗi bài toán khi giải xong nhằm mục đích sử dụng l i,hạn chếnhững thao tác thừa trong quá trình tính toán

4 Các khái niệm

- Công thức phối hợp nghiệm của các bài toán con để có nghiệm của bài toán lớn gọi làcông thức truy hồi (hay phương trình truy toán) của quy hoạch động

Trang 19

Ví dụ như bài toán Fibonaci thì công thức là :

- Tập các bài toán nhỏ nhất có ngay lời giải để từ đó giải quyết các bài toán lớn hơn gọi là

cơ sở quy hoạch động

Ví dụ như bài toán Fibonaci là : F1 = 1 và F2 = 1;

- Không gian lưu trữ lời giải các bài toán con để tìm cách phối hợp chúng gọi là bảngphương án của quy hoạch động

Ví dụ như bài toán Fibonaci thì bảng phương án là : mảng F[1 N]

5 Công thức truy hồi

Nếu như bài toán đặt ra đúng là một bài toán quy hoạch động thì việc đầu tiên phải làm là phân tích xem một bài toán lớn có thể phân rã thành những bài toán con đồng dạng nhưthế nào, sau đó xây dựng cách tìm nghiệm của bài toán lớn trong điều kiện chúng ta đãbiết nghiệm của những bài toán con - tìm công thức truy hồi Đây là công đoạn khó nhất

vì chẳng có phương pháp tổng quát nào xây dựng công thức truy hồi cả, tất cả đều dựavào kinh nghiệm và độ nhạy cảm của người lập trình khi đọc và phân tích bài toán

Ta xét một số bài toán sau :

5.1 Bài toán cầu thang: Một cầu thang có n bậc thang được đánh số từ 1 đến n Một

người đứng ở bậc thứ 1 muốn lên đến bậc thứ n của cầu thang mà chỉ có thể bước với sốbước là 1 bậc hoặc 2 bậc

Yêu cầu: Hãy cho biết có bao nhiêu cách đi từ bậc 0 đến bậc thứ n.

Hướng dẫn : Gọi F[i] là số cách để bước tới bậc thứ i Để bước tới bậc thứ i theo bài

toán ta có hai lựa chọn:

- Bước tới bậc i-1 và bước thêm một bước nữa Mà để bước tới bậc i-1 có F[i-1] cách

- Bước tới bậc i-2 và bước thêm hai bước nữa Mà để bước tới bậc i-2 có F[i-2] cách.Vậy theo nguyên lý cộng ta có : F[i] = F[i-1] + F[i-2] Theo công thức muốn tính F[i] taphải có F[i-1] và F[i-2] … muốn tính F[3] ta phải tìm F[2] và F[1] đó chính là cơ sở quyhoạch động - bài toán con nhỏ nhất

- Ta có F[1] =1 : Tại bậc 1 có một cách để bước tới bậc 1 là không bước bước nào

- Ta có F[2] =1 : Tại bậc 1 có một cách để bước tới bậc 2 là bước một bước

Trang 20

5.2 Bài toán bóng đèn: Một hệ thống đèn gồm n bóng đèn được bố trí từ trái qua phải

và được đánh số lần lượt từ 1 đến n Mỗi bóng đèn có 2 trạng thái tắt và mở Người ta ký hiệu trạng thái tắt là 0 và mở là 1 Bóng đèn ở vị trí đầu tiên (vị trí 1) luôn ở trạng thái mở(trạng thái 1)

Yêu cầu: Hãy cho biết có bao trạng thái khác nhau của hệ thống đèn gồm n bóng đèn

thỏa điều kiện sau:

• Bóng đèn ở vị trí đầu tiên luôn mở.

• Không tồn tại 2 bóng đèn mở bất kỳ liên tiếp nhau trong hệ thống.

Hướng dẫn : Gọi F[i] là số trạng thái để i bóng đèn ban đầu thỏa yêu cầu Việc chọn

bóng thứ i sẽ xảy ra hai trường hợp:

- Bóng thứ i là bóng tắt thì việc thêm bóng i cũng không làm thay đổi trạng thái của i-1bóng trước Hay khi này ta có F[i-1] cách chọn

- Bóng thứ i là bóng mở thì bóng thứ i-1 phải là bóng tắt, khi này việc thêm bóng i cũngkhông làm thay đổi trạng thái của i-2 bóng trước Hay khi này ta có F[i-2] cách chọn.Vậy theo nguyên lý cộng ta có : F[i] = F[i-1] + F[i-2]

- Ta có F[1] =1 : bóng đầu mở (1)

- Ta có F[2] =1 : bóng đầu mở, bóng sau tắt (10)

5.3 Bài toán lát gạch: Đường viền trang trí ở nền nhà có kích thước 2*n được lát bằng 2

loại gạch: loại kích thước 1*2 và loại 2*2

Yêu cầu: Hãy xác định số cách lát khác nhau có thể thực hiện.

Hướng dẫn : Gọi F[i] là số cách lát gạch cho nền nhà kích thước 2xi Ta có hai trường

Vậy theo nguyên lý cộng ta có : F[i] = F[i-1] + 2*F[i-2]

- Ta có F[1] =1 : dùng 1 viên 1*2

- Ta có F[2] =3 : dùng 1 viên 2*2 hoặc 2 viên 1*2 (ngang và dọc)

Trang 21

5.4 Bài toán dãy con tăng dài nhất: Cho một dãy số nguyên gồm N phần tử.

Yêu cầu: Hãy cho biết dãy con tăng đơn điệu dài nhất của dãy này có bao nhiêu phần tử? Hướng dẫn : Gọi F[i] là độ dài của dãy con đơn điệu dài nhất kết thúc tại i và có mặt ai

trong dãy Dãy con tăng này được thành lập bằng cách lấy ai ghép vào cuối một trongnhững dãy con tăng kết thúc tại một vị trí j nào đó trước i Ta sẽ chọn dãy con dài nhất đểghép ai vào cuối đồng thời aj < ai

Như vậy khi này F[i] = Max(F[j]) + 1; với 1≤1<i và aj < ai

- Khi dãy có 1 phần tử thì F[1] = 1; Vậy ta có công thức tổng quát sau :

1; n=1( ) 1; 1 j<i, a <a

i

F Max F

- F[i,T] = 0 nếu không có dãy con của dãy từ a1 đến ai có tổng bằng T

- F[i,T] = l nếu có dãy con của dãy từ a1 đến ai có tổng bằng T

Nhận xét : Nếu tồn tại một dãy con có tổng bằng T thì có 2 khả năng xẩy ra như sau:

- Nếu phần tử ai được chọn thì: Nếu tìm được dãy con của i-1 phần tử (loại bỏ phần tử ai)sao cho có tổng bằng T-ai thì bài toán ban đầu sẽ sẽ tìm được

- Nếu phần tử ai không được chọn thì: Nếu tìm được dãy con của i-l phần tử (loại bỏ phần

từ ai) sao cho có tổng bằng T thì bài toán ban đầu sẽ sẽ tìm được

Do đó ta có công thức :

1; 1 i n, T=0[ , ] 0; i=0, 1 T S

F[n,S] = 0 nếu không có

Trang 22

5.6 Bài toán Túi xách: Trong siêu thị có n đồ vật, đồ vật thứ i có trọng lượng là wi và

giá trị vi Một tên trộm đột nhập vào siêu thị, tên trộm mang theo một cái túi có thể mangđược tối đa trọng lượng M

Yêu cầu: Hỏi tên trộm sẽ lấy đi những đồ vật nào để được tổng giá trị lớn nhất

Giải quyết bài toán trong các trường hợp sau:

- Mỗi vật chỉ được chọn một lần

- Mỗi vật được chọn nhiều lần (không hạn chế số lần)

a Trường hợp mỗi vật được chọn 1 lần

Hướng dẫn : Gọi F[i,j] là tổng giá trị lớn nhất của cái túi khi xét từ vật 1 đến vật i và

trọng lượng của cái túi chưa vượt quá j Ta có hai khả năng:

- Nếu không chọn vật thứ i thì F[i,j] là giá trị lớn nhất có thể chọn trong số các vật{1,2, ,i-1} với giới hạn trọng lượng là j, tức là trọng lượng của vali là như cũ (như lúctrước khi chọn ai) Khi này F[i,j] = F[i-l,j]

- Nếu có chọn vật thứ i (phải thỏa điều kiện wi< j) thì F[i,j] bằng giá trị vật thứ i là vi cộngvới giá trị lớn nhất có thể có được bằng cách chọn trong số các vật {1,2, ,i-l} với giớihạn trọng lượng j-wi Khi này F[i,j] = F[i-l,j-wi] + vi

- Vậy chúng ta phải xem xét xem nếu chọn vật i hay không chọn vật i thì sẽ tốt hơn

0; i=0, 1 j M[ , ] [ 1, ]; j<

b Trường hợp mỗi vật được chọn nhiều lần:

Hướng dẫn : Tương tự như suy luận ở trên ta xét:

- Nếu không chọn vật thứ i thì F[i,j] = F[i-l,j]

- Nếu có chọn vật thứ i (phải thỏa điều kiện wi < j) thì F[i,j] bằng giá trị vật thứ i là vicộng với giá trị lớn nhất có thể có được bằng cách chọn trong số các vật {1,2, ,i} với giớihạn trọng lượng j-wi Khi này F[i,j]:=F[i,j-wi] + vi

- Vậy chúng ta phải xem xét xem nếu chọn vật i hay không chọn vật i thì sẽ tốt hơn

0; i=0, 1 j M[ , ] [ 1, ]; j<

Trang 23

- X gọi là xâu nguồn, X có n ký tự: X = <x1x2…xn>.

- Y gọi là xâu đích, Y có m ký tự: Y = <y1y2…ym>

Có 3 phép biến đổi xâu như sau:

- Chèn một ký tự vào sau ký tự c vào vị trí thứ i của xâu X

- Thay thể ký tự ở vị trí thứ i của xâu X bằng ký tự c

- Xóa ký tự ở vị trí thứ i của xâu X

Yêu cầu: Hãy tìm số ít nhất các phép biến đổi để biến xâu X thành xâu Y.

Hướng dẫn : Gọi F[i,j] là số phép biển đổi ít nhất để biến đổi i ký tự đầu tiên của xâu X

thành j ký tự đầu tiên của xâu Y Ta sẽ có hai trường hợp xảy ra như sau:

- Nếu xi = yj, thì bài toán lúc này của chúng ta trở thành bài toán biến đổi xâu x1x2…xi-1thành xâu y1y2…yj-1 Do đó F[i,j] = F[i-1,j-1 ]

- Nếu xi <> yj thì lúc này chúng ta sẽ có 3 lựa chọn:

Do đó F[i,j] = F[i,j-1] + 1

Do đó F[i,j] = F[i-l,j] + 1

xâu y1y2…yj-1 Do đó F[i,j] = F[i-l,j-1] + 1

Cuối cùng ta có công thức:

; j=0

; i=0[ , ]

[ 1, 1]; x( [ , 1], [ 1, ], [ 01, 1]) 1; x

i j

i j

i j

5.8 Bài toán Xâu chung : Xâu ký tự A được gọi là xâu con của xâu ký tự B nếu ta có thể

xoá đi một số ký tự trong xâu B để được xâu A

Cho biết hai xâu ký tự X = <x1x2 xn>) và Y = <y1y2 ym>

Yêu cầu: Hãy tìm xâu ký tự Z có độ dài lớn nhất và là con của cả X và Y.

Hướng dẫn : Gọi F[i,j] là độ dài độ dài lớn nhất của xâu con chung của hai xâu: x1x2 xi

và xâu y1y2 yj Ta xét các trường hợp sau:

- Nếu xi = yj thì chắc chắn khi bổ sung được xi hoặc yj vào dãy con chung và độ dài sẽtăng thêm 1 Do đó : F[i,j] = F[i-1,j-1 ] + 1

Trang 24

- Nếu xi <> yj, thì đương nhiên là không tăng thêm chiều dài của dãy con chung Tuynhiên ta phải lựa chọn chiều dài lớn nhất của các dãy con chung trước đó Có hai lựa chọn

là F[i,j-1] hoặc F[i-1,j] Do đó : F[i,j] = Max(F[i,j-1],F[i-1,j])

Ta được công thức sau

0, khi i=0 or j=0 [ , ] [ 1, 1] 1, khi i,j>0 and x

max( [ , ], [ 1, ]), khi i,j>0 and x

5.9 Bài toán Palindrome : Dãy kí tự s được gọi là đối xứng (palindrome) nếu các phần

tử cách đều đầu và cuối giống nhau

Yêu cầu : Hãy cho biết cần xoá đi từ s ít nhất là bao nhiêu kí tự để thu được một dãy đối

xứng

Hướng dẫn : Gọi F[i,j] là chiều dài của dãy con dài nhất thu được khi giải bài toán

với dữ liệu vào là đoạn s[i j] Khi đó F[1,n] là chiều dài của dãy con đối xứng dài nhấttrong dãy n kí tự s[1 n] và do đó số kí tự cần loại bỏ khỏi dãy s[1 n] sẽ là : n – F[1,n]

Đó chính là đáp số của bài toán Ta xét các trường hợp sau:

- Nếu i > j, tức là chỉ số đầu trái lớn hơn chỉ số đầu phải, ta quy ước đặt F[i, j] = 0

- Nếu i = j thì F[i,i] = 1 vì dãy khảo sát chỉ chứa đúng 1 kí tự nên nó là đối xứng

- Nếu i < j và s[i] = s[j] Khi này hai kí tự đầu và cuối dãy s[i,j] giống nhau nên chỉ cầnxác định chiều dài của dãy con đối xứng dài nhất trong đoạn giữa là :s[i+1, j-1] rồi cộngthêm 2 đơn vị ứng với hai kí tự đầu và cuối dãy là được

Vậy ta có công thức : F[i,j] = F[i+1,j-1] + 2

- Nếu i < j và s[i] <> s[j], tức là hai kí tự đầu và cuối của dãy con s[i j] là khác nhau thì takhảo sát hai dãy con là s[i (j-1)] và s[(i+1) j] để lấy chiều dài của dãy con đối xứng dàinhất trong hai dãy này làm kết quả Do đó F[i,j] = max(F[i,j-1],F[i+1,j])

Trang 25

5.10 Bài toán Vận may : Một người may mắn gặp một ma trận kim cương gồm MxN ô.

Giá trị A[i,j] (A[i,j] là một số nguyên dương) là lượng kim cương có ở ô ở dòng i cột j.Người này chỉ được xuất phát tử một ô ở mép bên trái của ma trận và di chuyển sang mépbên phải Từ ô (i,j) người này chỉ có thể di chuyến sang 1 trong 3 ô (i-l,j+1), (i,j+l) hoặc(i+1,j+1) Di chuyển qua ô nào thì người đó được mang theo lượng kim cương ở ô đó

Yêu cầu : Em hãy giúp người này di chuyển theo đường đi nào để có thể nhận được nhiêu

kim cương nhất

Hướng dẫn : Gọi F[i,j] là giá trị lớn nhất có được khi di chuyển đến ô (i,j) Có 3 ô có thể

di chuyển đến ô (i,j) là ô (i,j-l), (i-1 ô-l) và (i+l,j-l)

- Rõ ràng đối với những ô ở cột 1 thì F[i,1] = A[i,1]

- Với những nút (i,j) ở các cột khác, vì chỉ những nút (i, j-1), (i-1, j-1), (i+1, j-1) là có thểsang được nút (i,j), và khi sang nút (i,j) thì số điểm được cộng thêm A[i,j] nữa

Công thức :

[1, ]; j=1[ , ]

5.11 Bài toán phân tích số : Cho số tự nhiên N

Yêu cầu : Tìm các cách phân tích N thành tổng các số tự nhiên nhỏ hơn hoặc bằng N Hướng dẫn: Gọi F[m,v] là số cách phân tích số v thành tổng các số ≤ m Khi đó cách

phân tích số v thành tổng các số ≤ m có thể chia làm hai loại:

- Loại 1: Không chứa số m trong phép phân tích, khi đó số cách phân tích loại này chính

là số cách phân tích số v thành tổng các số nguyên dương ≤ m-1 Chính là F[m-1,v]

- Loại 2: Có chứa ít nhất một số m trong phép phân tích Khi đó nếu trong các cách phântích loại này ta bỏ đi số m đó thì ta sẽ được các cách phân tích số v–m thành tổng các sốnguyên dương ≤ m Chính là F[m,v–m]

Trong trường hợp m > v thì rõ ràng chỉ có các cách phân tích loại 1, còn trong trường hợp

m ≤ v thì sẽ có cả các cách phân tích loại 1 và loại 2 Vì thế ta có công thức

1; m=0, v=00; m=0, v 0[ , ]

[ 1, ]; m>v[ -1, ] [ , - ]; m v

Trang 26

5.12 Bài toán chia phần thưởng : Có m phần thưởng và n bạn học sinh sắp theo thứ tụ

từ giỏi trở xuống

Yêu cầu : Cần chia hết m phần thưởng cho n học sinh sao cho mỗi bạn không nhận ít

phần thưởng hơn bạn xếp sau mình

Thí dụ: với số phần thưởng m =7, và số học sinh n = 4 sẽ có 11cách chia:

Hướng dẫn : Gọi F[i,j] là số cách chia i phần thưởng cho j học sinh, ta thấy:

- Nếu không có học sinh nào (j=0) thì không có cách chia nào

- Nếu không có phần thưởng nào (i=0) thì có một cách chia mỗi học sinh nhận 0 phần

- Nếu số phần thưởng ít hơn số học sinh (i<j) thì trong mọi phương án chia, từ học sinh thứ i+1 trở đi sẽ không được nhận phần thưởng nào: F[i,j] = F[i,i]

Ta xét tất cả các phương án chia trong trường hợp i j Ta tách các phương án chia

thành hai nhóm không giao nhau dựa trên số phần thưởng mà học sinh đứng cuối bảng thành tích - học sinh thứ j, được nhận:

- Nhóm thứ nhất gồm các phương án trong đó học sinh thứ j không được nhận thưởng, tức là i phần thưởng chỉ chia cho j-1 học sinh và d đó, số cách chia, tức là số phần

tử của nhóm này sẽ là: F[i, j-1]

- Nhóm thứ hai gồm các phương án trong đó học sinh thứ j cũng được nhận thưởng Khi

đó mọi học sinh khác cũng sẽ có thưởng Do ai cũng được thưởng nên ta bớt của mỗi người một phần thưởng (để họ lĩnh sau), số phần thưởng còn lại (i-j) sẽ được chia cho j học sinh Số cách chia khi đó sẽ là F[i-j,j]

Tổng hợp lại ta có công thức :

0; j=01; i=0 and j 0[ , ]

[ , ]; i<j[ , 1] [ , ]; i j

Trang 27

IV Tham lam

1 Tổng quan

Tư tưởng của phương pháp tham ăn như sau: Ta xây dựng tập nghiệm X dần từng bước,bắt đầu từ tập rỗng X=∅ Giả sử đã xây dựng được (k-1) thành phần X=(x1,x2, ,xk-1) của

nghiệm và khi mở rộng nghiệm ta sẽ chọn x k ”tốt nhất” trong các ứng cử viên trong tập S k

để được X=(x1, x2, , xk) Việc lựa chọn như thế được thực hiện bởi một hàm chọn Cứtiếp tục xây dựng, cho đến khi xây dựng xong hết thành phần của nghiệm

Lược đồ tổng quát của phương pháp tham ăn.

Các bài toán tham lam thường sử dụng thuật toán sắp xếp để được thứ tự tối ưu

Một số bài toán giải được bằng tham lam : cây khung nhỏ nhất, đường đi ngắn nhất,

lập lịch trễ hạn ít nhất

Một số bài toán giải được bằng tham lam chỉ cho ngiệm gần tối ưu : chia bánh Ai cập,

tô màu bản đồ, chia các quận, phủ vecto

Một số bài toán giải không được bằng tham lam : đổi xu, vali.

Trang 28

2 Bài toán minh họa

Bài toán 1 Xếp lịch thực hiện : Chúng ta có rất nhiều nhiệm vụ trong ngày Giả sử có n

nhiệm vụ và nhiệm vụ thứ i phải bắt đầu ngay sau thời điểm si, thực hiện liên tục và kếtthúc tại thời điểm fi Có thể coi mỗi nhiệm vụ tương ứng với một khoảng thời gian thựchiện (si,fi]

Yêu cầu : Hãy chọn ra nhiều nhất các nhiệm vụ để làm, sao cho không có thời điểm nào

chúng ta phải làm hai nhiệm vụ cùng lúc, hay nói cách khác, khoảng thời gian thực hiệnhai nhiệm vụ bất kỳ là không giao nhau

Ví dụ:

Hướng dẫn : Tư tưởng của giải thuật tham lam có thể tóm tắt lại:

Chọn i1 là nhiệm vụ kết thúc sớm nhất

Chọn i2 là nhiệm vụ kết thúc sớm nhất bắt đầu sau khi i1 kết thúc: s[i2] > f[i1]

Chọn i3 là nhiệm vụ kết thúc sớm nhất bắt đầu sau khi i2 kết thúc: s[i3] > f[i2]

Cứ như vậy cho tới khi không còn nhiệm vụ nào chọn được nữa

Đến đây ta có thể thiết kế một giải thuật lặp:

Sắp xếp các nhiệm vụ theo thứ tự không giảm của thời điểm kết thúc f[i]

Khởi tạo thời điểm FinishTime = 0

Duyệt các nhiệm vụ theo danh sách đã sắp xếp (nhiệm vụ kết thúc sớm sẽ được xéttrước nhiệm vụ kết thúc muộn), nếu xét đến nhiệm vụ i có s[i]≥ FinishTime thìchọn ngay nhiệm vụ i vào phương án tối ưu và cập nhật FinishTime thành thời điểmkết thúc nhiệm vụ : FinishTime = f[i]

Cách phát biểu khác của bài toán : Đoạn rời Cho N đoạn thẳng với các điểm đầu ai

và điểm cuối bi Hai đoạn thẳng [a,b] và [c,d] được coi là không giao nhau nếu chúngkhông có điểm chung Liệt kê số lượng tối đa đoạn thẳng không giao nhau

Trang 29

Bài toán 2 Phủ đoạn: Cho N đoạn thẳng trên trục số với các điểm đầu ai và điểm cuối bi Yêu cầu : Hãy chỉ ra ít nhất đoạn thẳng sao cho khi đặt chúng trên trục số thì có thể phủ

kín đoạn [p,q] với tọa độ nguyên cho trước

Ví dụ :

Hướng dẫn : Tư tưởng của giải thuật tham lam có thể tóm tắt lại:

Chọn đoạn [ai1,bi1] có bi1 lớn nhất thỏa mãn p∈[ai1,bi1] Nếu đoạn này phủ hết đoạn [p,q]: thì xong Nếu không, ta lại chọn tiếp đoạn [ai2,bi2] có bi2 lớn nhất và phủ được điểmpmới=bi1, và cứ tiếp tục như vậy, ta có phương án tối ưu:

[ai1,bi1] [ai2,bi2] [ai3,bi3]……[aik,bik]

Nhận xét:

- Các đoạn được chọn vào phương án tối ưu có cận trên tăng dần: bi1 < bi2 < … < bikĐiều này có thể dễ hình dung được qua cách chọn: Mỗi khi chọn một đoạn mới, đoạn này sẽ phải phủ qua cận trên của đoạn trước đó

- Các đoạn được chọn vào phương án tối ưu có cận dưới tăng dần: ai1 < ai2 < … < aik.Thật vậy, nếu cận dưới của các đoạn được chọn không tăng dần thì trong số các đoạn được chọn sẽ có hai đoạn chứa nhau, suy ra phương án này không phải tối ưu

Đến đây ta có thể thiết kế một giải thuật lặp:

Sắp xếp danh sách các đoạn đã cho theo thứ tự không giảm của cận dưới Đặt i = 1 Bước 1: Xét phần danh sách bắt đầu từ vị trí i gồm các đoạn có cận dưới ≤p Tìm trongphần này để chọn ra đoạn có cận trên RightMost lớn nhất vào phương án tối ưu

Bước 2: Nếu RightMost≥q, thuật toán kết thúc Nếu không, đặt p = RightMost, cập nhật i thành chỉ số đứng sau đoạn vừa xét và lặp lại từ bước 1 (Ta bỏ qua những đoạnđứng trước vị trí i, bởi những đoạn nằm trong phần này đều có cận trên ≤RightMost)

Trang 30

Bài toán 3 Xử lý lỗi: Bạn là một người quản trị một hệ thống thông tin, và trong hệ

thống cùng lúc đang xảy ra n lỗi đánh số từ 1tới n Lỗi i sẽ gây ra thiệt hại di sau mỗi ngày

và để khắc phục lỗi đó cần ti ngày Tại một thời điểm, bạn chỉ có thể xử lý một lỗi

Yêu cầu : Hãy lên lịch trình xử lý lỗi sao cho tổng thiệt hại của n lỗi là nhỏ nhất có thể.

Ví dụ :

Hướng dẫn:Do mỗi lỗi chỉ ngưng gây thiệt hại khi nó được khắc phục, nên dễ thấy rằng

lịch trình cần tìm sẽ phải có tính chất: Khi bắt tay vào xử lý một lỗi, ta sẽ phải làm liêntục cho tới khi lỗi đó được khắc phục Tức là ta cần tìm một hoán vị của dãy số (1,2 n)

tương ứng với thứ tự trong lịch trình khắc phục các lỗi.

Giả sử rằng lịch trình A = (1,2, ,i,i+1,…,n) xử lý lần lượt các lỗi từ 1 tới n là lịch trình tối

ưu Ta lấy một lịch trình khác B= (1,2, ,i,i+1,…,n) có được bằng cách đảo thứ tự xử lý hai lỗi liên tiếp: i và i+1 trên lịch trình A Ta sẽ chứng minh được rằng nếu lịch trình A tối

ưu thì nó phải thỏa mãn :

n n

Trang 31

BÀI TẬP CHƯƠNG IV

Một máy ATM hiện có n (n < 20) tờ tiền có giá t1; t2, , tn

Yêu cầu : Hãy tìm cách trả ít tờ nhất với số tiền đúng bằng S.

Dữ liệu vào từ file “ATM.INP” có dạng:

Trang 32

Bài 2 Người du lịch Tên file chương trình ‘TSP.???’

Có n thành phố (được đánh số từ l đến n) Một người du lịch xuất phát từ l thành phố, muốn đi thăm các thành phố khác, mỗi thành phố đúng l lần rồi quay lại về nơi xuất phát Biết chi phí đi từ thành phố i đến thành phố j là C[i,j]

Yêu cầu : Hãy chỉ ra cho người đó hành trình với chi phí ít nhất

Dữ liệu vào trong file “TSP.INP” có dạng:

■ Dòng đầu chứa số n(1<n<20), là số thành phố

■ N dòng tiếp theo, mỗi dòng n số mô tả mảng C

Kết quả ra file “TSP.OUT” : Ghi chi phí ít nhất.

Trang 33

Bài 3: Người du lịch 2 Tên file chương trình ‘TOURIST.???’

Có n thành phố (được đánh số từ l đến n) Một người du lịch xuất phát từ l thành phố, muốn đi thăm các thành phố khác, mỗi thành phố đúng l lần rồi quay lại về nơi xuất phát Biết chi phí đi từ thành phố i đến thành phố j là C[i,j]

Yêu cầu: Hãy tìm l hành trình cho người du lịch để tổng chi phí theo hành trình này là

nhỏ nhất Giả sử là từ i đến j luôn tồn tại l đường đi

Dữ liệu vào từ file ‘TOURIST.INP’:

Trang 34

Bài 4 Con kiến 3 Tên file chương trình ‘ANT3.???’

Cho hình chữ nhật kích thước m x n, người ta chia hình chữ nhật thành m x n hình vuông

có cạnh 1 đơn vị Ô trái trên là (1,1), ô phải dưới là (m,n)

Một con kiến bò từ góc trái dưới (A) đến góc phải trên (B) theo nguyên tắc sau: đi lên (kýhiệu L) hoặc sang phải (ký hiệu P) theo cạnh của hình vuông

Yêu cầu : Hãy chỉ ra tất cả các đường đi của con kiến để có thể đi từ A đến B

Dữ liệu vào trong file “ANT3.INP” có dạng: gồm 2 số n, m(1<n,m<30)

Kết quả ra file “ANT3.OUT” : Ghi tổng số cách đi.

Trang 35

Bài 5 Mã Cipher Tên file chương trình ‘CIPHER.???’

Cho dãy gồm N số nguyên, dùng để mã hóa các thông báo Mỗi thông báo có n bit Nếudãy bit của thông báo là : t1t2…tn thì nó mã hóa thành số :

S = t1*a1 + t2*a2 +…+ tn*an

Yêu cầu : Cho thông báo đã mã hóa và dãy số ai Hãy giải mã thông báo.

Dữ liệu vào trong file “CIPHER.INP” có dạng:

■ Dòng đầu chứa số n(1<n<20)

■ N dòng tiếp theo, mỗi dòng một số ai

■ Dòng cuối cùng chứa số s là thông báo đã mã hóa

Kết quả ra file “CIPHER.OUT” : Ghi thông báo đã giải mã.

Cho số nguyên dương n (n<20),

Yêu cầu : Tìm số cách khác nhau đặt n dấu ngoặc mở và n dấu ngoặc đóng đúng đắn?

Dữ liệu vào trong file “NGOAC3.INP” : chứa số n (1<n<20).

Kết quả ra file “NGOAC3.OUT” : Ghi số cách đặt.

Ví dụ:

Trang 36

Bài 7 Chia K nhóm Tên file chương trình ‘DIVK.???’

Cho dãy số A gồm N (N<10) số nguyên a1, a2, ,an và một số nguyên dương K (1<K<N)

Yêu cầu : Hãy đưa ra số cách chia dãy số thành K nhóm mà các nhóm có tổng bằng nhau.

Dữ liệu vào trong file “DIVK.INP” có dạng:

■ Dòng đầu chứa số n, k(1<n, k<20)

■ N dòng tiếp theo, mỗi dòng một số ai

Kết quả ra file “DIVK.OUT” : Ghi số cách chia.

Trang 37

Bài 8 Xếp chỗ Tên file chương trình ‘XEPCHO.???’

Liên hợp quốc tổ chức cuộc họp của N nước tham gia Các đại biểu sẽ được ngồi quanhbàn tròn Giữa một số nước có quan hệ căng thẳng nên không thể xếp họ ngồi cạnh nhau

Yêu cầu : Hãy đưa ra số cách xếp thỏa yêu cầu của bài.

Dữ liệu vào trong file “XEPCHO.INP” có dạng:

■ Dòng đầu chứa số n(1<n<20)

■ N dòng tiếp, dòng i chứa các số nguyên cho biết các nước có căng thẳng với nước i

Kết quả ra file “XEPCHO.OUT” : Ghi số cách xếp chỗ ngồi.

Trang 38

Bài 9: Bảng vuông Tên file chương trình ‘TABSQUA.???’

Cho một bảng vuông có kích thước n hàng và n cột Hàng được đánh số thứ tự từ 1 đến ntheo trình tự từ trên xuống dưới, Cột được đánh số thứ tự cũng từ 1 đến n theo trình tự từtrái qua phải Giao của hàng i và cột j là ô (i,j) Trên ô (i,j) của bảng có giá trị là aij

Trang 39

Kết quả các ô được chọn (in đậm) có tổng là 2+3+1+5=11 là nhỏ nhất.

Dữ liệu vào từ file ‘TABSQUA.INP’ có nội dung như sau:

■ Dòng đầu là số nguyên dương n (n<18)

■ Trong n dòng sau, mỗi dòng gồm n số nguyên dương mô tả các giá trị của bảng vuông

Kết quả ghi vào file ‘TABSQUA.OUT’ số nguyên duy nhất là giá trị nhỏ nhất tìm được.

Trang 40

Bài 10: Tổ chức công việc Tên file chương trình ‘NMIN.???’

Cho N công việc, công việc i hoàn thành trong thời gian ti Các công việc được thực hiệntrên M máy (công suất như nhau), mỗi công việc được làm liên tục trên một máy

Yêu cầu: Hãy tổ chức các máy thực hiện đủ N công việc sao cho thời gian hoàn thành tất

cả các công việc càng sớm càng tốt

Dữ liệu vào từ file ‘NMIN.INP’:

■ Dòng đầu tiên là hai số N và M (N,M<100)

■ Dòng tiếp theo là N số ti, t2, ,tn

Kết quả ghi vào file ‘NMIN.OUT’ thời gian sớm nhất hoàn thành N công việc

Ví dụ:

6 3

Ngày đăng: 24/09/2019, 22:15

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w