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

THUẬT TOÁN QUY HOẠCH ĐỘNG

11 717 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 11
Dung lượng 112,5 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 thuật toán quy hoạch động Đối với nhiều thuật toán chúng ta đã biết nguyên lý “chia để trị” thường đóng vai trò chủ đạo trong việc thiết kế thuật toán: để giải quyết bài toán

Trang 1

THUẬT TOÁN QUY HOẠCH ĐỘNG

Nguyễn Hồng Thái Trường THPT Chuyên Hạ Long, Quảng Ninh

1 Giới thiệu thuật toán quy hoạch động

Đối với nhiều thuật toán chúng ta đã biết nguyên lý “chia để trị” thường đóng vai trò chủ đạo trong việc thiết kế thuật toán: để giải quyết bài toán lớn, chúng ta chia nó thành nhiều bài toán con có thể được giải quyết độc lập Trong thuật toán quy hoạch động, việc thể hiện nguyên lý này được đẩy đến cực độ, chúng ta giải quyết các bài toán con và lưu trữ những lời giải này với mục đích sử dụng lại chúng theo một sự phối hợp nào đó để giải quyết các bài toán tổng quát hơn Cách tiếp cận này được ứng dụng rộng rãi trong vận trù học

Thuật ngữ “quy hoạch động” mà chúng ta đề cập ở đây ngụ ý nói đến quá trình đưa bài toán ban đầu về một dạng nào đó có thể áp dụng phương pháp này để giải Ý tưởng cơ bản của nó

là giải các bài toán con giống như vậy Dưới đây chúng ta xem xét một vài bài toán cụ thể để qua đó giới thiệu phương pháp tiếp cận này

2 Thuật toán q uy hoạch động trên mảng một chiều

Bài toán 1 Cho một dãy gồm n số nguyên: a 1 , a 2 , , a n (1 ≤ n ≤ 105, 0 < a i < 106) Hãy loại

bỏ một số ít nhất các phần tử của dãy số và giữ nguyên thứ tự các phần tử còn lại sao cho dãy

số còn lại là một dãy tăng Ta gọi dãy số còn lại sau khi đã loại bỏ một số phần tử là dãy con của dãy đã cho Như vậy yêu cầu của bài toán cũng đồng nghĩa với việc tìm dãy con tăng dài nhất, tức là nhiều phần tử nhất

Phân tích và thiết kế thuật toán

Thuật toán 1:

Một thuật toán đơn giản cho bài toán này là thuật toán duyệt và có đánh giá nhánh cận Rõ ràng với bài toán này thì thuật toán trên sẽ không đáp ứng được yêu cầu về mặt thời gian Vì vậy ta cần tìm một thuật toán tốt cho bài toán trên

Ý tưởng của thuật toán này là ta sẽ lần lượt đi giải n bài toán con sau: tìm dãy con tăng dài nhất của dãy a 1 , a 2 , , a i với i = 1, 2, , n Rõ ràng bài toán con cuối cùng (ứng với i = n) là bài toán gốc ban đầu của ta Mặt khác lời giải của bài toán i sẽ kế thừa lời giải của các bài toán nhỏ trước đó Vì vậy ta lưu lời giải của các bài toán vào mảng một chiều best[1 n], ở đó best[i] là số phần của dãy con tăng dài nhất của dãy a 1 , a 2 , , a i với a i là phần tử cuối cùng của dãy con tăng dài nhất nói trên

Ta có công thức truy hồi tính best[i] như sau:

best[i] = max{best[j] + 1} với mọi j = 1, 2, , (i-1) và a j < a i

Nếu các phần tử a j đứng trước a i đều lớn hơn hoặc bằng a i thì công thức trên không xác định

được giá trị cho best[i], trong trường hợp này best[i] = 1.

Nhìn vào công thức truy hồi trên, ta thấy cần phải khởi tạo giá trị best[1] = 1.

Như vậy độ dài của dãy con tăng dài nhất của dãy đã cho sẽ là giá trị lớn nhất của các phần tử

mảng best: max{best[i]} với mọi i = 1, 2, …, n.

Trang 2

Công việc cuối cùng là tìm các phần tử của dãy con tăng dài nhất Để làm việc này ta dùng

một mảng truoc[1 n] với ý nghĩa truoc[i] là chỉ số của phần tử trước phần tử i trong dãy con tăng dài nhất Do đó từ mảng truoc ta có thể lấy chỉ số các phần tử thuộc dãy con tăng dài

