Mặc dù không tồn tại một ph-ơng pháp vạn năng có thể giúp ta xây dựng đ-ợc thuật toán giải quyết mọi vấn đề, nh-ng các nhà nghiên cứu đã tìm ra một số ph-ơng pháp xây dựng thuật toán..
Trang 1Lời nói đầu
Theo một nghĩa nào đó, có thể xem máy tính nh- một công cụ để giải các bài toán ở đây khái niệm bài toán đ-ợc quan niệm một cách rất mềm dẻo bao gồm các bài toán hiểu theo nghĩa thuần tuý toán học nh- những tr-ờng hợp riêng Nói một cách đơn giản, ta có thể đồng nhất việc giải một bài toán với việc làm một việc gì
đó bằng máy tính Nh- vậy, học sử dụng máy tính thực chất là học cách làm thể nào giao cho máy tính làm đ-ợc việc mà ta muốn nó làm Cần chú ý rằng máy tính là một vật vô tri vô gi²c, sứ ‚thông minh‛ cða m²y tính chỉ l¯ sứ thể hiện sứ thông minh của ng-ời sử dụng nó Cùng một loại máy tính, chất l-ợng khai thác công cụ
đó rất khác nhau ở mỗi ng-ời Vậy thì thế nào là giao cho máy điều cần làm? Nói vắn tắt đó là việc lập ch-ơng trình cho máy tính Mỗi ch-ơng trình nhằm mục đích giải một bài toán nào đó, mục đích đó phải đ-ợc thể hiện thành những dãy thao tác m¯ m²y có thể thức hiện được Việc viết c²c ‚mệnh lệnh‛ để giao cho m²y thức hiện đ-ợc gọi là việc lập trình cho máy tính Ng-ời lập trình chuyển lời giải bài toán thành các lệnh cho máy thực hiện Quá trình đó gồm các giai đoạn
- Xác định rõ bài toán cần giải quyết
- Xây dựng thuật toán
- Viết ch-ơng trình
- Thử và hiệu chỉnh ch-ơng trình
- T- liệu hoá ch-ơng trình
Mặc dù không tồn tại một ph-ơng pháp vạn năng có thể giúp ta xây dựng
đ-ợc thuật toán giải quyết mọi vấn đề, nh-ng các nhà nghiên cứu đã tìm ra một số ph-ơng pháp xây dựng thuật toán Mỗi ph-ơng pháp có thể áp dụng để giải quyết một phạm vi khả rộng các bài toán Có rất nhiều ph-ơng pháp trong chiến l-ợc xây dựng thuật toán nh-: Chia- để - trị, ph-ơng pháp tham ăn, quay lui, nhánh và cận,
Trang 2quy hoạch động Trong khuôn khổ luận văn tốt nghiệp của mình, tôi muốn đ-ợc
tìm hiểu phương ph²p xây dứng thuật to²n b´ng phương ph²p ‚Quy hoạch động‛
và giải một số bài toán điển hình - đ-ợc ứng dụng rất nhiều trong thực tế
Để có thể thực hiện đ-ợc đề tài này, tôi đã đ-ợc sự h-ởng dẫn rất nhiệt tình
của thầy giáo Trần Xuân Hào, sự ủng hộ của các bạn trong lớp Tôi xin cảm ơn
thầy và các bạn rất nhiều Có thể nói, trong quá trình thực hiện đề tài tôi đã cố gắng hết sức mình Do đó, kết quả đạt đ-ợc là đáng đ-ợc ghi nhận nh-ng chắc chắn không tránh khỏi những thiếu sót, những vấn đề ch-a làm đ-ợc không phải là ít Rất mong đ-ợc dạy bảo, đóng góp ý kiến của các thầy cô giáo và các bạn
Một lần nữa, tôi xin cảm ơn các thầy cô giáo và các bạn rất nhiều
Vinh, ngày 05 tháng 05 năm 2004
Sinh viên thực hiện:
Tô Hữu Hùng
Trang 3Tóm tắt
Ch-ơng I Thuật toán và các ph-ơng pháp thiết kế phổ dụng
I.1 Một số khái niệm cơ bản
I.1.1 Khái niệm về thuật toán
I.1.1.1 Sơ l-ợc về lịch sử
I.1.1.2 Khái niệm về bài toán tính toán
I.1.1.3 Khái niệm thuật toán
I.1.1.4 Mở rộng khái niệm thuật toán
I.1.2 Xây dựng thuật toán
I.1.2.1 Quan niệm về thuật toán
I.1.2.2 Mô tả thuật toán
I.1.2.3 Hiệu quả của thuật toán
I.2 Một số ph-ơng pháp thiết kế thuật toán phổ dụng
I.2.1 Chia - để – trị
I.2.2 Ph-ơng pháp tham ăn
I.2.3 Ph-ơng pháp quay lui
I.2.4 Ph-ơng pháp nhánh và cận
Ch-ơng II Ph-ơng pháp Quy hoạch động
II.1 Nội dung ph-ơng pháp
II.2 Các b-ớc thực hiện Quy hoạch động
II.3 Hạn chế của Quy hoạch động
Ch-ơng III Một số bài toán điển hình
III.1 Dãy con không giảm dài nhất
III.2 Dãy con chung dài nhất của hai dãy số nguyên
III.3 Xếp hàng mua vé
III.4 Di chuyển từ tây sang đông
III.5 Bài toán sắp xếp đồ vật vào Ba lô
III.6 Tìm đ-ờng đi ngắn nhất giữa 2 thành phố
Trang 4Môc lôc
Trang
Ch-¬ng I ThuËt to¸n vµ c¸c ph-¬ng ph¸p thiÕt kÕ phæ dông 6
I.2 Mét sè ph-¬ng ph¸p thiÕt kÕ thuËt to¸n phæ dông 13
Trang 5Ch-¬ng III Mét sè bµi to¸n ®iÓn h×nh 26
III.2 D·y con chung dµi nhÊt cña hai d·y sè nguyªn 29
Trang 6
Ch-ơng I Thuật toán và các ph-ơng pháp thiết kế phổ dụng
I.1 Một số khái niệm cơ bản
I.1.1 Khái niệm về thuật toán
I.1.1.1 Sơ l-ợc về lịch sử
Thuật toán đã đ-ợc biết đến từ rất lâu Bản thân thuật ngữ Thuật toán (Algorithm) l¯ viết tắt tên cða nh¯ to²n học thế kỷ thữ IX: Abu Ja’fa Mohammed ibn Musa al-Khowarizmi Khái niệm thuật toán có một lịch sử phát triển lâu dài Chúng ta hãy điểm qua một số móc quan trọng
Đầu tiên, thuật toán đ-ợc hiểu nh- là các quy tắc thực hiện các phép tính số học với các con số đ-ợc viết trong hệ cơ đếm thập phân
Euclid đề xuất thuật toán để tìm -ớc số chung lớn nhất của hai số GCD(x,y)
Hibert vào năm 1900 đã đề xuất một vấn đề rất hóc búa cho cộng đồng các nh¯ to²n học: ‚H±y xây dứng một thð túc m¯ theo đó sau một số hửu h³n phép to²n có thể x²c định một đa thữc có nghiệm nguyên hay không‛ Vấn
đề này đ-ợc biết dưới tên gọi ‚B¯i to²n thữ 10 cða Hibert‛
Chúng ta có ví dụ về thuật toán, nh-ng ch-a có định nghĩa hình thức thể nào
là thuật toán Để chứng minh là không tồn tại thuật toán giải bài toán tính toán, ta cần có định nghĩa hình thức của thuật toán
Năm 1936, hai nhà toán học Turing và Church mỗi ng-ời đã đề xuất một mô hình tính toán riêng, mà sau đó đ-ợc chứng minh là t-ơng đ-ơng
Bài toán về tính dừng (halting problem) và bài toán về nghiệm nguyên của đa thức (Integer Root Problem) đã đ-ợc chứng minh là các bài toán không có thuật toán giải
Trang 7 Sự xuất hiện của máy tính điện tử là một động lực thúc đẩy sự phát triển mạnh mẽ của các nhà nghiên cứu về cơ sở lý thuyết của khoa học máy tính nói chung và thuật toán và độ phức tạp tính toán nói riêng
I.1.1.2 Khái niệm bài toán tính toán (Computational Problem)
Một cách không hình thức, bài toán tính toán là ánh xạ từ tập các đầu vào nào
đó vào tập các đầu ra nhất định Chẳng hạn, đầu vào là một đa thức nhiều biến P còn đầu ra là bộ những giá trị nguyên của biến số mà tại đó đa thức nhận giá trị 0
Ta nói một thuật toán hay một máy giải đ-ợc bài toán nếu mọi bộ dữ liệu vào có thể, nó luôn dừng và đ-a ra đầu ra đúng của bài toán Trong cách trình bày hình thức khái niệm độ phức tạp tính toán, ng-ời ta luôn giả thiết là cả đầu vào lẫn đầu ra
đều là các xâu nhị phân {0, 1}n
Định nghĩa Bài toán tính toán F là ánh xạ từ tập các xâu nhị phân độ dài hữu
hạn vào tập các xâu nhị phân độ dài hữu hạn: F: {0, 1}* {0, 1}*
Một trong những vấn đề quan trọng nhất tr-ớc khi chúng ta muốn xử lý các
đầu vào không phải là xâu nhị phân, đó là tìm cách biểu diễn chúng d-ới dạng xâu
Ta có thể dùng xâu để biểu diễn các đối t-ợng nh- các đa thức, đồ thị, ôtômat, ngôn ngữ, âm thanh, hình ảnh , cũng nh- mọi tố hợp của các đối t-ợng này
Đồ thị có thể biểu diễn bởi ma trận kề
Đa thức một biến: P(x) = a0 + a1x + +anxn, hoàn toàn xác định bởi dãy số n, a0, a1, , an, mà để biểu diễn dãy số này chúng ta có thể sử dụng xâu nhị phân
Trang 8Máy turing có thể cài đặt để giải mã các biểu diễn này, và vì thế nó có thể thực hiện đ-ợc những thao tác mà ta đòi hỏi
Ta sẽ dùng <O> để ký hiệu mã hoá của biểu diễn của một đối t-ợng O d-ới dạng xâu Nếu có nhiều đối t-ợng O1, O2, , On cần biểu diễn thì ta dùng ký hiệu
<O1, O2, ,On> Tất nhiên, việc mã hoá một đối t-ợng có thể thực hiện bằng nhiều cách Tuy nhiên việc chọn cách biểu diễn hợp lý có ý nghĩa quan trọng trong việc
xử lý các đối t-ợng đó Chẳng hạn, không nên biểu diễn một đồ thị nh- là danh sách tất cả các đ-ờng đi có thể có trên nó
I.1.1.3 Khái niệm thuật toán
Định nghĩa Thuật toán là một hệ thống chặt chẽ và rõ ràng các quy tắc nhằm
xác định một dãy các thao tác trên những đối t-ợng, sao cho sau một số hữu hạn b-ớc thực hiện các thao tác, ta đạt đ-ợc mục tiêu định tr-ớc
Các đặc tr-ng của thuật toán
Tính xác định: Mỗi b-ớc của thuật toán, các thao tác phải hết sức rõ ràng Không thể gây nên sự nhập nhằng, lẫn lộn, tuỳ tiện Nói cách khác là trong cùng một điều kiện, hai bộ xử lý cùng thực hiện một b-ớc của thuật toán thì phải có cùng một kết quả
Tính hữu hạn dừng: Một thuật toán bao giờ cũng phải dừng lại sau một số hữu hạn b-ớc
Tính đúng đắn: Sau khi thực hiện tất cả các lệnh của thuật toán ta phải đ-ợc kết quả mong muốn, kết quả đó th-ờng đ-ợc xác định theo định nghĩa cho tr-ớc
Tính phổ dụng: Thuật toán có thể giải bất kỳ bài toán nào trong cùng một lớp các bài toán, có nghĩa là thuật toán có thể làm việc với các dữ liệu khác nhau, trong một miền xác định và luôn dẫn đến kết quả mong muốn
Tính có đại l-ợng vào và ra: Khi bắt đầu, một thuật toán bao giờ cũng nhận các đại l-ợng vào mà ta th-ờng gọi là dữ liệu vào, các dữ liệu vào th-ờng
Trang 9lấy từ một tập xác định cho tr-ớc Sau khi kết thúc, một thuật toán bao giờ cũng cho ta một số đại l-ợng ra tuỳ theo chức năng mà thuật toán đảm nhiệm, chúng th-ờng đ-ợc gọi là dữ liệu ra
Tính hiệu quả: Tính hiệu quả của một thuật toán đ-ợc đánh giá dựa trên các tiêu chuẩn sau
- Dung l-ợng bộ nhớ cần có
- Số các phép toán cần thực hiện
- Thời gian cần thiết để chạy
- Có dễ hiểu đối với con ng-ời không?
- Có dễ cài đặt trên máy không?
I.1.1.4 Mở rộng khái niệm thuật toán
Để có thể giải các bài toán bằng máy tính chúng ta th-ờng phải có một quan niệm rộng rãi hơn về thuật toán Cụ thể là l-u ý đến các đặc điểm sau
Không cần xác định toàn bộ lời giải các thao tác theo từng b-ớc một cách chính xác, đơn vị và rõ ràng Thay vào đó chỉ cần chỉ ra một cách chuyển từ một b-ớc giải i tới b-ớc giải tiếp i+1, và tìm cách cắt nhỏ bài toán thành các bài toán con,
đó chính là thuật toán Đệ quy rất quan trọng để giải các bài toán tổng quát
Có nhiều bài toán không có cách giải đúng hoặc cách giải đúng không thể chấp nhận đ-ợc do hạn chế về thời gian chạy và kích th-ớc về bộ nhớ Nh-ng nếu chúng ta chấp nhận kết quả gần đúng thì có thể tồn tại nhiều cách giải đỡ phức tạp và có hiệu quả hơn, đó chính là các thuật toán Heuristic giải các bài toán gần đúng
I.1.2 Xây dựng thuật toán
I.1.2.1 Quan niệm về thuật toán
Nh- chúng ta đã nói ở trên, việc cho một bài toán có nghĩa là cho input và output Việc giải bài toán có nghĩa là tìm cách xuất phát từ input tìm đ-ợc output
Trang 10theo yêu cầu của bài toán đã đề ra và công việc đó ta muốn giao cho máy tính làm Chính vì vậy, ta chỉ quan tâm đến những ph-ơng pháp hiệu quả để xuất phát từ input của bài toán, ta dẫn ra đ-ợc output cần thiết
Một ph-ơng pháp hiệu quả để giải một bài toán nào đó là việc xác định t-ờng minh output theo input bằng một quá trình bao gồm một tập hợp hữu hạn các thao tác đơn giản đ-ợc sắp xếp theo một trình tự xác định sao cho theo đó, từ input ta sẽ nhận đ-ợc output cần tìm hoặc khẳng định không có output nh- bài toán đó đòi hỏi
Về mặt thuật ngữ, ta gọi quá trình nh- vậy là một thuật toán (algorithm) Đó chính là quan niệm trực quan về thuật toán Nh- vậy, giải một bài toán là xây dựng một thuật toán đối với bài toán đó Nói cụ thể hơn, việc giải một bài toán P nào đó
là việc xây dựng một tập hữu hạn các thao tác đơn giản đ-ợc sắp xếp theo một trình
tự xác định sao cho sau khi hoàn thành dãy thao tác đó, ta thu đ-ợc output của P Chỉ những dãy thao tác nh- vậy mới có khả năng chuyển giao cho máy tính thực hiện đ-ợc
Toán học vẫn rất cần những nghiên cứu định tính và những kết quả có đ-ợc theo h-ớng nghiên cứu này đã, đang và sẽ vẫn có những vị trí xứng đáng trong toán học nói riêng và khoa học nói chung Tuy nhiên, trong khuôn khổ của tin học, khi nói đến việc giải bài toán, ta sẽ chỉ quan tâm đến những ph-ơng pháp hiệu quả để xuất phát từ input của bài toán, dẫn ra đ-ợc output cần thiết
Trong quá trình nghiên cứu giải bài toán theo nghĩa nêu trên, trong toán học
đã diẽn ra một quá trình phát triển đầy kịch tính Cho tới đầu thế kỷ XX, với lòng tin tiên nghiệm vào việc mọi bài toán (phát biểu đúng đắn) đều có thuật toán giải, nhiều nhà toán học đầy tài năng và tâm huyết đã tiến công vào vào các bài toán
đang tồn tại nh- những lời thách đố con ng-ời
Vấn đề then chốt nhất của lý thuyết tính toán phát sinh ở đây Để chứng minh một bài toán nào đó có thuật toán giải nó, ta chỉ cần đề ra một thuật toán theo quan niệm trực giác của khái niệm này và kiếm định tính đúng đắn của nó đối với bài toán đã cho Tuy nhiên, khi cần chứng minh việc không có thuật toán giải một bài
Trang 11toán nào đó, quan niệm trực quan về thuật toán không thể là cơ sở đảm bảo cho một chứng minh toán học chặt chẽ đ-ợc Do đó, muốn chứng minh những điều khẳng
định ‚không có thuật to²n gi°i một b¯i to²n n¯o đó‛, ta cần có một định nghĩa to²n học cho khái niệm thuật toán
Vào những năm 1930-1936, lần l-ợt các nhà toán học K.Godel, S.Kleene, A.Church, A.Turing đã đề ra một số định nghĩa khác nhau cho khái niệm thuật toán Trong số các định nghĩa toán học khác nhau (nh-ng t-ơng đ-ơng) về thuật toán, các khái niệm máy Turing (1937) và hàm đệ quy (1931-1936) đ-ợc sử dụng rộng rãi hơn vì có nhiều thuận tiện cho các nghiên cứu cả về lý thuyết lẫn thực hành Ta có thể xem máy tính Turing là một mô hình toán học của máy tính
I.1.2.2 Mô tả thuật toán
Việc mô tả một thuật toán giải một bài toán nào đó có nghĩa là trình bày trình
tự các thao tác cơ bản của thuật toán Việc mô tả này có thể dùng ngôn ngữ thông th-ờng Ta có thể thấy cách mô tả qua một số ví dụ sau
Ví dụ 1 Thuật chia Euclide
Định lí Euclide khẳng định rằng cho tr-ớc hai số nguyên d-ơng bất kì a và b, luôn tồn tại duy nhất hai số q và r sao cho a=qb+r và 0 r < b, trong đó q đ-ợc gọi
là th-ơng của phép chia a cho b và r đ-ợc gọi là phần d- Bài toán đặt ra là cho tr-ớc a và b, ta cần tìm q và r Thuật toán giải bài toán này đ-ợc thể hiện nh- sau
B-ớc 0 q=0;
B-ớc 1 Nếu a < b thì r = a và kết thúc, nếu không thì chuyển đến b-ớc 2; B-ớc 2 Nếu a b thì thay a bởi a - b, q bởi q + 1 và quay về b-ớc 1;
Ta thấy rằng các b-ớc 0 -> 2 cho ta một thuật toán để tìm q và r vì mỗi b-ớc
đó đều l¯ nhửng ‚Thao t²c đơn gi°n‛ v¯ trình tứ thức hiện c²c thao t²c đó được x²c
định rõ ràng Dãy thao tác đó không thể tiếp diễn vô hạn vì mỗi lần quay trở lại b-ớc 1, a giảm đi một l-ợng là b
Trang 12Ví dụ 2 Cho dãy số a1, a2, ,an Hãy tìm giá trị lớn nhất max và giá trị nhỏ nhất min của dãy đó Thuật toán tìm max và min đ-ợc diễn đạt nh- sau
B-ớc 0 max=:a1; min:=a1; i:=2;
B-ớc 1 Nếu i n thì [ nếu ai < min thì thay min bằng ai ; Nếu ai > max thì thay max
bằng ai ] Nếu không thì kết thúc
B-ớc 2 Thay i bằng i + 1 và quay về b-ớc 1;
I.1.2.3 Hiệu quả của thuật toán
Cần chú ý rằng mỗi thuật toán chỉ giải một bài toán nào đó nh-ng có thể có nhiều thuật toán khác nhau giải cùng một bài toán Một vấn đề đặt ra là ta nên chọn một thuật toán tốt để giải bài toán đã cho
Nh-ng thế nào là thuật toán tốt ? Đây là nội dung nghiên cứu của lý thuyết
độ phức tạp của thuật toán Nói một cách đơn giản, khi dùng máy tính thực hiện một ch-ơng trình (thể hiện một thuật toán nào đó ), hệ điều hành cần cung cấp cho ch-ơng trình đó các tài nguyên nh- giờ CPU, bộ nhớ … Số l-ợng các tài nguyên cần dùng thể hiện độ phức tạp của thuật toán Thuật toán đ-ợc xem là tốt nếu ch-ơng trình t-ơng ứng dùng ít tài nguyên
Trong các tài nguyên để chạy ch-ơng trình, hiện nay ng-ời ta quan tâm nhiều nhất đến thời gian vì đó là dạng tài nguyên không tái tạo đ-ợc Một thuật toán đ-ợc xem là tốt nếu ch-ơng trình t-ơng ứng chạy nhanh, hay chính xác hơn, chạy trong thời gian chấp nhận đ-ợc Để đánh giá độ phức tạp của một thuật toán, ta có thể -ớc tính số thao tác cơ bản cần dùng để thực hiên thuật toán Th-ờng có hai cấu trúc phổ biến trong các thuật toán: Cấu trúc vòng lặp và cấu trúc đệ quy Số thao tác của một vòng lặp dễ dàng tính đ-ợc nh-ng nếu có một ch-ơng trình con đệ quy, việc -ớc l-ợng số thao tác khó khăn hơn vì ta phải tính một đại l-ợng theo một công thức truy hồi
Trang 13I.2 Một số ph-ơng pháp thiết kế thuật toán phổ dụng
I.2.1 Chia - để - trị
Ph-ơng pháp thiết kế thuật toán đ-ợc áp dụng rộng rãi nhất là chiến l-ợc chia -
để - trị T- t-ởng của chiến l-ợc này là nh- sau: Ng-ời ta phân bài toán cần giải thành các bài toán con Các bài toán con lại đ-ợc phân thành các bài toán con nhỏ hơn, cứ tiếp tục cho tới khi ta nhận đ-ợc các bài toán con hoặc đã có thuật giải, hoặc là có thể dễ dàng đ-a ra thuật giải Sau đó ta tìm cách kết hợp các nghiệm của các bài toán con để nhận đ-ợc nghiệm của bài toán con lớn hơn, để cuối cùng nhận
đ-ợc nghiệm của bài toán cần giải Thông th-ờng các bài toán con nhận đ-ợc trong quá trình phân chia là cùng dạng với bài toán ban đầu, chỉ có cở của chúng là nhỏ hơn Trong các tr-ờng hợp nh- thế, thuật toán tìm đ-ợc có thể biểu diễn một cách
tự nhiên bởi thủ tục đệ quy
Sau đây là l-ợc đồ ph-ơng pháp chia - để - trị
Procedure DivideConquer (A, x);
Tìm nghiệm của toàn bộ bài toán A
begin
if A đủ nhỏ Then solve (A)
else begin
Phân A thành các bài toán con A1, A2, , Am;
For i:=1 to m do DivideConquer (Ai, xi);
Kết hợp các nghiệm xi (i = 1, 2, , m) của các bài toán con Ai để nhận
đ-ợc nghiệm x của bài toán A;
End;
End;
Trong thủ tục trên, solve là thuật giải bài toán A trong tr-ờng hợp A có cở đủ nhỏ
Trang 14I.2.2 Ph-ơng pháp tham ăn
Ph-ơng pháp tham ăn là một chiến l-ợc thiết kế thuật toán th-ờng đ-ợc sử dụng để giải quyết các bài toán tối -u Nhiều vấn đề cần giải quyết có thể quy về vấn đề sau đây Cho tr-ớc một tập A các đối t-ợng nào đó, đòi hỏi phải chọn ra một tập con S các đối t-ợng thoả mãn các yêu cầu đã đặt ra đ-ợc gọi là nghiệm chấp nhận đ-ợc của bài toán Một hàm mục tiêu gắn mỗi nghiệm chấp nhận đ-ợc với một giá trị nào đó Một nghiệm chấp nhận đ-ợc mà tại đó hàm mục tiêu có giá trị lớn nhất (hoặc nhỏ nhất ) đ-ợc gọi là nghiệm tối -u
T- t-ởng của ph-ơng pháp tham ăn là nh- sau Ta xây dựng tập S dần dần tụng bước bắt đầu tụ tập rỗng T³i mỗi bước, ta sẽ chọn một phần từ ‛Tốt nhất ‛ trong các phần tử còn lại của A để đ-a vào S Việc lựa chọn một phần tử nh- thế ở mỗi b-ớc đ-ợc h-ớng dẫn bởi hàm chọn Phần tử đ-ợc chọn sẽ bị loại khỏi tập A Nếu thêm phần tử đ-ợc chọn vào tập S mà S vẫn còn thoả mãn các điều kiện của bài toán thì ta mở rộng S bằng cách thêm vào phần tử đ-ợc chọn
Trong l-ợc đồ tổng quát trên, select là hàm chọn, nó cho phép ta chọn ra từ tập
A một phần tử đ-ợc xem là tốt nhất, nhiều hứa hẹn nhất là thành viên của nghiệm
Trang 15Ta có thể dễ d¯ng thấy t³i sao c²c thuật to²n như thế được gọi l¯ ‚tham ăn‛ T³i mỗi bước nó chọn ‚miếng ngon nhất‛ (được x²c định bởi hàm chọn), nếu thấy
có thể nuốt đ-ợc (có thể đ-a vào nghiệm) nó sẽ xơi ngay, nếu không nó sẽ bỏ đi, sau này không bao giờ xem xét lại
Cần nhấn mạnh rằng, thuật toán tham ăn trong một số bài toán, nếu xây dựng
đ-ợc hàm chọn thích hợp có thể cho nghiệm tối -u Trong nhiều bài toán, thuật toán tham ăn chỉ tìm đ-ợc gần đúng với nghiệm tối -u
I.2.3 Ph-ơng pháp quay lui
Trong các kỹ thuật cơ bản thiết kế thuật toán, quay lui là một trong những kỹ thuật quan trọng nhất Nó có thể đ-ợc áp dụng để thiết kế thuật toán tìm ra một nghiệm hoặc tất cả các nghiệm của bài toán
Trong nhiều vấn đề, việc tìm nghiệm có thể quy về việc tìm một vectơ hữu hạn(x1, x2, , xn) nh-ng độ dài véc tơ có thể không đ-ợc xác định tr-ớc Vectơ này cần phải thoả mãn một số điều kiện nào đó tuỳ thuộc vào vấn đề cần giải Các thành phần xi của vectơ đ-ợc chọn ra từ một tập hữu hạn Ai(i=1,2, ,n)
Ví dụ Bài toán tám con hậu
Chúng ta cần đặt tám con hậu vào bàn cờ 8 x 8 sao cho chúng không tấn công nhau, tức là không có cặp con hậu nào nằm cùng hàng, cùng cột, cùng đ-ờng chéo
Do các con hậu phải nằm trên các hàng khác nhau, ta sẽ đánh số các con hậu
từ 1 đến 8, con hậu i là con hậu nằm ở dòng thứ i (i = 1, 2, , 8) Gọi xi là cột mà con hậu thứ i đứng Nh- vậy nghiệm của bài toán 8 con hậu là vectơ (x1, x2, , x8), trong đó 1 xi 8, tức là xi đ-ợc chọn từ tập Ai = 1, 2, , 8 Vectơ (x1, x2, , x8)
là nghiệm nếu xi xj và hai ô (i, xi), (j, xj) không nằm trên cùng một đ-ờng chéo T- t-ởng của ph-ơng pháp quay lui là nh- sau Ta xây dựng vectơ nghiệm dần từng b-ớc, bắt đầu từ vectơ không ( ) Thành phần đầu tiên x1 đ-ợc chọn ra từ tập
S1=A1 Khi đã chọn đ-ợc các thành phần x1, , xi-1 thì các điều kiện của bài toán ta
sẽ xác định đ-ợc tập Si các ửng cứ viên có thể chọn làm thành phần xi Tập Si là tập
Trang 16con của Ai và phụ thuộc vào các thành phần x1, x2, , xi-1 đã chọn Chọn một phần
tử xi từ Si ta mở rộng nghiệm một phần (x1, x2, , xi-1) đến nghiệm một phần (x1, x2, , xi) Lặp lại quá trình trên để tiếp tục mở rộng nghiệm một phần (x1, x2, , xi-1,
xi) Nếu không thể chọn đ-ợc thành phần xi+1 (khi Si+1 = ) thì ta quay lại chọn một phần tử khác của Si làm xi Nếu không còn một phần tử của Si ta quay lại chọn một phần tử khác của Si-1 làm xi-1 và cứ thể tiếp tục Trong quá trình mở rộng nghiệm, ta phải kiểm tra nghiệm một phần có là nghiệm của bài toán hay không Nếu chỉ cần tìm một nghiệm thì khi gặp nghiệm ta dừng lại Còn nếu cần tìm tất cả các nghiệm thì quá trình chỉ dừng lại khi tất cả các khả năng chọn các thành phần của vectơ nghiệm đã bị vét cạn
L-ợc đồ tổng quát của thuật toán quay lui có thể biểu diễn bởi thủ tục Backtrack sau
Trang 17End;
End;
Thuật toán quay lui có thể đ-ợc biểu diễn bởi thủ tục đệ quy Rbacktrack Đó là thủ tục chọn thành phần thứ i của vectơ nghiệm Trong thủ tục này ta sử dụng phép toán thêm thành phần mới vào vectơ nghiệm (ký hiệu là +) và phép toán loại thành phần cuối cùng khỏi vectơ (ký hiệu là -)
Khi áp dụng l-ợc đồ tổng quát của thuật toán quay lui cho ta các thuật toán
cụ thể, có ba điểm quan trọng cần l-u ý là
Tìm cách biểu diễn nghiệm của bài toán d-ới dạng một dãy các đối t-ợng đ-ợc chọn dần từng b-ớc (x1, x2, ,xi, )
Xác định đ-ợc tập Si các ứng cử viên đ-ợc chọn làm thành phần thứ i của vectơ nghiệm Chọn cách thích hợp để biểu diễn Si
Tìm các điều kiện để một vectơ đã chọn là nghiệm của bài toán
Trang 18Cây không gian trạng thái Việc tìm kiếm vectơ nghiệm (x1, , xi, xi+1, ) bằng ph-ơng pháp quay lui có thể quy về việc tìm kiếm trên cây không gian trạng thái Cây đ-ợc xây dựng theo từng mức nh- sau Các đỉnh con thuộc gốc là các phần tử thuộc S1 Giả sử xi là đỉnh ở mức thứ i Khi đó các đỉnh con của xi là các phần tử thuộc Si+1, trong đó Si+1 là tập các ửng cứ viên của thành phần i+1 của vectơ nghiệm khi ta đã chọn các thành phần x1, , xi ở đây x1, , xi là các đỉnh nằm trên đ-ờng
đi từ gốc tới xi Nh- vậy, mỗi đỉnh của cây không gian trạng thái biểu diễn một nghiệm một phần, đó là vectơ mà các thành phần của nó theo thứ tự là các đỉnh nằm trên đ-ờng đi từ gốc tới đỉnh đó
Việc tìm kiếm nghiệm theo chiến l-ợc quay lui chẳng qua là tìm kiếm theo độ sâu trên cây không gian trạng thái (hay đi qua cây theo preorder)
I.2.4 Ph-ơng pháp nhánh và cận
Ph-ơng pháp nhánh và cận là một dạng cải tiến của ph-ơng pháp quay lui,
đ-ợc áp dụng để tìm nghiệm của bài toán tối -u
Giả sử nghiệm của bài toán có thể biểu diễn d-ới dạng một vectơ (a1, a2, , an), mỗi thành phần ai (i = 1, 2, , n) đ-ợc chọn ra từ tập Si các đối t-ợng nào đó Mỗi nghiệm (a1, , ak) của bài toán đ-ợc gắn với một giá trị cost(a1, , ak) và ta cần tìm nghiệm có giá thấp nhất (nghiệm tối -u)
Giả sử giá của các nghiệm một phần cũng đ-ợc xác định và là các số thực không âm, đồng thời với nghiệm một phần bất kỳ (a1, , ak-1) và nghiệm mở rộng của nó (a1, , ak-1, ak) ta luôn có
cost(a1, , ak-1) cost(a1, , ak-1, ak)
T- t-ởng của ph-ơng pháp nhánh và cận là nh- sau Trong quả trình mở rộng từng b-ớc nghiệm một phần, khi ta đạt đ-ợc nghiệm một phần (a1, , ak), nếu biết rằng tất cả nghiệm mở rộng của nó (a1, , ak, ak+1, ) là mở rộng của nghiệm một phần (a1, ., ak) Gọi giá của nghiệm tốt nhất là lowcost
Trang 19Thực chất của ph-ơng pháp nhánh và cận là tìm kiếm theo độ sâu trên cây không gian trạng thái nh- kỹ thuật quay lui Chỉ có điều khác là khi đạt tới đỉnh ak
mà cost*(a1, , ak-1, ak) lowcost thì ta cắt đi các nhánh từ a1 đi xuống các đỉnh con của nó Tức là, khi đó ta không đi xuống các đỉnh con của ak nữa mà quay lên cha của nó là ak-1
Dùng làm giá trị ban đầu của lowcost ta có thể lấy lowcost = + hoặc lowcost
là giá trị của một nghiệm đ-ợc tìm thấy bằng ph-ơng pháp thực nghiệm nào đó Thuật toán nhánh và cận có thể đ-ợc mô tả bởi thủ tục BanchBound sau
Trang 21Ch-ơng II Ph-ơng pháp quy hoạch động
II.1 Nội dung ph-ơng pháp
Ph-ơng pháp quy hoạch động cùng nguyên lý tối -u đ-ợc nhà toán học Mỹ R.Bellman đề xuất vào những năm 50 của thế kỷ XX Ph-ơng pháp này đ-ợc áp dụng để giải hàng loạt bài toán thực tế trong các quá trình kỹ thuật công nghệ, tổ chức sản xuất, kế hoạch hoá kinh tế Tuy nhiên cần l-u ý rằng có một số bài toán
mà cách giải bằng quy hoạch động tỏ ra không thích hợp
Trong thực tế, ta th-ờng gặp bài toán tối -u loại sau
Có một đại l-ợng f hình thành trong một quá trình gồm nhiều giai đoạn và ta chỉ quan tâm đến kết quả cuối cùng là trị của f phải lớn nhất hoặc nhỏ nhất, ta gọi chung là giá trị của f Giá trị của f phụ thuộc vào những đại l-ợng xuất hiện trong bài toán mà mỗi bộ giá trị của chúng đ-ợc gọi là một trạng thái của hệ thống và cũng phụ thuộc vào cách thức đạt đ-ợc giá trị f, trong từng giai đoạn mà mỗi cách thức đ-ợc gọi là một điều khiển Đại l-ợng f th-ờng đ-ợc gọi là hàm mục tiêu và quá trình đạt đ-ợc giá trị tối -u của f đ-ợc gọi là quá trình điều khiển tối -u
Bellman phát biểu nguyên lý tối -u (Gọi là nguyên lý Bellman) mà ý t-ởng cơ b°n l¯ như sau:‛Với mỗi qu² trình điều khiển tối ưu, đối với tr³ng th²i bắt đầu A0, với mọi trạng thái A trong quá trình đó, phần quá trình kể từ trạng thái A xem nh- tr³ng th²i bắt đầu củng l¯ tối ưu‛ Chũ ý r´ng nguyên lý n¯y chỉ được thụa nhận m¯ không chứng minh
Ph-ơng pháp tìm điều khiển tối -u theo nguyên lý Bellman th-ờng đ-ợc gọi là
Quy hoạch động Thuật ngữ này nói lên thực chất của quá trình điều khiển là động
Có thể trong một số b-ớc đầu tiên lựa chọn điều khiển tối -u d-ờng nh- không tốt nh-ng tựu chung lại là tốt nhất
Ta có thể giải thích ý này qua bài toán sau
Cho một dãy N số nguyên A1, A2, , An Hãy tìm cách xoá đi một số ít nhất số hạng để dãy còn lại là đơn điệu hay nói cách khác hãy chọn một số nhiều nhất các
Trang 22số hạng sao cho dãy B gồm các số hạng đó theo trình tự xuất hiện trong dãy A là
đơn điệu
Quá trình chọn dãy B đ-ợc điều khiển qua N giai đoạn để đạt đ-ợc mục tiêu là
số l-ợng số hạng của dãy B là nhiều nhất, điều khiển của giai đoạn i thể hiện việc chọn hay không chọn Ai vào dãy B hay không
Giả sử dãy đã cho là 1, 8, 10, 2, 4, 6, 7 Nếu ta chọn lần l-ợt 1, 8, 10 thì chỉ chọn
đ-ợc 3 số hạng nh-ng nếu bỏ qua 8 và 10 thì ta chọn đ-ợc năm số hạng 1, 2, 4, 6,
7
Khi gi°i một số b¯i to²n b´ng c²ch ‚Chia - để - trị‛, chuyển việc gi°i b¯i to²n kích th-ớc lớn về việc giải bài toán cùng kiểu có kích th-ớc nhỏ hơn thì các thuật toán này th-ờng đ-ợc thể hiện bằng các ch-ơng trình con đệ quy Khi đó, trên thực
tế nhiều kết quả trung gian phải tính nhiều lần
Vậy ý t-ởng cơ bản của quy hoạch động thật đơn giản: Tránh tính toán lại mọi thứ hai lần, mà l-u giữ kết quả đã tìm kiếm đ-ợc vào một bảng làm giả thiết cho việc tìm kiếm những kết quả của tr-ờng hợp sau Chúng ta sẽ làm đầy dần giá trị của bảng này bỡi các kết quả của những tr-ờng hợp tr-ớc đã đ-ợc giải Kết quả cuối chính là bài toán cần giải Nói cách khác ph-ơng pháp quy hoạch động đã thể hiện sức mạnh của nguyên lý Chia - để - trị đến cao độ
Quy hoạch động là kỹ thuật thiết kế bottom – up (từ d-ới lên) Nó đ-ợc bắt đầu
từ những tr-ờng hợp con nhỏ nhất (th-ờng là đơn giản nhất và giải đ-ợc ngay) Bằng cách tổ hợp các kết quả đã có (không phải tính lại) của các tr-ờng hợp con, sẽ
đạt tới kết quả của tr-ờng hợp có kích th-ớc lớn dần lên và tổng quát hơn, cho đến khi cuối cùng đạt tới lời giải của tr-ờng hợp tổng quát nhất
Trong một số tr-ờng hợp, khi giải một bài toán A, tr-ớc hết ta tìm họ bài toán A(p) phụ thuộc tham số p (có thể p là một véc tơ) mà A(p0) = A với p0 là trạng thái ban đầu của bài toán A Sau đó tìm cách giải họ bài toán A(p) với tham số p bằng cách áp dụng nguyên lý tối -u của Bellman Cuối cùng cho p = p0 sẽ nhận đ-ợc kết quả của bài toán A ban đầu
Trang 23 Về cách xây dựng ph-ơng trình truy toán
Ta chia việc giải bài toán thành n giai đoạn Mỗi giai đoạn i có trạng thái ban
đầu là t(i) và chịu tác động điều khiển d(i) sẽ biến thành trạng thái tiếp theo t(i+1) của giai đoạn i+1 (i = 1, 2, , n-1) Theo nguyên lý tối -u của Bellman thì việc tối -u giai đoạn cuối cùng không làm ảnh h-ởng đến kết quả toàn bài toán Với trạng thái ban đầu là t(n) sau khi làm giai đoạn n tốt nhất ta có trạng thái ban đầu của giai
đoạn ban đầu n-1 là t(n-1) và tác động điều khiển của giai đoạn n-1 là d(n-1), có thể tiếp tục xét đến giai đoạn n-1 Sau khi tối -u giai đoạn n-1 ta lại có t(n-2) và d(n-2)
và lại có thể tiến hành tối -u giai đoạn n-2 cho đến khi các giai đoạn từ n giảm đến
1 đ-ợc tối -u thì coi nh- hoàn thành bài toán Gọi giá trị tối -u của bài toán tính
đến giai đoạn k là Fk, giá trị tối -u của bài toán tính riêng ở giai đoạn k là Gk thì
Fk = Fk-1 + Gk
Hay là
Fk(t(k)) = max Gk(t(k), d(k)) + Fk-1(t(k-1)) (*)
B-ớc 2 Tổ chức dữ liệu và ch-ơng trình
Tổ chức dữ liệu sao cho đạt đ-ợc các yêu cầu sau
a Dữ liệu đ-ợc tính toán dần theo từng b-ớc
b Dữ liệu đ-ợc l-u trữ để giảm l-ợng tính toán lặp lại
Trang 24 d(k)
c Kích th-ớc miền nhớ dùng cho l-u trữ dữ liệu càng nhỏ càng tốt, kiểu dữ liệu
đ-ợc chọn phù hợp, nên chọn đơn giản để dễ truy cập
Dựa vào công thức, ph-ơng trình truy toán (*) và các giá trị đã có trong
bảng để tìm dần các giá trị còn lại của bảng
Ngoài ra còn cần mảng l-u trữ nghiệm t-ơng ứng với giá trị tối -u trong từng giai đoạn
Dựa vào bảng l-u trữ nghiệm và bảng giá trị tối -u từng giai đoạn đã xây dựng, tìm ra kết quả bài toán
Làm tốt thuật toán bằng cách thu gọn hệ thức (*) và giảm kích th-ớc miền nhớ Th-ờng tìm cách dùng mảng một chiều thay cho mảng hai chiều nếu giá trị một dòng (hoặc cột) của mảng hai chiều chỉ phụ thuộc một dòng (hoặc cột) kề tr-ớc Trong một số tr-ờng hợp có thể mảng hai chiều với các giá trị phần tử chỉ nhận giá trị 0, 1 bởi mảng hai chiều mới bằng cách dùng kỹ thuật quản lý bit
II.3 Hạn chế của quy hoạch động
Việc tìm công thức, ph-ơng trình truy toán hoặc tìm cách phân rã bài toán nhiều khi đòi hỏi sự phân tích tổng hợp rất công phu, dễ sai sót, khó nhận ra nh- thể nào là thích hợp, đòi hỏi nhiều thời gian suy nghĩ Đồng thời không phải lúc nào kết hợp lời giải của các bài toán con cũng cho kết quả của bài toán lớn hơn
Khi l-u trữ đòi hỏi mảng hai, ba chiều thì khó có thể xử lý với kích cỡ mỗi
Trang 25chiều lớn hàng trăm
Cho đến nay, vẫn ch-a có ai xác định đ-ợc một cách chính xác những bài toán là
có thể giải quyết đ-ợc một cách hiệu quả bằng ph-ơng pháp quy hoạch động Có những vấn đề quá phức tạp và khó khăn mà xem ra không thể ứng dụng quy hoạch
động để giải quyết đ-ợc, trong khi đó cũng có những bài toán đơn giản khiến cho việc sử dụng quy hoạch động để giải quyết lại kém hiệu quả hơn so với dùng các thuật toán kinh điển
Trang 26Ch-ơng III Một số bài toán điển hình
III.1 Dãy con không giảm dài nhất
Cho số nguyên d-ơng n (0 < n 104
) và một dãy A1, A2, , An các số nguyên Tìm trong dãy đã cho một dãy con Ai1, Ai2, , Aik thoả mãn các điều kiện:
a) Ail < Ail+1; b) ij < ij+1;