1. Trang chủ
  2. » Luận Văn - Báo Cáo

PHƯƠNG PHÁP QUY HOẠCH ĐỘNG

21 557 1

Đ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 21
Dung lượng 542 KB

Nội dung

PHƯƠNG PHÁP QUY HOẠCH ĐỘNG Đặng Tuấn Thành – THPT Chuyên Nguyễn Tất Thành, tỉnh Yên BáiTư tưởng cơ bản của phương pháp quy hoạch động là sử dụng bảng để lưu trữ lờigiải của các bài toán

Trang 1

PHƯƠNG PHÁP QUY HOẠCH ĐỘNG (Đặng Tuấn Thành – THPT Chuyên Nguyễn Tất Thành, tỉnh Yên Bái)

Tư tưởng cơ bản của phương pháp quy hoạch động là sử dụng bảng để lưu trữ lờigiải của các bài toán con đã được giải Khi giải bài toán con cần đến nghiệm của các bàitoán con cỡ nhỏ hơn, ta chỉ cần lấy lời giải trong bảng mà không cần phải giải lại Chính

vì thế mà các thuật toán được thiết kế bằng phương pháp quy hoạch động sẽ rất hiệuquả

Để giải quyết một bài toán bằng phương pháp quy hoạch động, chúng ta cần tiếnhành những công việc sau:

1) Tìm các tham số mô tả bài toán;

2) Tìm nghiệm của các bài toán con nhỏ nhất;

3) Tìm công thức (hoặc quy tắc) xây dựng nghiệm của bài toán con thông quanghiệm của bài toán con cỡ nhỏ hơn;

4) Tạo bảng (dựa trên các tham số mô tả bài toán) để lưu trữ nghiệm của các bàitoán con Tính nghiệm của các bài toán con theo công thức đã tìm và lưu trữvào bảng;

5) Từ các bài toán con đã giải để tìm nghiệm của bài toán

1 Lớp các bài toán giải được bằng phương pháp quy hoạch động

 Bài toán tối ưu

 Bottom-up (từ dưới lên)

o Khi đã xác định được thứ tự các bài toán con cần giải

o Cài đặt bằng vòng lặp

o Có thể giải thừa các bài toán con không cần thiết

 Top-down (từ trên xuống)

o Không cần thiết xác định được thứ tự các bài toán con cần giải

o Cài đặt bằng đệ quy có nhớ  có thể đặt cận

o Chỉ giải các bài toán con cần thiết

Độ phức tạp của thuật toán thiết kế theo phương pháp quy hoạch động

Giả sử bài toán được mô tả bằng các tham số và cần tính hàm mục tiêu Khi đó, số bài toán con (hay còn gọi là số trạng thái) cần tính là

Trang 2

Gọi là độ phức tạp tính nghiệm của bài toán con thông qua nghiệm của bài toáncon cỡ nhỏ hơn (còn gọi là chi phí chuyển trạng thái).

Khi đó độ phức tạp của thuật toán bằng: Số trạng thái chi phí chuyển trạng thái

3 Những vấn đề cần chú ý khi giải bài toán bằng phương pháp quy hoạch động

1 Tìm các tham số mô tả bài toán

Việc tìm các tham số mô tả bài toán được dựa trên các đặc điểm, tính chất của bàitoán (công việc này còn được gọi là đoán nhận trạng thái) Cụ thể, cần xác định cónhững tham số nào, ý nghĩa mỗi tham số, miền giá trị của từng tham số Đây là côngviệc quan trọng mang ý nghĩa quyết định đến việc giải quyết bài toán

2 Tối ưu thuật toán

Qua cách tính độ phức tạp thuật toán theo phương pháp quy hoạch động (độ phứctạp bằng số trạng thái nhân với chi phí chuyển trạng thái) ta nhận thấy, để giảm độ phứctạp thuật toán có thể giảm thiểu số trạng thái hoặc giảm chi phí chuyển trạng thái

3 Một số ví dụ minh hoạ

Bài toán 1: Bài toán cái túi

Trong siêu thị có n gói hàng (n ≤ 100), gói hàng thứ i có trọng lượng là W[i] ≤

