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

BÁO CÁO THỰC TẬP-Lập trình quy hoạch động

17 320 0

Đ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 17
Dung lượng 358,31 KB

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

Nội dung

Giới thiệu • Nói chung, ta có thể giải một bài toán với cấu trúc con tối ưu bằng một quy trình ba bước: – Chia bài toán thành các bài toán con nhỏ hơn.. – Giải các bài toán con này một c

Trang 1

Lập trình quy hoạch động

(Dynamic Programming)

Trang 2

Giới thiệu

• Nhà toán học Richard Bellman đã phát minh

phương pháp quy hoạch động vào năm 1953

• Trong ngành khoa học máy tính, quy hoạch

động là một phương pháp giảm thời gian chạy

của các thuật toán thể hiện các tính chất của các bài toán con gối nhau (overlapping

subproblem) và cấu trúc con tối ưu (optimal

substructure)

Trang 3

Giới thiệu

• Cấu trúc con tối ưu có nghĩa là các lời giải tối

ưu cho các bài toán con có thể được sử dụng

để tìm các lời giải tối ưu cho bài toán toàn cục

Trang 4

Giới thiệu

• Nói chung, ta có thể giải một bài toán với cấu trúc con tối ưu bằng một quy trình ba bước:

– Chia bài toán thành các bài toán con nhỏ hơn

– Giải các bài toán con này một cách tối ưu bằng cách sử dụng một cách đệ quy quy trình ba bước này

– Sử dụng các kết quả tối ưu đó để xây dựng một lời giải tối ưu cho bài toán ban đầu

• Như vậy, các bài toán con được giải bằng cách chia chúng thành các bài toán nhỏ hơn, và cứ tiếp tục như thế, cho đến khi ta đến được trường hợp đơn giản để tìm lời giải

Trang 5

Giới thiệu

• Nói rằng một bài toán có các bài toán con

trùng nhau có nghĩa là mỗi bài toán con đó

được sử dụng để giải nhiều bài toán lớn hơn khác nhau

• Ví dụ, trong dãy Fibonacci, F3 = F1 + F2 và F4

= F2 + F3 — khi tính mỗi số đều phải tính F2

Vì tính F5 cần đến cả F3 và F4, một cách tính

F5 một cách đơn giản có thể sẽ phải tính F2 hai lần hoặc nhiều hơn

Trang 6

Giới thiệu

• Điều này xảy ra mỗi khi có mặt các bài toán con gối nhau: do vậy tốn thời gian tính toán lại lời giải tối ưu cho các bài toán con mà nó đã giải

• Để tránh việc đó, ta lưu trữ lời giải của các bài toán con đã giải Do vậy, nếu sau này ta cần giải lại chính bài toán đó, ta có thể lấy và sử dụng kết quả đã được tính toán

Trang 7

Giới thiệu

• Hướng tiếp cận này được gọi là lưu trữ (trong

tiếng Anh được gọi là memoization, không

phải memorization)

• Nếu ta chắc chắn rằng một lời giải nào đó không còn cần thiết nữa, ta có thể xóa nó đi để tiết kiệm không gian bộ nhớ

• Trong một số trường hợp, ta còn có thể tính lời giải cho các bài toán con mà ta biết trước rằng

sẽ cần đến

Trang 8

Giới thiệu

• Tóm lại, quy hoạch động sử dụng:

– Các bài toán con gối nhau

– Cấu trúc con tối ưu

– Lưu trữ

Trang 9

Giới thiệu

• Quy hoạch động thường dùng một trong hai cách tiếp cận:

top-down (từ trên xuống): Bài toán được chia

thành các bài toán con, các bài toán con này được giải và lời giải được ghi nhớ để phòng trường hợp cần dùng lại chúng Đây là đệ quy và lưu trữ được kết hợp với nhau

Trang 10

Giới thiệu

• Quy hoạch động thường dùng một trong hai cách tiếp cận:

bottom-up (từ dưới lên): Tất cả các bài toán con

có thể cần đến đều được giải trước, sau đó được dùng để xây dựng lời giải cho các bài toán lớn hơn Cách tiếp cận này hơi tốt hơn về không gian bộ nhớ dùng cho ngăn xếp và số lời gọi hàm Tuy nhiên, đôi khi việc xác định tất cả các bài toán con cần thiết cho việc giải quyết bài toán cho trước không được trực giác lắm

Trang 11

Dãy Fibonacci

• Một cài đặt đơn giản của một hàm tính phần tử

thứ n của dãy Fibonacci, trực tiếp dựa theo

định nghĩa toán học

function fib(n)

if n = 0 or n = 1

return n

else

Trang 12

Dãy Fibonacci

• Giả sử nếu gọi, chẳng hạn, fib(5), ta sẽ tạo ra một cây các lời gọi hàm, trong đó các hàm của cùng một giá trị được gọi nhiều lần:

– fib(5)

– fib(4) + fib(3)

– (fib(3) + fib(2)) + (fib(2) + fib(1))

– ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) +

fib(0)) + fib(1))

Trang 13

Dãy Fibonacci

– (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) +

((fib(1) + fib(0)) + fib(1))

• Trong minh họa trên, fib(2) được tính hai lần Trong các ví dụ lớn hơn, sẽ có nhiều giá trị của

fib, hay các bài toán con được tính lại, dẫn đến

một thuật toán có thời gian lũy thừa

Trang 14

Dãy Fibonacci

• Giả sử ta có một đối tượng ánh xạ đơn giản, nó ánh xạ mỗi giá trị của fib đã được tính tới kết quả của giá trị đó

• Ta sửa đổi hàm trên như sau để sử dụng và cập nhật ánh xạ trên Hàm thu được chỉ đòi hỏi

thời gian chạy O(n) thay vì thời gian chạy lũy

thừa:

Trang 15

Dãy Fibonacci

var m := map(0 → 1, 1 → 1)

function fib(n)

if n not in keys(m)

m[n] := fib(n − 1) + fib(n − 2)

return m[n]

Trang 16

Dãy Fibonacci

• Nhận xét: Đây là cách tiếp cận từ trên xuống,

do trước hết ta chia bài toán thành các bài toán nhỏ hơn, rồi giải chúng và lưu trữ các kết quả

• Trong trường hợp này, ta cũng có thể giảm từ

chỗ hàm sử dụng không gian tuyến tính (O(n))

xuống chỉ còn sử dụng không gian hằng bằng cách sử dụng cách tiếp cận từ dưới lên Cách này tính các giá trị nhỏ hơn của fib trước, rồi

từ đó xây dựng các giá trị lớn hơn:

Trang 17

Dãy Fibonacci

function fib(n)

var previousFib := 1, currentFib := 1

repeat n − 1 times

var newFib := previousFib + currentFib

previousFib := currentFib

currentFib := newFib

return currentFib

Ngày đăng: 23/05/2015, 17:14

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

w