nhất bằng cách lần ngược từ phần tử cuối về phần tử đầu Vì vậy để in ra các phần tử của dãy

con tăng dài nhất ta phải dùng thêm một mảng phụ p và in ngược lại các phần tử của mảng p Chú ý rằng các phần tử của mảng truoc được khởi tạo bằng 0, do vậy trước của phần tử đầu

tiên trong dãy con tăng dài nhất là 0

m := 0; // số phần tử của dãy con tăng dài nhất

i := i_max; // i_max là chỉ số của phần tử lớn nhất mảng best

while i <> 0 do

begin

m := m + 1;

p[m] := a[i];

i := truoc[i];

end;

Khi đó các phần tử của dãy con tăng dài nhất được in ra bằng dòng lệnh:

for i := m downto 1 do writeln(p[i]);

Tuy nhiên nếu tinh ý ta có thể nhận ra tính đệ quy trong việc in kết quả Do đó thủ tục in ra dãy con tăng dài nhất rất ngắn gọn và sáng sủa:

procedure print(i : integer);

begin

if i = 0 then exit;

print(truoc[i]);

writeln(f, a[i]);

end;

Công việc in ra chỉ cần một lời gọi: print(i_max);

Độ phức tạp thời gian của thuật toán 1 là O(n2) Chương trình được cài đặt như sau

program day_con_tang_dai_nhat_1;

const

FI = 'dctdn.in';

FO = 'dctdn.out';

var

n : longint;

a, best, truoc : array[1 100000] of longint;

f : text;

procedure doc;

var

i : longint;

begin

assign(f, FI); reset(f);

readln(f, n);

for i := 1 to n do readln(f, a[i]);

close(f);

end;

procedure xuli;

var

i, j : longint;

Trang 3

for i := 1 to n do

begin

best[i] := 1;

truoc[i] := 0;

for j := 1 to (i-1) do

if (a[j] < a[i]) and (best[i] < best[j] + 1) then

begin

best[i] := best[j] + 1;

truoc[i] := j;

end;

end;

end;

procedure print(i : longint);

begin

if i = 0 then exit;

print(truoc[i]);

writeln(f, a[i]);

end;

procedure ghi;

var

i, j : longint;

begin

assign(f, FO); rewrite(f);

i := 1;

for j := 2 to n do

if best[j] > best[i] then i := j;

writeln(f, best[i]);

print(i);

close(f);

end;

begin

doc;

xuli;

ghi;

end.

Thuật toán 2:

Gọi p j là vị trí của phần tử nhỏ nhất để dãy con tăng có độ dài đúng bằng j trong dãy a1, a2, ,

a i Ta sẽ sử dụng thuật toán tìm kiếm nhị phân để xây dựng mảng p Độ phức tạp thời gian của thuật toán 2 là O(n.log2n).

program day_con_tang_dai_nhat_2;

const

FI = 'dctdn.in';

FO = 'dctdn.out';

var

n, m : longint;

a, p, truoc : array[0 100000] of longint;

f : text;

procedure doc;

var

i : longint;

begin

assign(f, FI); reset(f);

readln(f, n);

for i := 1 to n do readln(f, a[i]);

Trang 4

close(f);

end;

procedure xuli;

var

i, j, l, r, c : longint;

begin

a[0] := -MAXLONGINT;

m := 0;

p[0] := 0;

for i := 1 to n do

begin

if a[i] < a[p[1]] then j := 0

else

if a[i] > a[p[m]] then j := m

else

begin

l := 1; r := m;

repeat

c := (l+r) div 2;

if a[p[c]] < a[i] then l := c

else r := c;

until l+1 >= r;

j := l;

end;

truoc[i] := p[j];

if (j = m) or (a[i] < a[p[j+1]]) then

begin

p[j+1] := i;

if j = m then inc(m);

end;

end;

end;

procedure print(i : integer);

begin

if i = 0 then exit;

print(truoc[i]);

writeln(f, a[i]);

end;

procedure ghi;

begin

assign(f, FO); rewrite(f);

writeln(f, m);

print(p[m]);

close(f);

end;

begin

doc;

xuli;

ghi;

end.

3 Thuật toán quy hoạch động trên mảng hai chiều

Chúng ta có thể gặp các bài toán mà mảng quy hoạch động có kích thước lớn hơn: 2, 3, … chiều, chẳng hạn như bài toán dưới đây