100 và trị giá V[i] ≤ 100 Một tên trộm đột nhập vào siêu thị, tên trộm mang theo mộtcái túi có thể mang được tối đa trọng lượng M (M ≤ 100) Hỏi tên trộm sẽ lấy đi nhữnggói hàng nào để được tổng giá trị lớn nhất

Input: file văn bản BAG.INP

- Dòng 1: Chứa hai số n, M cách nhau ít nhất một dấu cách

- n dòng tiếp theo, dòng thứ i chứa hai số nguyên dương W[i], V[i] cách nhau ítnhất một dấu cách

Output: file văn bản BAG.OUT

- Dòng 1: Ghi giá trị lớn nhất tên trộm có thể lấy

- Dòng 2: Ghi chỉ số những gói bị lấy

Trang 3

Bài giải:

Nếu gọi F[i, j] là giá trị lớn nhất có thể có bằng cách chọn trong các gói {1, 2, …,i} với giới hạn trọng lượng j Thì giá trị lớn nhất khi được chọn trong số n gói với giớihạn trọng lượng M chính là F[n, M]

Công thức truy hồi tính F[i, j]

Với giới hạn trọng lượng j, việc chọn tối ưu trong số các gói {1, 2, …, i - 1, i} để

có giá trị lớn nhất sẽ có hai khả năng:

o Nếu không chọn gói thứ i thì F[i, j] là giá trị lớn nhất có thể bằng cách chọn trong

số các gói {1, 2, …, i - 1} với giới hạn trọng lượng là j Tức là F[i, j] = F[i - 1, j]

o Nếu có chọn gói thứ i (tất nhiên chỉ xét tới trường hợp này khi mà W[i] ≤ j) thìF[i, j] bằng giá trị gói thứ i là V[i] cộng với giá trị lớn nhất có thể có được bằng cáchchọn trong số các gói {1, 2, …, i - 1} với giới hạn trọng lượng j - W[i] Tức là về mặtgiá trị thu được: F[i, j] = V[i] + F[i - 1, j - W[i]] Vì theo cách xây dựng F[i, j] là giá trịlớn nhất có thể, nên F[i, j] sẽ là max trong 2 giá trị thu được ở trên

Cơ sở quy hoạch động:

Dễ thấy F[0, j] = giá trị lớn nhất có thể bằng cách chọn trong số 0 gói = 0

1, M] thì tức là không chọn gói thứ n, ta truy tiếp F[n 1, M] Còn nếu F[n, M] ≠ F[n

1, M] thì ta thông báo rằng phép chọn tối ưu có chọn gói thứ n và truy tiếp F[n 1, M W[n]] Cứ tiếp tục cho tới khi truy lên tới hàng 0 của bảng phương án

Trang 4

Assign(fi, InputFile); Reset(fi); ReadLn(fi, n, M);

for i := 1 to n do ReadLn(fi, W[i], V[i]);

if (j >= W[i]) and (F[i, j] < F[i - 1, j - W[i]] + V[i]) then

F[i, j] := F[i - 1, j - W[i]] + V[i];

Trang 5

Bài toán 2: 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 Cho dãy s tạo bởi n kí tự gồm các chữ cái hoa và thường phân biệt vàcác chữ số 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 Giả thiết rằng sau khi xoá bớt một số kí tự từ s thì các kí tự còn lại sẽ tự độngxích lại sát nhau

Dữ liệu vào ghi trong tệp văn bản PALIN.INP với cấu trúc như sau:

 Dòng đầu tiên là giá trị n, 1  n  1000

 Dòng thứ hai là n kí tự của dãy viết liền nhau

Kết quả ghi trong tệp văn bản PALIN.OUT: số lượng kí tự cần xóa.

PALIN.INP PALIN.OUT9

Trang 6

Dĩ nhiên là có nhiều cách xoá Thí dụ, có thể xoá các kí tự thứ 2, 3, 4 và 6 từ dãy s đểthu được dãy con đối xứng khác là bdadb với cùng chiều dài 5:

baeadbadb  bdadb

Tuy nhiên đáp số là số ít nhất các kí tự cần loại bỏ khỏi s thì là duy nhất và bằng 4 Bài giải

