Tiểu luận về ý tưởng và ứng dụng của Thuật toán Tham lam (GREEDY) trong lập trình. Tài liệu có chứa thuật toán Cây đường đi ngắn nhất DIJKSTRA và giải thuật heuristic. Tiểu luận do nhóm Học sinh chuyên Tin Khóa K26 trường THPT chuyên Thái Nguyên thực hiệnVui lòng tải toàn bộ để nhận được đề bài và TEST của tất cả bài tập trong tiểu luận
Trang 1TRƯỜNG THPT CHUYÊN THÁI NGUYÊN
BÀI TIỂU LUẬN MÔN TIN HỌC
Trang 2LỜI NÓI ĐẦU
Giải thuật cho những bài toán tối ưu thường đi qua một số bước, với một tập hợp các chọn lựa tại mỗi bước Với nhiều bài toán tối ưu hoá có thể sử dụng phương pháp đơn giản và hiệu quả hơn phương pháp qui hoạch động
Tham Lam hiểu một cách dân gian là: trong một mâm có nhiều món ăn, món nào ngon nhất ta sẽ ăn trước và ăn cho hết món đó thì chuyển sang món ngon thứ hai, lại
ăn hết món ngon thứ hai này và chuyển sang món ngon thứ ba… Phương pháp tham lam luôn chọn phương án tốt nhất vào thời điểm hiện tại Nó chọn tối ưu cục bộ với hy vọng rằng lựa chọn này sẽ dẫn đến một kết quả tối ưu toàn cục Phương pháp tham lam không phải lúc nào cũng mang lại các kết quả tối ưu, nhưng có nhiều bài toán nó
có thể giải quyết được một cách tối ưu
Tham lam là một trong những phương pháp phổ biến nhất để thiết kế giải thuật Rất nhiều thuật toán nổi tiếng được thiết kế dựa trên tư tưởng của tham lam, ví dụ như thuật toán tìm đường đi ngắn nhất của Dijkstra, thuật toán cây khung nhỏ nhất của Kruskal, v.v Trong bài tiểu luận này, chúng ta sẽ tìm hiểu phương pháp thiết kế giải thuật này và ứng dụng của nó.
Mặc dù tiểu luận đã tham khảo và chọn lọc khá kỹ về nội dung, tuy nhiên, vì thời gian thực hiện có hạn, đồng thời có nhiều hạn chế về ngôn ngữ, nhóm chúng em không thể tránh khỏi được những sai sót Rất mong được phản hồi từ thầy để chúng
em hoàn chỉnh được bài tiểu luận một cách chính xác nhất.
Thái Nguyên, tháng 12/2015 Nhóm học sinh chuyên Tin K26 thực hiện
Trang 3MỤC LỤC LỜI NÓI ĐẦU _2
1 ĐẶT VẤN ĐỀ _4
2 CƠ SỞ LÝ THUYẾT VÀ BÀI TẬP _4 2.1 KHÁI NIỆM _4 2.2 PHƯƠNG PHÁP CÀI ĐẶT _6 2.3 BÀI TẬP ĐIỂN HÌNH _8
3 ỨNG DỤNG _16 3.1 THUẬT TOÁN DIJKSTRA _16 3.2 THUẬT GIẢI HEURISTIC _20 KẾT LUẬN 25 TÀI LIỆU THAM KHẢO 26
Trang 41 ĐẶT VẤN ĐỀ
Trong mọi khía cạnh của cuộc sống hàng ngày, công việc và nghiên cứu, con người phải luôn đối mặt với các vấn đề (problem) Có ai đó còn phát biểu: sống là một quá trình cố gắng để giải quyết những bài toán, những vấn đề Trong số những vấn đề
đó, có những vấn đề chỉ đơn giản là cần có giải pháp nhưng cũng có những vấn đề khắt khe hơn đòi hỏi không chỉ là giải pháp (Solution) mà giải pháp đó phải là giải pháp tốt nhất (best solution) (nhanh nhất, đơn giản nhất, hiệu quả nhất ) đó được gọi
là những vấn đề cần tối ưu (Optimization Problem)
Ý tưởng Greedy (tham lam) là một trong những hướng suy nghĩ được sử dụng trong tình huống này Các thuật toán sử dụng Greedy như nền tảng logic để tiếp cận, giải quyết vấn đề được gọi là những Greedy Algorithms Các thuật toán ứng dụng Greedy thường diễn ra, hoạt động qua nhiều chặng (phase) về không gian hay thời gian, và tại mỗi chặng chúng ta thường không biết thông tin toàn bộ dữ liệu của cả quátrình mà chỉ biết tình trạng hiện tại và thông tin cho bước đi kế tiếp Ý tưởng chính củaGreedy là chúng ta không cần quan tâm tới dữ liệu tổng thể mà chỉ từ những dữ liệu tạitừng chặng chọn ra giải pháp tối ưu tại mỗi chặng đó với hy vọng là tổng hợp những giải pháp tối ưu cục bộ sẽ mang lại một giải pháp tối ưu cho tổng thể Từ ý tưởng đó cho thấy, kết quả có được từ Greedy Algorithm chỉ mang tính tương đối, thông thườnggiải pháp cuối cùng không phải là tối ưu mà chỉ là gần với tối ưu Tuy nhiên với nhữngđiều kiện, thông tin thường không mấy rỏ ràng của đầu vào, và cách tiếp cận vấn đề khá trong sáng của mình, Greedy thường đưa ra giải pháp tương đối tốt trong giới hạn
Trang 5Lựa chọn giải pháp nào được cho là tốt nhất ở thời điểm hiện tại và sau đó giải bài toán con nảy sinh từ việc thực hiện lựa chọn vừa rồi Lựa chọn của thuật toán thamlam có thể phụ thuộc vào các lựa chọn trước đó Nhưng nó không thể phụ thuộc vào một lựa chọn nào trong tương lai hay phụ thuộc vào lời giải của các bài toán con.Giải thuật tham lam quyết định sớm và thay đổi đường đi thuật toán theo quyết định đó, và không bao giờ xét lại các quyết định cũ để thay đổi, vì vậy có thể là một thuật toán không tối ưu Tuy nhiên, cần nhấn mạnh rằng, trong một số bài toán, nếu xây dựng được hàm xác định sự tốt nhất của những lựa chọn thích hợp thì có thể cho
ra nghiệm tối ưu Dĩ nhiên, ta phải chứng minh rằng một lựa chọn tham lam tại mỗi bước đưa ra một giải pháp tối ưu toàn cục, và đây là nơi cần có sự thông minh Trong nhiều bài toán khác, thuật toán này chỉ tìm ra nghiệm gần đúng với nghiệm tối ưu
VD: Với mục tiêu đạt được tổng lớn nhất dưới đây, tại mỗi bước, thuật toán thamlam sẽ chỉ tối ưu trước mắt là chọn đường đi có số lớn hơn, nên sẽ chọn số 3 thay vì số
12 Khiến cho kết quả không phải là giải pháp tốt nhất, có chứa số 99
Nói chung, giải thuật tham lam có năm thành phần:
1. Một tập hợp các ứng viên (candidate), để từ đó tạo ra lời giải
2. Một hàm lựa chọn, để theo đó lựa chọn ứng viên tốt nhất để bổ sung vào lờigiải
3. Một hàm khả thi (feasibility), dùng để quyết định nếu một ứng viên có thể được dùng để xây dựng lời giải
4. Một hàm mục tiêu, ấn định giá trị của lời giải hoặc một lời giải chưa hoàn chỉnh
5. Một hàm đánh giá, chỉ ra khi nào ta tìm ra một lời giải hoàn chỉnh
Trang 6Có hai thành phần quyết định nhất tới quyết định tham lam:
Tính chất lựa chọn tham lam
Chúng ta có thể lựa chọn giải pháp nào được cho là tốt nhất ở thời điểm hiện tại
và sau đó giải bài toán con nảy sinh từ việc thực hiện lựa chọn vừa rồi Lựa chọn của thuật toán tham lam có thể phụ thuộc vào các lựa chọn trước đó Nhưng nó không thể phụ thuộc vào một lựa chọn nào trong tương lai hay phụ thuộc vào lời giải của các bài toán con Thuật toán tiến triển theo kiểu thực hiện các chọn lựa theo một vòng lặp, cùng lúc đó thu nhỏ bài toán đã cho về một bài toán con nhỏ hơn Đấy là khác biệt giữa thuật toán này và giải thuật Quy Hoạnh Động Giải thuật quy hoạch động duyệt hết và luôn đảm bảo tìm thấy lời giải Tại mỗi bước của thuật toán, quy hoạch động đưa ra quyết định dựa trên các quyết định của bước trước, và có thể xét lại đường đi của bước trước hướng tới lời giải Giải thuật tham lam quyết định sớm và thay đổi đường đi thuật toán theo quyết định đó, và không bao giờ xét lại các quyết định cũ Đối với một số bài toán, đây có thể là một thuật toán không chính xác
Cấu trúc con tối ưu
Một bài toán có cấu trúc con tối ưu nếu giải pháp tối ưu cho bài toán này chứa trong nócác giải pháp tối ưu cho các bài toán con Thuộc tính này là điểm để quyết định ta có thể giải quyết bài toán bằng phương pháp tham lam được hay không
2.2 Phương pháp cài đặt:
Điều kiện để bài toán có thể giải bằng phương phám Tham lam đó là chúng thuộc lớp các bài toán tối ưu tổ hợp là một trường hợp riêng của bài toán tối ưu
Các bài toán tối ưu là các bài toán có dạng tổng quát như sau:
Hàm f(X) được gọi là hàm mục tiêu , xác định trên một tập hữu hạn các phần tử D
Mỗi phần tử X thuộc D có dạng X=(x1,x2,….,xn) được gọi là một phương
Trang 7Ví dụ như các dạng bài toán sau:
Một tập các đối tượng
Một dãy các đối tượng đã lựa chọn
Một hàm để xem một tập các đối tượng có lập thành một giải pháp hay không (không nhất thiết tối ưu)
Một hàm để xem một tập đối tượng có là tiềm năng hay không
Một hàm để lựa chọn ứng viên có triển vọng nhất
Một hàm đích cho một giá trị của một giải pháp (để tối ưu hóa)
Giả sử nghiệm của bài toán có thể biểu diễn dưới dạng một vector (x 1 , x 2 , , x n),
mỗi thành phần x i (i=1,2, ,n) được chọn ra từ tập S i Mỗi nghiệm của bài toán X=(x 1 ,
x 2 , , x n ), được xác định " độ tốt" bằng một hàm ƒ(X) và mục tiêu cần tìm nghiệm có giá trị ƒ(X) càng lớn càng tốt (hoặc càng nhỏ càng tốt).
Tư tưởng của phương pháp tham lam như sau: Ta xây dựng vector nghiệm X dần
từng bước, bắt đầu từ vector không ( ) Giả sử đã xây dựng được (k-1) thành phần (x 1 ,
x 2 , , x k-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 Sk để được (x 1 , x 2 , , x k) Việc lựa chọn như vậy được thực hiện bởi một hàm chọn Cứ tiếp tục như vậy cho đến khi xây dưng xong hết tất cả các thành phần của nghiệm
Lược đồ tổng quát của phương pháp tham ăn:
Trong lược đồ tổng quát trên, Select là hàm chọn, để chọn ra từ tập các ứng cử viên Si
một ứng cử viên được xem là tốt nhất, nhiều hứa hẹn nhất
Trang 82.3 Bài tập điển hình:
Bài toán: Cho n thành phố được đánh số từ 1 đến n và các tuyến đường giao thông hai
chiều giữa chúng, mạng lưới 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ại mỗi thành phố đúng 1 lần và cuối cùng quay lại thành phố 1 Hãy chỉ racho người đó hành trình với chi phí ít nhất Bài toán được gọi là bài toán người
du lịch hay bài toán người chào hàng (Travelling Salesman Problem - TSP)
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
Output: file “TSP.OUT” có dạng:
Trang 9Hướng dẫn: Có nhiều thuật toán tham lam cho bài này, một thuật toán với ý tưởng
đơn giản như sau: Xuất phát từ thành phố 1, tại mỗi bước ta sẽ chọn thành phố tiếptheo là thành phố chưa đến thăm mà chi phí từ thành phố hiện tại đến thành phố đó lànhỏ nhất, cụ thể:
+ Hành trình cần tìm có dạng (x1 = 1, x2, , xn, xn+1 = 1), trong đó dãy (x1,
x2, , xn) lập thành một hoán vị của (1, 2, , n)
+ Ta xây dựng nghiệm từng bước, bắt đầu từ x1=1, chọn x2 là thành phố gần
x1 nhất, sau đó chọn x3 là thành phố gần x2 nhất (x3 khác x1) Tổng quát: chọn xi là thành phố chưa đi qua mà gần xi-1 nhất.(2 i n)
Trang 10 TEST 1: Xuất phát từ thành phố 1, phương pháp tham lam xây dựng
được hành trình 1 → 2 → 4 → 3→ 1 với chi phí 97, đây là phương án tối ưu
TEST 2: Xuất phát từ thành phố 1, phương pháp tham lam xây dựng
được hành trình 1 → 4 → 3 → 2→ 1 với chi phí 132, nhưng kết quả tối
ưu là 117
Trang 11 Bài toán máy rút tiền tự động ATM
Bài toán: 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.
Input: từ file “ATM.INP” có dạng:
-Dòng đầu là 2 số n và s
-Dòng thứ 2 gồm n số t1,t2, ,tn
Output: 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
TEST
10 390
200 10 20 20 50 50 50 50 100 100 520 20 50 100 200
Hướng dẫn: Thuật toán với ý tưởng tham lam đơn giản, hàm chọn như sau: Tại mỗi
bước ta sẽ chọn tờ tiền lớn nhất còn lại không vượt quá lượng tiền còn phải trả, cụ thể:
+ Sắp xếp các tờ tiền giảm dần theo giá trị
+ Lần lượt xét các tờ tiền từ giá trị lớn đến giá trị nhỏ, nếu vẫn còn chưa lấy
đủ s và tờ tiền đang xét có giá trị nhỏ hơn hoặc bằng s thì lấy luôn tờ tiền đó
Code:
const MAX = 100;
fi =’ATM.INP’;
fo =’ATM.OUT’;
type vector =array[1 MAX]of longint;
var t :array[1 MAX]of longint;
assign(f,fi); reset(f); readln(f,n, s);
for i:=1 to n do read(f,t[i]);
close(f);
Trang 13Nhận xét: Khi dùng phương phám tham lam với các TEST thử nghiệm như sau:
TEST 1: Thuật toán tham lam cho ra kết quả tối ưu
TEST 2: Thuật toán tham lam không cho nghiệm tối ưu
TEST 3: Thuật toán tham lam không tìm ra nghiệm mặc dù có nghiệm
Bài toán: Có n công việc đánh số từ 1 đến n và có một máy để thực hiện, biết:
- p i là thời gian cần thiết để hoàn thành công việc i.
- d i là thời hạn hoàn thành công việc i.
Máy bắt đầu hoạt động từ thời điểm 0 Mỗi công việc cần được thực hiện liên tục từ
lúc bắt đầu cho tới khi kết thúc, không được phép ngắt quãng Giả sử c i là thời điểm
hoàn thành công việc i Khi đó, nếu c i > d i ta nói công việc i bị hoàn thành trễ hạn, còn nếu c i > d i thì ta nói công việc i được hoàn thành đúng hạn.
Yêu cầu: Tìm trình tự thực hiện các công việc sao cho số công việc hoàn thành trễ hạn là ít nhất (hay số công việc hoàn thành đúng hạn là nhiều nhất)
Input: trong file “JS.INP” có dạng:
- Dòng đầu là số n (n < 100) là số công việc
- Dòng thứ hai gồm n số là thời gian thực hiện các công việc
- Dòng thứ ba gồm n số là thời hạn hoàn thành các công việc
Output: file “JS.OUT” có dạng: gồm một dòng là trình tự thực hiện các công việc.
Trang 14Hướng dẫn: Ta sẽ chỉ quan tâm đến việc xếp lịch cho các công việc hoàn thành đúng hạn, còn các công việc bị trễ hạn có thể thực hiện theo trình tự bất kỳ.
+ Giả sử ]s là tập gồm k công việc (mà cả k công việc này đều có thể thực hiện đúng hạn) và σ = ( i 1 , i 2 , , i k ) là một hoán vị của các công việc trong Js sao cho thì thứ tự ơ là thứ tự để hoàn thành đúng
hạn được cả k công việc
Ví dụ: J s gồm 4 công việc 1, 3, 4, 5 (4 công việc này đều có thể thực hiện đúng
hạn), ta có thứ tự thực hiện σ = (5,1, 3,4) vì d5 = 3 ≤ d 1 = 8 ≤ d3 = 15 ≤ d4 = 20
để cả 4 công việc đều thực hiện đúng hạn
Sử dụng chiến lược tham ăn, ta xây dựng tập công việc J s theo từng bước, ban đầu J s = Hàm chọn được xây dựng như sau: tại mỗi bước ta sẽ chọn công
việc ]ob i mà có thời gian thực hiện nhỏ nhất trong số các công việc còn lại cho
vào tập Js Nếu sau khi kết nạp ]ob i, các công được đánh số theo thứ tự thời gian
thực hiện tăng dần p 1 ≤ p 2 ≤ ≤ p n Ta có lược đồ thuật toán tham ăn như sau:
TArrJobs =array[1 MAX]of TJob;
var jobs,Js :TArrJobs;
d i
21
Trang 15var f :text;
i :longint;
begin
assign(f,fi); reset(f); readln(f,n);
for i:=1 to n do read(f,jobs[i].p);
for i:=1 to n do read(f,jobs[i].d);
for i:=1 to nJob-1 do
for j:=i+1 to nJob do
if Js[i].d>Js[j].d then swap(Js[i],Js[j]); t:=0;
for i:=1 to nJob do begin
if t+Js[i].p>Js[i].d then exit(false);
Trang 163.1 Thuật toán Dijkstra (Thuật toán tìm đường đi ngắn nhất trên đồ thị)
Thuật toán Dijkstra, mang tên của nhà khoa học máy tính người Hà Lan EdsgerDijkstra vào năm 1956 và ấn bản năm 1959, là một thuật toán giải quyết bài toánđường đi ngắn nhất nguồn đơn trong một đồ thị có hướng không có cạnh mangtrọng số âm Thuật toán thường được sử dụng trong định tuyến với một chươngtrình con trong các thuật toán đồ thị hay trong công nghệ Hệ thống định vị toàncầu (GPS)
Bài toán: Cho đồ thị G = (V, E), mỗi cạnh của đồ thị được gán tương ứng cho một sốkhông âm gọi là trọng số của cạnh Độ dài đường đi được tính bằng tổng trọng
số của các cạnh đi qua Hãy tìm một đường đi ngẳn nhất từ đỉnh xuất phát sVđến đình f V
Input: trong file “MINPATH.INP” có dạng:
- Dòng đầu là số đỉnh n (n<1000), số cung m, đỉnh xuất phát s, đình đích f cánh nhau ít nhất một dấu cách
- m dòng tiếp theo, mỗi dòng chứa 3 số u, v, C[u,v] (C[u,v]<=1000) cách nhau ít nhất một dấu cách, thể hiện trọng số của cung (u,v)
Output: file “MINPATH.OUT” có dạng:
- Dòng đầu là độ dài đường đi ngắn nhất từ đỉnh s đến đỉnh f
- Dòng thứ hai chứa đường đi ngắn nhất từ đỉnh s đến đỉnh f
Trang 17TESTMINPATH.INP MINPATH.OUT
Hướng dẫn: Thuật toán Dijkstra được miêu tả như sau:
Bước 1: Khởi tạo
Với đình vV, gọi nhãn d[v] lả độ dài đường đi ngắn nhất từ s tới v Ban đầu khởi gán d[s] = 0 và d[v] = ∞ với v ≠ s Nhãn của mỗi đỉnh có hai trạng thái tự
do hay cố định, nhãn tự do có nghĩa là có thể còn tối ưu hơn được nữa và nhãn cốđịnh tức là d[v] đã bằng độ dài đường đi ngắn nhất từ s tới v nên không thể tối ưu thêm Để làm điều này ta có thể sử dụng kỹ thuật đánh dấu: Free[v] = TRUE hay FALSE tuỳ theo d[v] tự do hay cố định Ban đầu các nhãn đều tự do
Bước 2: Lặp
Bước lặp gồm có hai thao tác:
+ Cố định nhãn: Chọn trong các đỉnh có nhãn tự do, lấy ra đỉnh u lả đỉnh cód[u] nhỏ nhất, và cố định nhãn đỉnh u
+ Sữa nhãn: Dùng đỉnh u, xét tất cả những đỉnh v và sửa lại các d[v] theo công thức: d[v] := min (d[v], d[u]+c[u,v])
Bước lặp sẽ kết thúc khi mà đỉnh đích f được cố định nhãn (tìm được đường đi ngẳn nhất từ s tới f); hoặc tại thao tác cố định nhãn, tất cả các đỉnh tự do đều có nhãn là ∞ (không tồn tại đường đi)
Có thể đặt câu hỏi, ở thao tác 1, tại sao đỉnh u như vậy được cố định nhãn, giả sử d[u] còn có thể tối ưu thêm được nữa thì tất phải có một đỉnh t mang nhãn tự do sao cho d[u] > d[t] + c[t, u] Do trọng số c[t, u] không âm nên d[u] > d[t], trái với cách chọn d[u] là nhò nhất Tất nhiên trong lần lặp đầu tiên thì s là đỉnh được cố định nhãn do d[s] = 0