Trang 5

Bài toán 2 Cho 2 dãy số nguyên a1, , a m và b1, , b n Hãy tìm dãy con chung dài nhất của

cả 2 dãy

Phân tích và thiết kế thuật toán

Ở đây, bài toán con là tìm dãy con chung dài nhất của 2 dãy nhỏ hơn: dãy gồm i (i = 1, 2, , n) phần tử đầu tiên của dãy thứ nhất và dãy gồm j (j = 1, 2, , n) phần tử đầu tiên của dãy thứ hai Ta gọi best[i, j] là độ dài của dãy con chung dài nhất này

Bây giờ ta xét bài toán tìm dãy con chung dài nhất của hai dãy a1, , a i và b1, , b j với i =

1, , m; j = 1, , n, giả sử rằng các bài toán với i, j nhỏ hơn đã giải xong Ta hãy bắt đầu tại

hai phần tử cuối cùng của hai dãy, có hai khả năng xảy ra:

Trường hợp thứ nhất a[i] = b[j]: Suy ra best[i, j] = best[i-1, j-1] + 1.

Trường hợp thứ hai a[i] ≠ b[j]: Suy ra best[i, j] = max(best[i, j-1], best[i-1, j]).

Nhìn vào công thức truy hồi trên, ta thấy cần phải khởi tạo hàng 1 và cột 1 của mảng best, tức

là phải giải bài toán khi 1 trong 2 dãy có một phần tử Thực ra bài toán cơ sở này là dễ, nhưng

để dễ hơn, ta sẽ xét bài toán con của nó là khi có 1 trong 2 dãy là rỗng (i = 0 hoặc j = 0) Lời

giải bài toán này đơn giản là không có dãy con chung nào cả Vì vậy ta sẽ mở rộng mảng best

ra thêm hàng 0, cột 0 và thay vì phải khởi tạo cho hàng 1, cột 1 ta sẽ khởi tạo cho hàng 0, cột 0:

best[0, j] = 0 với mọi j = 0, 1, …, n.

best[i, 0] = 0 với mọi i = 0, 1, …, m.

Khi đó best[m, n] sẽ là độ dài của dãy con chung dài nhất của hai dãy số đã cho Hơn nữa, dựa vào mảng best ta có thể đưa ra được một dãy con chung dài nhất.

Thuật toán có độ phức tạp thời gian là O(m×n).

Cài đặt thuật toán

program day_con_chung_dai_nhat;

const

FI = 'dccdn.in';

FO = 'dccdn.out';

var

m, n : integer;

a, b : array[1 5000] of longint;

best : array[0 5000, 0 5000] of integer;

f : text;

procedure doc;

var

i : integer;

begin

assign(f, FI); reset(f);

read(f, m, n);

for i := 1 to m do read(f, a[i]);

for i := 1 to n do read(f, b[i]);

close(f);

end;

Function max(a, b : integer) : integer;

Begin

if a > b then max := a

else max := b;

End;

Trang 6

procedure xuly;

var

i, j : integer;

begin

for i := 0 to m do best[i, 0] := 0;

for j := 0 to n do best[0, j] := 0;

for i := 1 to m do

for j := 1 to n do

if a[i] <> b[j] then best[i, j] := max(best[i, j-1], best[i-1, j]) else best[i, j] := best[i-1, j-1] + 1;

end;

procedure print(i, j : integer);

begin

if best[i, j] = 0 then exit;

if a[i] = b[j] then

begin

print(i-1, j-1);

writeln(f, a[i]);

end

else

if best[i, j] = best[i-1, j] then print(i-1, j)

else print(i, j-1);

end;

procedure ghi;

begin

assign(f, FO); rewrite(f);

writeln(f, best[m, n]);

print(m, n);

close(f);

end;

begin

doc;

xuly;

ghi;

end.

4 Kết luận

Như đã nói ở trên, chìa khóa trong thuật toán quy hoạch động là việc xây dựng các bài toán con mà ta gọi là mảng quy hoạch động Mảng này có thể là 1, 2 hoặc có thể nhiều chiều tùy thuộc vào lời giải của bài toán phụ thuộc vào các loại tham số nào Tiếp đến là cách quy nạp thu gọn bài toán sau mỗi bước, tức là không gian bài toán (kích thước dữ liệu) nhỏ lại, cho đến khi nào ta hoàn toàn có thể giải được bài toán nhỏ (điểm dừng của quy nạp) Bản chất của công việc này là ta phải xây dựng được lời giải của bài toán qua các bài toán con, tức là lập được công thức truy hồi, và dựa vào công thức truy hồi, ta sẽ biết được cần phải khởi tạo như thế nào