Với một nhận xét nhỏ ta có thể phát hiện ra rằng chỉ cần dùng một mảng mộtchiều kích thước n và một vài biến đơn là đủ

Gọi dãy dữ liệu vào là s Ta tìm chiều dài của dãy con đối xứng v dài nhất trích từ

s Khi đó số kí tự cần xoá từ s sẽ là t = length(s) - length(v) Dãy con ở đây được hiểu làdãy thu được từ s bằng cách xoá đi một số phần tử trong s Thí dụ với dãy

s = baeadbadb thì dãy con đối xứng dài nhất của s sẽ là baeab hoặc bdadb,… Các dãynày đều có chiều dài 5

Lập hệ thức: Gọi p(i, j) là chiều dài của dãy con dài nhất thu được khi giải bàitoán với dữ liệu vào là đoạn s[i j] Khi đó p(1, n) là chiều dài của dãy con đối xứng dàinhất trong 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-p(1,n)

Đó chính là đáp số của bài toán

Ta liệt kê một số tính chất quan trọng của hàm hai biến p(i, j) Ta có:

- 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 p(i, j) = 0

- Nếu i = j thì p(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] thì p(i, j) = p(i + 1, j – 1) + 2 Vì hai kí tự đầu và cuối dãy s[i,j]giống nhau nên chỉ cần xác định chiều dài của dãy con đối xứng dài nhất trong đoạngiữa là s[i + 1, j – 1] rồi cộng thêm 2 đơn vị ứng với hai kí tự đầu và cuối dãy làđược

- 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ì

ta khả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 đốixứng dài nhất trong hai dãy này làm kết quả:

p(i,j) = max(p(i,j-1),p(i+1,j))

Vấn đề đặt ra là cần tính p(1, n) Mà muốn tính được p(1, n) ta phải tính được cácp(i, j) với mọi i, j = 1 n

Trang 7

Gọi đệ quy sẽ phát sinh các lời gọi hàm trùng lặp Khắc phục điều này bằng cách

sử dụng một mảng hai chiều để tính trước các giá trị của hàm p(i, j), mỗi giá trị đượctính tối đa một lần Nếu dùng một mảng hai chiều, thí dụ mảng p[0 n, 0 n] thì giá trịcủa p[i, j] sẽ được điền lần lượt theo từng cột, từ cột thứ 1 đến cột thứ n Tại mỗi cột tađiền từ dưới lên trên Ta lưu ý:

- Phần tử tại cột i, dòng j là giá trị p[i, j] chính là chiều dài của dãy con đối xứng dàinhất khi khảo sát dãy con s[i j]

- Với các trị i > j, ta quy định p[i, j] = 0 Như vậy nửa tam giác dưới của ma trận p

if s[i] = s[j] then p[i,j] = p[i+1,j-1]+2

else p[i,j] := max(p[i,j-1],p[i+1,j]);

Trang 8

Ta thực hiện điền một vài giá trị cho bảng trên để rút ra quy luật

Hãy bắt đầu với cột 1: p[1, 1] = 0;

sử dụng các phần tử này như những lính canh chứa các giá trị khởi đầu phục vụ cho cáctrường hợp chỉ số i, j nhận các giá trị 0 hoặc n + 1

Giả sử mảng v chứa các giá trị đã điền của cột j – 1 trong mảng hai chiều p Ta sẽđiền các giá trị cho cột j của mảng p vào mảng một chiều d Như vậy, tại bước j, phần tửv[i] sẽ ứng với phần tử p[j – 1, i] còn phần tử d[i] sẽ ứng với p[j, i] Thủ tục điền trị chocột d tại bước j dựa theo kết quả lưu trong cột v của bước j – 1 khi đó sẽ như sau:

for i := j-1 downto 1 do

begin

if s[i] = s[j] then d[i] := v[i+1]+2

else d[i] := max(v[i],d[i+1]);

Trang 9

for j := 1 to n do

begind[j] := 1;

for i := j-1 downto 1 dobegin

if s[i]= s[j] then d[i] := v[i+1]+2else d[i] := max(v[i],d[i+1]);

Bài toán 3: Chia thưởng

Cần chia hết m phần thưởng cho n học sinh sắp theo thứ tự từ giỏi trở xuống sao chomỗi bạn không nhận ít phần thưởng hơn bạn xếp sau mình

