Lờ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àitoá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ácbà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àogiao 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ôngminh 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ắntắ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ảimộ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 đợcgọ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áclệ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 đợcthuật toán giải quyết mọi vấn đề, nhng các nhà nghiên cứu đã tìm ra một số phơngphá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ạmvi 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ậttoán nh: Chia- để - trị, phơng pháp tham ăn, quay lui, nhánh và cận,
quy 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ếtsức mình Do đó, kết quả đạt đợc là đáng đợc ghi nhận nhng chắc chắn không tránh
Trang 2khỏi những thiếu sót, những vấn đề cha làm đợc không phải là ít Rất mong đợc dạybả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
Tó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ị.
Trang 3I.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ố.
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 4I.2.4 Phơng pháp nhánh và cận 18
III.2 Dãy con chung dài nhất của hai dãy số nguyên 29
III.6 Tìm đờng đi ngắn nhất giữa 2 thành phố 46
Trang 5
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ọcvớ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ạnphé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, nhng cha 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 đathức (Integer Root Problem) đã đợc chứng minh là các bài toán không cóthuật toán giải.
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ểnmạ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ínhnó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 Pcò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
Trang 6niệ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ácxâ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ônngữ, â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ởidã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.
Má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ớidạ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ềucá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ệcxử 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áchtấ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ớcthực hiện các thao tác, ta đạt đợc mục tiêu định trớc.
Các đặc trng 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
Trang 7cù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 đợckế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ộtlớ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ácnhau, 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ậncá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 lấ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 chota một số đại lợng ra tuỳ theo chức năng mà thuật toán đảm nhiệm, chúngthờ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áctiê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 quanniệm rộng rãi hơn về thuật toán Cụ thể là lu ý đế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ínhxá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ớcgiả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ớ Nhng nếu chúngta 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à
Trang 8có 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 outputtheo 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ừ inputcủ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ờngminh 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 thaotá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ựngmộ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ìnhtự 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ó đợctheo hớng nghiên cứu này đã, đang và sẽ vẫn có những vị trí xứng đáng trong toánhọc nói riêng và khoa học nói chung Tuy nhiên, trong khuôn khổ của tin học, khinó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òngtin 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 minhmộ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 quanniệ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àitoá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 9toá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ộtchứ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ánhọ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ậttoán Trong số các định nghĩa toán học khác nhau (nhng 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ãihơ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ìnhtự 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ôngthờ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ọilà 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.
Ví 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 mincủ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 maxbằ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.
Trang 10Cần chú ý rằng mỗi thuật toán chỉ giải một bài toán nào đó nhng 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ọnmột thuật toán tốt để giải bài toán đã cho.
Nhng 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ộtchơ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 Số lợng các tài nguyên cần dùngthể 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ềunhấ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 đợcxem 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ờigian chấp nhận đợc Để đánh giá độ phức tạp của một thuật toán, ta có thể ớc tínhsố 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ếntrong 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ònglặp dễ dàng tính đợc nhng nếu có một chơng trình con đệ quy, việc ớc lợng số thaotá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.
I.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ácbà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ếptụ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ủabà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 chialà 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 ờnghợ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
Trang 11if 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;
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ỏ.
I.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àitoá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ộtnghiệ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ớcbắ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ầntử 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ộngS bằng cách thêm vào phần tử đợc chọn.
X select (A);A A - x;
If S x chấp nhận đợc Then S S x;
Trang 12Trong lợc đồ tổng quát trên, select là hàm chọn, nó cho phép ta chọn ra từ tậpA 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.
Ta 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ạimỗ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àykhô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ántham ă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ộtnghiệ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ữuhạn(x1, x2, , xn) nhng độ dài véc tơ có thể không đợc xác định trớc Vectơ này cầnphả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ànhphầ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ôngnhau, 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ậutừ 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ừngbớ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 con củaAi 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
Trang 13khô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ảikiể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ìmmộ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 Backtracksau.
Procedure Backtrack;Begin
S1 := A1;K := 1;
While k > 0 doBegin
While Sk < > doBegin
Chọn xk Sk;Sk := Sk - xk;
If (x1, , xk) là nghiệm Then viết ra nghiệm;
K := k+1;Xác định Sk;
K := k - 1; quay lui
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éptoá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ànhphần cuối cùng khỏi vectơ (ký hiệu là -)
(a1, a2, ,an) + (b) = (a1, a2, , an, b)(a1, a2, ,an) - (an) = (a1, a2, , an-1)
procedure Rbacktrack(vector, i);begin
xác định Si;
Trang 14for xi Si dobegin
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 lu ý 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ủavectơ 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
Cây không gian trạng thái Việc tìm kiếm vectơ nghiệm (x1, , xi, xi+1, ) bằngphơ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ệmkhi ta đã chọn các thành phần x1, , xi ở đây x1, , xi là các đỉnh nằm trên đờng đitừ 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ệmmộ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)
Trang 15Giả sử giá của các nghiệm một phần cũng đợc xác định và là các số thựckhông âm, đồng thời với nghiệm một phần bất kỳ (a1, , ak-1) và nghiệm mở rộngcủ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ừngbớ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ấtcả 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.
Thự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âykhô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 đỉnhcon 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êncha 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 lowcostlà 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ậttoán nhánh và cận có thể đợc mô tả bởi thủ tục BanchBound sau.
Procedure BanchBound;Begin
Lowcost := ;Cost* := 0;Tinh S1;K :=1;
While k > 0 doBegin
While (Sk < > ) and (cost* < lowcost) doBegin
Chọn ak Sk;Sk := Sk - ak;Cost* := (a1, , ak);
If (a1, , ak) là nghiệm then
If cost(a1, , ak) < lowcost then
Lowcost := cost(a1, , ak);K := k + 1;
Tính Sk;
End;
Trang 16K := k - 1;
Cost* := cost*(a1, ,ak);
Nh vậy, với phơng pháp nhánh và cận, ta không phải duyệt toàn bộ cây khônggian trạng thái để tìm ra nghiệm tốt nhất mà bằng cách đánh giá cận dới cost* củacác nghiệm là mở rộng của nghiệm một phần, ta có thể cắt bỏ đi những nhánhkhông cần thiết, do đó việc tìm ra nghiệm tối u sẽ nhanh hơn Cái khó nhất trongviệc áp dụng phơng pháp nhánh và cận là xây dựng đợc hàm đánh giá cận dớicost* Hàm này có đợc xây dựng tốt thì mới giúp ta cắt bỏ đợc nhiều nhánh khôngcần thiết và thuật toán nhận đợc mới có thể cải tiến đáng kể so với thuật toán vétcạn.
Chơ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ứcsản xuất, kế hoạch hoá kinh tế Tuy nhiên cần lu ý 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.
Trang 17Có 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ọichung 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àitoá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ũngphụ 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ảnlà 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ọitrạ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áibắt đầu cũng là tối u” Chú ý rằng nguyên lý này chỉ đợc thừa nhận mà khôngchứ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à Quyhoạ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 nhng tựuchung 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ácsố 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ọnhay 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 nhng 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ánkí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ánnày thờng đợc thể hiện bằng các chơng trình con đệ quy Khi đó, trên thực tế nhiềukế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ọithứ hai lần, mà lu giữ kết quả đã tìm kiếm đợc vào một bảng làm giả thiết cho việctì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ủabả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
Trang 18Trong 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ủabài toán A ban đầu
II.2 Các b ớc thực hiện quy hoạch động
Bớc 1 Lập hệ thức.
Dựa vào nguyên lý tối u tìm cách chia quá trình giải bài toán tính toán thànhtừng giai đoạn, sau đó tìm hệ thức biểu diễn tơng quan quyết định các bớc đang xửlý trớc đó Hoặc tìm cách phân rã bài toán thành các “bài toán con” tơng tự có kíchthớc nhỏ hơn, tìm hệ thức nêu quan hệ giữa kết quả bài toán kích thớc đã cho vớicác kết quả của các “bài toán con” cùng kiểu có kích thớc nhỏ hơn của nó nhằmxây dựng phơng trình truy toán (dạng hàm hoặc thủ tục đệ quy).
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 ugiai đ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áiban đầ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)) (*).
Trang 19Bớ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 lu trữ để giảm lợng tính toán lặp lại.
c Kích thớc miền nhớ dùng cho lu trữ dữ liệu càng nhỏ càng tốt, kiểu dữ liệu đợcchọn phù hợp, nên chọn đơn giản để dễ truy cập.
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ậngiá 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ánnhiề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 ranh thể nào là thích hợp, đòi hỏi nhiều thời gian suy nghĩ Đồng thời khôngphả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àitoán lớn hơn.
Khi lu trữ đòi hỏi mảng hai, ba chiều thì khó có thể xử lý với kích cỡ mỗi chiều lớn hàng trăm.
Trang 20Cho đến nay, vẫn cha 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 choviệ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ácthuật toán kinh điển.
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.
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;