Trong các phần trên, chúng ta đã khảo sát một số bài toán có thể dùng thuật toán quy hoạch

động để giải quyết một cách hiệu quả Những vấn đề này đều liên quan đến bài toán tìm phương án tối ưu để thực hiện một công việc nào đó và chúng có chung một tính chất là đáp

án tốt nhất cho một bài toán con vẫn được duy trì khi bài toán con đó trở thành một phần trong bài toán lớn hơn

Trang 7

Thuật toán quy hoạch động thường được áp dụng để giải các bài toán tối ưu, bài toán đếm, …

Vì vậy, nếu giới hạn kích thước dữ liệu của các bài toán tối ưu lớn và việc sử dụng các thuật toán khác (như duyệt, nhánh cận, ) có độ phức tạp thời gian lớn thì chúng ta hãy nghĩ đến thuật toán quy hoạch động

5 Bài t ậ p áp dụng

1 Triangle

Hãy xem tam giác số dưới đây Hãy viết chương trình tính

tổng lớn nhất của các số trên đường đi bắt đầu từ đỉnh và kết

thúc đâu đó ở đáy Mỗi bước có thể đi chéo xuống phía trái

hoặc đi chéo xuống phía phải

Trong ví dụ trên, đường đi từ 7 đến 3 đến 8 đến 7 đến 5 sẽ

tạo ra tổng lớn nhất là 30

Dữ liệu: Dòng đầu tiên của file vào ghi số nguyên N (1 ≤ N

≤ 1.000) là số lượng hàng của tam giác; Dòng thứ i trong số N dòng tiếp theo, ghi các số trên hàng thứ i của tam giác Các số ghi cách nhau bởi một dấu cách và có giá trị trong đoạn từ 0

đến 100

Kết quả: Ghi ra file ra tổng lớn nhất của các số trên đường đi theo quy tắc nêu trên.

Ví dụ:

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

30

2 Piggy-Bank

Trước khi nhóm ACM có thể làm một việc gì đó thì cần phải chuẩn bị một ngân sách và sự hỗ trợ tài chính cần thiết Nguồn thu nhập chính cho việc này là từ tiền tiết kiệm Ý tưởng này rất đơn giản: bất cứ khi nào mỗi thành viên của nhóm ACM có một số tiền nhỏ, họ lấy tất cả các đồng tiền đó và bỏ chúng vào con lợn đất Bạn biết rằng, khi bỏ các đồng tiền vào thì không thể lấy các đồng tiền đó ra nếu không đập vỡ con lợn đất Sau một khoảng thời gian đủ dài thì

sẽ có đủ số tiền mặt có trong con lợn đất để chi trả mọi thứ cần thiết

Nhưng có một vấn đề lớn đối với các con lợn đất là không thể xác định có bao nhiêu tiền ở bên trong Vì vậy, chúng ta chỉ có thể đập vỡ con lợn thành các mảnh nhỏ thì mới biết là có bao nhiêu tiền ở bên trong nó Rõ ràng chúng ta không muốn tình huống này xảy ra Tuy nhiên, có một điều mà chúng ta có thể làm được là cân con lợn đất và ước chừng có bao nhiêu tiền ở trong đó Giả sử rằng chúng ta xác định được chính xác trọng lượng của con lợn và chúng ta biết trọng lượng của tất cả các đồng tiền, thì chúng ta có thể chắn chắn có một lượng tiền tối thiểu ở trong con lợn Nhiệm vụ của bạn là phải tìm ra trường hợp xấu nhất này và xác định lượng tiền tối thiểu trong con lợn đất đó Chúng tôi cần sự giúp đỡ của bạn để không có con lợn đất nào bị đập vỡ trước thời hạn

Trang 8

Dữ liệu: Dòng đầu tiên của file vào chứa hai số nguyên E và F Các số này là trọng lượng của

con lợn rỗng và con lợn chứa đầy các đồng tiền Cả hai trọng lượng là được cho bằng đơn vị gam Không có con lợn nào nặng quá 10 kg, điều này có nghĩa là 1 ≤ E F ≤ 10.000 Dòng