Trang 10

Gọi Chia(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 (Chia = 0)

 Nếu không có phần thưởng nào (i = 0) thì chỉ có một cách chia (Chia(0,j) = 1 mỗi học sinh nhận 0 phần thưởng) Ta cũng quy ước Chia(0, 0) = 1

- 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: Chia(i, j) = Chia(i,i) nếu i < j

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 chiathà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ảngthà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ậnthưởng, tức là i phần thưởng chỉ chia cho j - 1 học sinh và do đó, số cách chia, tức là sốphần tử của nhóm này sẽ là: Chia(i, j - 1)

- Nhóm thứ hai gồm các phương án trong đó học sinh thứ j cũng được nhậnthưởng Khi đó, do học sinh đứng cuối bảng thành tích được nhận thưởng thì mọi họcsinh 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ộtphầ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à Chia(i - j, j)

Tổng số cách chia cho trường hợp i  j sẽ là tổng số phần tử của hai nhóm, ta có:

Chia(i, j) = Chia(i, j - 1) + Chia(i - j, j)

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

Điều kiệni: số phần thưởngj: số học sinh

Chia(i, j)

i = 0 and j  0 Chia(i, j) = 1

i < j Chia(i, j) = Chia(i, i)

Trang 11

i  j Chia(i, j) = Chia(i, j – 1) + Chia(i – j, j)Các tính chất của hàm Chia(i, j)

Chia i phần thưởng cho j học sinhBước 2: Tổ chức dữ liệu và chương trình

Ta có phương án đầu tiên của giải thuật Chia như sau:

Phương án đệ quy Hàm Chia(i,j) tính số cách chia i phần thưởng cho j học sinhfunction Chia(i,j: integer):longint;

if i < j then {0 < i < j } Chia := Chia(i,i) else {i >= j > 0 }

Chia := Chia(i,j-1)+Chia(i-j,j);

end;

Phương án này chạy chậm vì phát sinh ra quá nhiều

lần gọi hàm trùng lặp Bảng dưới đây liệt kê số lần gọi

hàm Chia khi giải bài toán chia thưởng với bảy phần

thưởng (m = 7) và 4 học sinh (n = 4) Thí dụ, hàm

Chia(1,1) sẽ được gọi 9 lần,… Tổng số lần gọi hàm Chia

là 79 79 lần gọi hàm để sinh ra kết quả 11 là quá tốn

kém

Bước 3: Làm tốt

Phương án 1 khá dễ triển khai nhưng chương trình sẽ

chạy rất lâu Diễn tả đệ quy thường trong sáng, nhàn tản,

nhưng khi thực hiện sẽ sinh ra hiện tượng gọi lặp lại những

hàm đệ quy Cải tiến là tránh những lần gọi lặp như vậy

Muốn thế chúng ta tính sẵn các giá trị của hàm theo các trị

của đầu vào khác nhau và điền vào một mảng hai chiều cc

Trang 12

Mảng cc được mô tả như sau:

Const MN = 70;{ gioi han tren cua m va n }

var cc: array[0 MN,0 MN] of longint;

Ta quy ước cc[i, j] chứa số cách chia i phần thưởng cho j học sinh

Theo phân tích của phương án 1, ta có:

 cc[0, 0] = 1; cc[i, 0] = 0, với i:=1 m

 cc[i, j] = cc[i, i], nếu i < j

 cc[i, j] = cc[i, j-1]+cc[i-j, j], nếu i  j

Từ đó ta suy ra quy trình điền trị vào bảng cc như sau:

 Khởi trị

 cc[0,0 ]:= 1;

 với i := 1 m: cc[i,0] := 0;

 Điền bảng: Lần lượt điền theo từng cột j:= 1 n Tại mỗi cột j ta đặt:

 với i := 0 j-1: cc[i,j] := cc[i,i];

 với i := j m: cc[i,j] := cc[i,j-1]+cc[i-j,j];

Nhận kết quả: Sau khi điền bảng, giá trị cc[m, n] chính là kết quả cần tìm.Phương án dùng mảng 2 chiều:

function Chia2(m,n: integer):longint;

var i,j: integer;

Trang 13

for i := 0 to j-1 do cc[i,j] := cc[i,i];

for i := j to m do cc[i,j] := cc[i,j-1]+cc[i-j,j];

end;

Chia2 := cc[m,n];

end;

Bài toán 4 Bảng số (VOIR2_2012)

Giả sử A là lưới ô vuông gồm m dòng và n cột Các dòng của lưới được đánh số

từ 1 đến m, từ trên xuống dưới Các cột của lưới được đánh số từ 1 đến n, từ trái sangphải Ô nằm trên giao của dòng i và cột j của lưới gọi là ô (i, j)

Với số nguyên dương x, gọi f(x) là số lượng số nguyên dương không vượt quá x

mà trong biểu diễn nhị phân có hai bít 1 đứng cạnh nhau Ví dụ, f(5)=1 vì trong các sốnguyên dương bé hơn hoặc bằng 5 chỉ có số 3 có biểu diễn nhị phân với hai bít 1 đứngcạnh nhau

Cho dãy số nguyên dương gồm mn số b1, b2, , bmn Ta sẽ lần lượt điền các sốhạng của dãy

f(b1) mod 3, f(b2) mod 3, , f(bmn) mod 3 vào các ô của lưới A theo thứ tự từ trên xuống dưới từ trái qua phải Gọi bảng sốthu được là B

Xét truy vấn sau đây đối với bảng số thu được B: Cho hai số nguyên p và q (1 ≤ p

≤ q ≤ m), hãy cho biết diện tích lớn nhất của hình chữ nhật gồm các ô nằm trong phạm

vi từ dòng thứ p đến dòng thứ q của bảng B mà trong đó chênh lệch giữa phần tử lớnnhất và phần tử nhỏ nhất không vượt quá 1

Yêu cầu: Cho m, n, dãy số b1, b2, , bmn và k bộ pi, qi (i = 1, 2, , k) tương ứng với ktruy vấn, hãy đưa ra các câu trả lời cho k truy vấn

Dữ liệu: Vào từ file văn bản NUMTAB.INP trong đó:

 Dòng đầu tiên chứa hai số nguyên m, n (1 ≤ m, n ≤ 1000);

 Dòng tiếp theo chứa dãy số b1, b2, , bmn (mỗi số không vượt quá 109);

 Dòng tiếp theo chứa số nguyên k (1 ≤ k ≤ 106);

 Dòng thứ i trong số k dòng tiếp theo chứa 2 số nguyên pi và qi (i = 1, 2, , k)

Hai số liên tiếp trên cùng một dòng được ghi cách nhau bởi dấu cách

Kết quả: Ghi ra file văn bản NUMTAB.OUT gồm k dòng, mỗi dòng chứa một số là câutrả lời cho truy vấn theo thứ tự xuất hiện trong dữ liệu vào

Ví dụ:

Trang 14

3 3

3 8 7 6 3 2 4 6 64

Tìm hiểu chương trình giải sau (sẽ được trao đổi khi tập huấn).

int kq01[MAX][MAX], kq12[MAX][MAX], w[MAX][MAX];

int xLen, xArr[32];

if (dx[pos][firstDigit][firstOk][lastDigit][lastOk]) return res;

if (pos>15) return ((firstDigit == lastDigit) && (firstOk == lastOk)); res = 0;

for (int cs = 0; cs<=max(xArr[pos],firstOk); cs++)

Trang 15

int tinhSL15(int x, int firstDigit, int firstOk, int lastDigit, int lastOk) { int &res = fy[x][firstDigit][firstOk][lastDigit][lastOk];

if (dy[x][firstDigit][firstOk][lastDigit][lastOk]) return res;

for (int digit=0; digit<=1; digit++)

for (int ok=0; ok<=1; ok++) {

int tmp = tinhSL15(xB, digit, ok, 0, 0);

tmp += tinhSL15(xB, digit, ok, 0, 1);

tmp += tinhSL15(xB, digit, ok, 1, 0);

tmp += tinhSL15(xB, digit, ok, 1, 1);

res = res + tinhSL15(xA, 0, 0, digit, ok )*tmp;

}

return (x+1 - res);

}

void docFile() {

Ngày đăng: 14/10/2015, 14:42

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

w