thứ hai ghi một số nguyên N (1 N ≤ 500) là số các đồng tiền khác nhau có thể được sử dụng

Tiếp theo có đúng N dòng, mỗi dòng mô tả một loại tiền Mỗi dòng này chứa hai số nguyên P

và W (1 P ≤ 50.000, 1 ≤ W 10.000) P là giá trị một đơn vị tiền tệ của loại đồng tiền này,

W là trọng lượng của nó tính bằng gam.

Kết quả: File ra gồm một dòng ghi đúng một số nguyên là lượng tiền nhỏ nhất có thể có được

khi sử dụng các đồng tiền trên để bỏ vào lợn có trọng lượng ban đầu E (lợn rỗng) để đạt đến trọng lượng F Nếu trọng lượng của lợn không thể đạt được đúng bằng F thì ghi ra câu

“impossible”

Ví dụ:

10 110

2

1 1

30 50

60

1 6

2

10 3

20 4

impossible

3 Little shop of flowers (IOI ’99)

Bạn muốn sắp đặt cửa sổ hiệu bán hoa của mình sao cho hấp dẫn nhất Bạn có M bó hoa, mỗi

bó một loại khác nhau và số bó hoa không nhiều hơn số bình hoa sắp sẵn thành một hàng trên

cửa sổ Các bình hoa được gắn cố định và được đánh số liên tục từ 1 đến N, trong đó N là số bình, theo thứ tự từ trái sang phải sao cho bình 1 là bình bên trái nhất, còn bình N là bình bên phải nhất Mỗi bó hoa được gán một số nguyên duy nhất có giá trị trong khoảng giữa 1 và M

và có thể được cắm vào các bình khác nhau Số hiệu của các bó hoa có ý nghĩa như sau: bó

hoa i nằm bên trái bó hoa j trong dãy các bình hoa nếu i < j Ví dụ, giả sử ta có một bó hoa Đỗ

Quyên (có số hiệu là 1), một bó hoa Thu Hải Đường (có số hiệu là 2) và một bó hoa Cẩm Chướng (có số hiệu là 3) Bây giờ tất cả các bó hoa phải được cắm vào dãy các bình hoa bảo đảm ràng buộc về thứ tự các số hiệu Bó hoa Đỗ Quyên phải cắm vào bình phía bên trái của bình hoa Thu Hải Đường Còn bó hoa Thu Hải Đường phải cắm vào bình phía bên trái của bình hoa Cẩm Chướng Nếu số bình hoa nhiều hơn số bó hoa thì những bình không dùng đến

sẽ để trống Mỗi bình chỉ được cắm 1 bó hoa

Mỗi bình hoa có đặc điểm khác nhau (cũng như bản thân các bó hoa) Vì vậy, khi một bó hoa được cắm vào bình sẽ có một giá trị thẩm mỹ nhất định, được biểu diễn bởi một số nguyên Các giá trị thẩm mỹ được cho trong bảng dưới đây Các bình để trống sẽ có giá trị thẩm mỹ bằng 0

Theo bảng trên, hoa Đỗ Quyên sẽ rất hấp dẫn khi được cắm vào bình 2, nhưng sẽ khó coi khi cắm vào bình 4

Trang 9

Để nhận được hiệu quả thẩm mỹ tốt nhất, bạn phải tìm cách cắm các bó hoa vào bình tuân theo ràng buộc về thứ tự sao cho tổng các giá trị thẩm mỹ là lớn nhất

Dữ liệu: Dòng đầu tiên của file vào chứa hai số M, N (1 M N 100) M dòng tiếp theo, mỗi dòng chứa N số nguyên sao cho A ij là số thứ j trên dòng thứ (i+1), trong đó A ij là giá trị

thẩm mỹ đạt được khi cắm bó hoa i vào bình j (-50 A ij≤ 50)

Kết quả: File ra chứa hai dòng, dòng 1 ghi giá trị tổng nhận được theo cách cắm của bạn;

dòng 2 biểu diễn cách cắm như là một danh sách M số, sao cho số thứ k trong dòng này cho biết bình hoa dùng để cắm bó hoa có số hiệu k Nếu có nhiều cách cắm cùng cho giá trị tổng

lớn nhất thì đưa ra cách cắm nhỏ nhất theo thứ tự từ điển

Ví dụ:

3 5

7 23 -5 -24 16

5 21 -4 10 23

-21 5 -4 -20 20

53

2 4 5

4 Palindrome (IOI2000 - Beijing China)

Xâu đối xứng là xâu mà việc đọc nó từ trái sang phải cũng như từ phải sang trái Bạn hãy viết một chương trình, cho trước một xâu và xác định số ký tự nhỏ nhất cần chèn vào xâu để có được một xâu đối xứng

Ví dụ, chèn 2 ký tự vào xâu “Ab3bd” sẽ tạo thành một xâu đối xứng (“dAb3bAd” hoặc

“Adb3bdA”) Hơn nữa, việc chèn ít hơn 2 ký tự sẽ không tạo ra một xâu đối xứng

Dữ liệu: File vào gồm 2 dòng Dòng đầu tiên chứa một số nguyên N là độ dài của xâu vào (3

N 5000); Dòng thứ hai chứa một xâu độ dài N Xâu này chỉ gồm các chữ cái in hoa từ ‘A’

đến ‘Z’, các chữ cái in thường từ ‘a’ đến ‘z’ và các chữ số từ ‘0’ đến ‘9’ Các chữ cái in hoa

và in thường được xem là khác nhau

Kết quả: File ra gồm một dòng chứa một số nguyên là số ký tự nhỏ nhất cần chèn như mô tả

ở trên

Ví dụ:

5

5 Truyền tin

Người ta cần truyền n gói tin được đánh số từ 1 đến n từ một điểm phát đến một điểm thu Để thực hiện việc truyền tin có thể sử dụng m đường truyền được đánh số từ 1 đến m Biết rằng nếu truyền j gói tin theo đường truyền tin i thì chi phí phải trả là s ij (s ij là số nguyên dương, s ij

32767; i = 1, 2, , m; j = 1, 2, , n).

Hãy xác định số lượng gói tin cần truyền theo mỗi đường truyền tin để việc truyền n gói tin

được thực hiện với tổng chi phí phải trả là nhỏ nhất

Trang 10

Dữ liệu: Dòng đầu tiên chứa hai số nguyên dương n và m (n , m 100); Dòng thứ i trong số

m dòng tiếp theo chứa n số nguyên dương s i1 s i2 s in , i = 1, 2, , m.

Kết quả: Dòng đầu tiên chứa S là tổng chi phí phải trả theo cách truyền tin tìm được; Dòng

thứ hai chứa m số nguyên không âm q 1 q 2 q m , trong đó q i là số gói tin cần truyền theo đường

truyền tin i.

Ví dụ:

3 3

20 20 20

4 3 10

1 3 20

4

0 2 1

6 Coin

Giả sử tại một lúc nào đó bạn có N loại tiền kim loại (dạng đồng xu) được đánh số từ 1 đến N, mỗi loại có số lượng đồng không giới hạn Mỗi đồng của loại tiền kim loại thứ i mang giá trị

v i xu và có trọng lượng w i gam Vì các loại tiền được đúc bằng các kim loại khác nhau nên có thể có những loại tiền cùng giá trị hoặc cùng trọng lượng nhưng không thể đồng thời có cùng giá trị và trọng lượng

Trong số N loại tiền của bạn, hãy chọn ra một số ít nhất M các đồng, sao cho chúng có tổng giá trị là V xu và tổng trọng lượng là W gam M sẽ nhận giá trị 0 nếu không có cách chọn các đồng tiền thoả mãn hai giá trị V và W.

Dữ liệu: Dòng đầu tiên chứa 3 số tự nhiên N, V, W (1 N ≤ 20; 1 ≤ V, W 150); N dòng tiếp theo, dòng thứ i chứa cặp số (v i , w i ) là thông tin về một đồng của loại tiền thứ i (1 v i , w i

150)

Kết quả: Nếu không tìm được cách thoả mãn thì chỉ ghi vào file ra số 0 Ngược lại, ghi ra file

ra: Dòng 1: Ghi số M thoả mãn yêu cầu đặt ra; Dòng 2: Ghi N số nguyên không âm, trong đó

số thứ i cho biết số đồng được chọn của loại tiền thứ i Các số viết cách nhau bởi một dấu

cách Nếu có nhiều lời giải, hãy đưa ra lời giải nhỏ nhất theo thứ tự từ điển

Ví dụ:

8 141 4

1 1

2 1

4 1

8 1

16 1

32 1

64 1

128 1

4

1 0 1 1 0 0 0 1

4 11 17

12 34 7

8 10

21 9

0

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

TỪ KHÓA LIÊN QUAN

w