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

Chuyên đề PHƯƠNG PHÁP QUY HOẠCH ĐỘNG

28 475 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 28
Dung lượng 279 KB

Nội dung

Trường THPT Chuyên Thái Nguyên Chuyên đề PHƯƠNG PHÁP QUY HOẠCH ĐỘNG Nguyên lý tối ưu Bellman Phương pháp quy hoạch động nguyên lý tối ưu nhà toán học Mỹ R.Bellman đề xuất vào năm 50 kỷ 20 Phương pháp áp dụng để giải hàng loạt toán thực tế trình kỹ thuật cộng nghệ, tổ chức sản xuất, kế hoạch hoá kinh tế… Trong thực tế, ta thường gặp số toán tối ưu loại sau: Có đại lượng f hình thành trình gồm nhiều giai đoạn ta quan tâm đến kết cuối giá trị f phải lớn nhỏ nhất, ta gọi chung giá trị tối ưu f Giá trị f phụ thuộc vào đại lượng xuất toán mà giá trị chúng gọi trạng thái hệ thống phụ thuộc vào cách thức đạt giá trị f giai đoạn mà cách tổ chức gọi điều khiển Đại lượng f thường gọi hàm mục tiêu trình đạt giá trị tối ưu f gọi trình điều khiển tối ưu Bellman phát biểu nguyên lý tối ưu (cũng gọi nguyên lý Bellman) mà ý tưởng sau: “Với trình điều khiển tối ưu, trạng thái bắt đầu A0, với trạng thái A q trình đó, phần trình kể từ trạng thái A xem trạng thái bắt đầu tối ưu” Chú ý nguyên lý thừa nhận mà không chứng minh Phương pháp tìm điều khiển tối ưu theo nguyên lý Bellman thường gọi quy hoạch động Thuật ngữ nói lên thực chất q trình điều khiển động: số bước lựa chọn điều khiển tối ưu dường không tốt tựu chung trình lại tốt Hiểu cách đơn giản quy hoạch động phương pháp giải toán từ nhỏ đến lớn, việc giải – tìm phương án tối ưu toán nhỏ lưu trữ kết lại sẽ giúp ta giải toán với kích thước lớn dần đến đạt kết mong muốn Ý tưởng nội dung phương pháp quy hoạch động Xét toán sau: Cho dãy N số nguyên A1, A2,…,AN Hãy tìm cách xoá số ít số hạng để dãy cịn lại đơn điệu hay nói cách khác chọn số nhiều số hạng cho dãy B gồm số hạng theo trình tự xuất dãy A đơn điệu Quá trình chọn B điều khiển qua N giai đoạn để đạt mục tiêu số lượng số hạng dãy B nhiều nhất, điều khiển giai đoạn i thể việc chọn hay không chọn Ai vào dãy B Giả sử dãy cho 10 Nếu ta chọn 1, 8, 10 chọn số hạng bỏ qua 10 ta chọn số hạng 1, 2, 4, 6, Khi giải toán cách “chia để trị” chuyển việc giải toán kích thước lớn việc giải nhiều tốn kiểu có kích thước nhỏ thuật tốn thường thể chương trình đệ quy Khi đó, thực tế, nhiều kết trung gian phải tính nhiều lần Vậy ý tưởng quy hoạch động : Tránh tính tốn lại thứ hai lần, mà lưu giữ kết tìm kiếm vào mợt bảng làm giả thiết cho việc tìm kiếm kết trường hợp sau Chúng ta sẽ làm đầy dần giá trị bảng kết trường hợp trước giải Kết cuối chính kết toán cần giải Nói cách khác phương pháp quy hoạch động thể sức mạnh nguyên lý chia để trị đến cao độ Quy hoạch động kỹ thuật thiết kế bottom-up (từ lên) Nó bắt đầu với trường hợp nhỏ (thường đơn giải giải ngay) Bằng cách tổ hợp kết có (khơng phải tính lại) trường hợp con, đạt đạt tới kết trường hợp có kích thước lớn dần lên tổng quát hơn, cuối đạt tới lời giải trường hợp tổng quát Trong số trường hợp, giải toán A, trước hết ta tìm họ tốn A(p) phụ thuộc tham số p (có thể p véc tơ) mà A(p0)=A với p0 trạng thái ban đầu tốn A Sau tìm cách giải họ tốn A(p) với tham số p cách áp dụng nguyên lý tối ưu Bellman Cuối cho p=p0 sẽ nhận kết toán A ban đầu Các bước thực Bước 1: Lập hệ thức Dựa vào nguyên lý tối ưu tìm cách chia trình giải tốn thành giai đoạn, sau tìm hệ thức biểu diễn tương quan định bước xử lý với bước xử lý trước Hoặc tìm cách phân rã tốn thành “bài tốn con” tương tự có kích thước nhỏ hơn, tìm hệ thức nêu quan hệ kết toán kích thước cho với kết “bài tốn con” kiểu có kích thước nhỏ nhằm xây dựng phương trình truy tốn (dạng hàm thủ tục đệ quy) Về một cách xây dựng phương trình truy tốn: Ta chia việc giải toán thành n giai đoạn Mỗi giai đoạn i có trạng thái ban đầu t(i) chịu tác động điều khiển d(i) sẽ biến thành trạng thái t(i+1) giai đoạn i+1 (i=1,2,…,n-1) Theo nguyên lý tối ưu Bellman việc tối ưu giai đoạn cuối khơng làm ảnh hưởng đến kết tồn toán Với trạng thái ban đầu t(n) sau làm giai đoạn n tốt ta có trạng thái ban đầu giai đoạn n-1 t(n-1) tác động điều khiển giai đoạn n-1 d(n-1), tiếp tục xét đến giai đoạn n-1 Sau tối ưu giai đoạn n-1 ta lại có t(n-2) d(n-2) lại tối ưu giai đoạn n-2 … giai đoạn từ n giảm đến tối ưu coi hồn thành toán Gọi giá trị tối ưu toán tính đến giai đoạn k Fk, giá trị tối ưu toán tính riêng giai đoạn k Gk Fk = Fk-1 + Gk ax {G k (t (k ), d ( k )) + Fk −1 (t (k − 1))} (*) Hay là: F1 (t (k )) = m ∀d ( k ) Bước 2: Tổ chức liệu chương trình Tổ chức liệu cho đạt yêu cầu sau:  Dữ liệu tính toán dần theo bước  Dữ liệu lưu trữ để giảm lượng tính toán lặp lại  Kích thước miền nhớ dành cho lưu trữ liệu nhỏ tốt, kiểu liệu chọn phù hợp, nên chọn đơn giản dễ truy cập Cụ thể • Các giá trị Fk thường lưu trữ bảng (mảng chiều hai, ba, v.v… chiều) • Cần lưu ý khởi trị giá trị ban đầu bảng cho thích hợp, kết tốn có kích cỡ nhỏ tốn giải: F1 (t (1)) = m ax {G (t (1), d (1)) + F0 (t (0))} ∀d (1) • Dựa vào cơng thức, phương trình truy tốn (*) giá trị có bảng để tìm dần giá trị cịn lại bảng • Ngồi cần mảng lưu trữ nghiệm tương ứng với giá trị tối ưu gian đoạn • Dựa vào bảng lưu trữ nghiệm bảng giá trị tối ưu giai đoạn xây dựng, tìm kết toán Bước 3: Làm tốt Làm tốt thuật toán cách thu gọn hệ thức (*) giảm kích thước miền nhớ Thường tìm cách dùng mảng chiều thay cho mảng hai chiều giá trị dòng (hoặc cột) mảng hai chiều phụ thuộc dòng (hoặc cột) kề trước Trong số trường hợp thay mảng hai chiều với giá trị phần tử nhận giá trị 0, mảng hai chiều cách dùng kỹ thuật quản lý bit Ví dụ minh họa Cho số tự nhiên n ≤ 100 Hãy cho biết có cách phân tích số n thành tổng dãy số ngun dương, cách phân tích hốn vị tính mợt cách n = có cách phân tích: = + + + + = + + + = + + 4 = + + 5 = + = + = (Lưu ý: n = coi có cách phân tích thành tổng số nguyên dương (0 tổng dãy rỗng) Bước 1: Lập hệ thức Nhận xét: Nếu gọi F[m, v] số cách phân tích số v thành tổng số nguyên dương ≤ m Khi đó: Các cách phân tích số v thành tổng số nguyên dương ≤ m chia làm hai loại: - Loại 1: Không chứa số m phép phân tích, số cách phân tích loại chính số cách phân tích số v thành tổng số nguyên dương < m, tức số cách phân tích số v thành tổng số nguyên dương ≤ m - F[m - 1, v] - Loại 2: Có chứa ít số m phép phân tích Khi cách phân tích loại ta bỏ số m ta sẽ cách phân tích số v - m thành tổng số nguyên dương ≤ m (Lưu ý: điều khơng tính lặp lại hốn vị cách) Có nghĩa mặt số lượng, số cách phân tích loại F[m, v - m] Trong trường hợp m > v rõ ràng có cách phân tích loại 1, cịn trường hợp m ≤ v sẽ có cách phân tích loại loại Vì thế: F[m 1, v]; if m > v F[m, v]=  F[m-1,v]+F[m,v-m]; if m ≤ v Bước 2: Tổ chức liệu chương trình Ta có cơng thức xây dựng F[m, v] từ F[m - 1, v] F[m, v - m] Cơng thức có tên gọi cơng thức truy hồi đưa việc tính F[m, v] việc tính F[m', v'] với liệu nhỏ Tất nhiên cuối ta sẽ quan tâm đến F[n, n]: Số cách phân tích n thành tổng số nguyên dương ≤ n Ví dụ với n = 5, bảng F sẽ là: F m 1 1 1 1 1 1 2 2 3 3 4 5 V Nhìn vào bảng F, ta thấy F[m, v] tính tổng của: Một phần tử hàng trên: F[m - 1, v] phần tử hàng, bên trái: F[m, v m] Cài đặt: program Analysis_Counting; const max = 100; var F: array[0 max, max] of Integer; n, m, v: Integer; begin Write('n = '); ReadLn(n); FillChar(F[0], SizeOf(F[0]), 0); F[0, 0] := 1; for m := to n for v := to n if v < m then F[m, v] := F[m - 1, v] else F[m, v] := F[m - 1, v] + F[m, v - m]; WriteLn(F[n, n], ' Analyses'); end Bước 3: Làm tốt Cải tiến dùng mảng chiều Cách làm tóm tắt lại sau: Khởi tạo dịng bảng, sau dùng dịng tính dòng 1, dùng dòng tính dòng v.v… tới tính hết dịng n Có thể nhận thấy tính xong dịng thứ k việc lưu trữ dòng từ dòng tới dòng k - khơng cần thiết việc tính dòng k + phụ thuộc giá trị lưu trữ dịng k Vậy ta dùng hai mảng chiều: Mảng Current lưu dòng thời xét bảng mảng Next lưu dòng kế tiếp, mảng Current gán giá trị tương ứng dịng Sau dùng mảng Current tính mảng Next, mảng Next sau tính sẽ mang giá trị tương ứng dòng Rồi lại gán mảng Current := Next tiếp tục dùng mảng Current tính mảng Next, mảng Next sẽ gồm giá trị tương ứng dịng v.v… Vậy ta có cài đặt cải tiến sau: program Analysis_Counting_2; const max = 100; var Current, Next: array[0 max] of Integer; n, m, v: Integer; begin Write('n = '); ReadLn(n); FillChar(Current, SizeOf(Current), 0); Current[0] := 1; for m := to n begin for v := to n if v < m then Next[v] := Current[v] else Next[v] := Current[v] + Next[v - m]; Current := Next; end; WriteLn(Current[n], ' Analyses'); end Một số toán tối ưu giải phương pháp quy hoạch động Bài toán 1: Bài tốn 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 W[i] ≤ 100 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 túi mang tối đa trọng lượng M (M ≤ 100) Hỏi tên trộm sẽ lấy gói hàng để tổng giá trị lớn Input: file văn BAG.INP - Dòng 1: Chứa hai số n, M cách í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 ít dấu cách Output: file văn BAG.OUT - Dòng 1: Ghi giá trị lớn tên trộm lấy - Dịng 2: Ghi số gói bị lấy BAG.INP BAG.OUT 11 11 33 521 44 54 10 44 Bài giải: Nếu gọi F[i, j] giá trị lớn có cách chọn gói {1, 2, …, i} với giới hạn trọng lượng j Thì giá trị lớn chọn số n gói với giới hạn trọng lượng M chính 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 số gói {1, 2, …, i - 1, i} để có giá trị lớn sẽ có hai khả năng: o Nếu khơng chọn gói thứ i F[i, j] giá trị lớn cách chọn số gói {1, 2, …, i - 1} với giới hạn trọng lượng j Tức F[i, j] = F[i - 1, j] o Nếu có chọn gói thứ i (tất nhiên xét tới trường hợp mà W[i] ≤ j) F[i, j] giá trị gói thứ i V[i] cộng với giá trị lớn có cách chọn số gói {1, 2, …, i - 1} với giới hạn trọng lượng j - W[i] Tức mặt giá 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] giá trị lớn có thể, nên F[i, j] sẽ Max giá trị thu Cơ sở quy hoạch động: Dễ thấy F[0, j] = giá trị lớn cách chọn số gói = Tính bảng phương án: Bảng phương án F gồm n + dòng, M + cột, trước tiên điền sở quy hoạch động: Dịng gồm tồn số Sử dụng cơng thức truy hồi, dùng dịng tính dòng 1, dùng dòng tính dòng 2, v.v… đến tính hết dòng n Truy vết Tính xong bảng phương án ta quan tâm đến F[n, M] chính giá trị lớn thu chọn n gói với giới hạn trọng lượng M Nếu F[n, M] = F[n - 1, M] tức khơng chọn gói thứ n, ta truy tiếp F[n - 1, M] Còn F[n, M] ≠ F[n - 1, M] ta thơng báo phép chọn tối ưu có chọn gói thứ n truy tiếp F[n 1, M - W[n]] Cứ tiếp tục truy lên tới hàng bảng phương án program Bag; const InputFile = 'BAG.INP'; OutputFile = 'BAG.OUT'; max = 100; var W, V: Array[1 max] of Integer; F: array[0 max, max] of Integer; n, M: Integer; procedure Enter; var i: Integer; fi: Text; begin Assign(fi, InputFile); Reset(fi); ReadLn(fi, n, M); for i := to n ReadLn(fi, W[i], V[i]); Close(fi); end; procedure Optimize; var i, j: Integer; begin FillChar(F[0], SizeOf(F[0]), 0); for i := to n for j := to M begin {Tính F[i, j]} F[i, j] := F[i - 1, j]; 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]; end; end; procedure Trace; var fo: Text; begin Assign(fo, OutputFile); Rewrite(fo); WriteLn(fo, F[n, M]); while n begin if F[n, M] F[n - 1, M] then begin Write(fo, n, ' '); M := M - W[n]; end; Dec(n); end; Close(fo); end; begin Enter; Optimize; Trace; end Bài toán 2: Chia thưởng Cần chia hết m phần thưởng cho n học sinh theo thứ tự từ giỏi trở xuống cho bạn không nhận ít phần thưởng bạn xếp sau ≤ m, n ≤ 70 Hãy tính số cách chia Thí dụ, với số phần thưởng m = 7, số học sinh n = sẽ có 11 cách chia phần thưởng cho học sinh theo yêu cầu đầu Đó là: 10 Nhận kết quả: Sau điền bảng, giá trị cc[m, n] kết cần tìm Phương án dùng mảng chiều: function Chia2(m,n: integer):longint; var i,j: integer; begin cc[0,0] := 1; for i := to m cc[i,0] := 0; for j := to n begin for i := to j-1 cc[i,j] := cc[i,i]; for i := j to m cc[i,j] := cc[i,j-1]+cc[i-j,j]; end; Chia2 := cc[m,n]; end; Bài toán 3: Phép nhân tổ hợp dãy ma trận Với ma trận A={a[i, j]} kích thước p×q ma trận B={b[i, j]} kích thước q×r Người ta có phép nhân hai ma trận để ma trận C={c[i, j]} kích thước p×r Mỗi phần tử ma trận C tính theo công thức: C [ i, j ] = ∑ k =1 a[i, j ].b[k , j ],1 ≤ i ≤ p,1 ≤ j ≤ r q Ví dụ: A ma trận kích thước × 4, B ma trận kích thước × C sẽ ma trận kích thước × 1 1     0 5 ×  10 11 12     1  0   14 36   1  =  34 14 25 100 21     54 22 41 164 33  1 1  Để thực phép nhân hai ma trận A(p×q) B(q×r) ta làm đoạn chương trình sau: for i := to p for j := to r begin c[i, j] := 0; for k := to q c[i, j] := c[i, j] + a[i, k] * b[k, j]; end; 14 Phí tổn để thực phép nhân ma trận đánh giá qua số lần thực phép nhân số học, với giải thuật nhân hai ma trận kể trên, để nhân ma trận A cấp pxq với ma trận B cấp qxr ta cần thực p.q.r phép nhân số học Phép nhân ma trận khơng có tính chất giao hốn có tính chất kết hợp (A.B).C = A.(B.C) Vậy A ma trận cấp 3x4, B ma trận cấp 4x10 C ma trận cấp 10x15 thì: - Để tính (A.B).C, phép tính (A.B) cho ma trận kích thước 3x10 sau 3.4.10=120 phép nhân số, sau nhân tiếp với C ma trận kết kích thước 3x15 sau 3.10.15=450 phép nhân số Vậy tổng số phép nhân số học phải thực sẽ 570 - Để tính A.(B.C), phép tính (B.C) cho ma trận kích thước 4x15 sau 4.10.15=600 phép nhân số, lấy A nhân với ma trận ma trận kết kích thước 3x15 sau 3.4.15=180 phép nhân số Vậy tổng số phép nhân số học phải thực sẽ 780 Vậy trình tự thực có ảnh hưởng lớn tới chi phí Vấn đề đặt tính số phí tổn ít thực phép nhân dãy ma trận: n ∏ m[i] = m[1].m[2] m[n] i =1 Với : m[1] ma trận kích thước a[1] x a[2] m[2] ma trận kích thước a[2] x a[3] … m[n] ma trận kích thước a[n] x a[n+1] Dữ liệu: file văn MULTMAT.INP - Dòng 1: Chứa số nguyên dương n ≤ 100 - Dòng 2: Chứa n + số nguyên dương a[1], a[2], …, a[n+1] (∀i: ≤ a[i] ≤ 100) cách ít dấu cách Kết quả: file văn MULTMAT.OUT - Dòng 1: Ghi số phép nhân số học tối thiểu cần thực - Dòng 2: Ghi biểu thức kết hợp tối ưu phép nhân dãy ma trận MULTMAT.INP MULTMAT.OUT Number of numerical multiplications: 31 3231223 ((m[1].(m[2].m[3])).((m[4].m[5]).m[6])) 15 Bài giải: Trước hết, dãy có ma trận chi phí 0, ta nhận thấy chi phí để nhân cặp ma trận tính Vậy ghi nhận chi phí cho phép nhân hai ma trận liên tiếp dãy Sử dụng thông tin ghi nhận để tối ưu hoá phí tổn nhân ba ma trận liên tiếp … Cứ tiếp tục ta tính phí tổn nhân n ma trận liên tiếp Công thức truy hồi Gọi f[i, j] số phép nhân số học tối thiểu cần thực để nhân đoạn ma trận liên tiếp: j ∏ m[t ] = m[i].m[i + 1].m[i + 2] m[ j ] t =i Thì f[i, i] = với ∀ i j Để tính ∏ m[t ] có nhiều cách kết hợp: t =i   k   j m[t ] =  ∏ m[u ]  ×  ∏ m[v]  ∀k : i ≤ k j, tức số đầu trái lớn số đầu phải, ta quy ước đặt p(i, j) = - Nếu i = j p(i, i) = dãy khảo sát chứa kí tự nên đối xứng - Nếu i < j s[i] = s[j] p(i, j) = p(i + 1, j – 1) + Vì hai kí tự đầu cuối dãy s[i,j] giống nên cần xác định chiều dài dãy đối xứng dài đoạn s[i + 1, j – 1] cộng thêm đơn vị ứng với hai kí tự đầu cuối dãy - Nếu i < j s[i] ≠ s[j], tức hai kí tự đầu cuối dãy s[i j] khác ta khảo sát hai dãy s[i (j – 1)] s[(i + 1) j] để lấy chiều dài dãy đối xứng dài hai dãy làm kết quả: p(i,j) = max(p(i,j-1),p(i+1,j)) Vấn đề đặt cần tính p(1, n) Mà muốn tính p(1, n) ta phải tính p(i, j) với i, j = n Phương án đệ quy Phương án đệ quy mô tả hàm nguyên rec(i, j) tính trực tiếp giá trị p(i, j) theo tính chất liệt kê Đáp số cho tốn sẽ n-rec(1,n) function rec(i,j: integer): integer; begin if i > j then rec := else if i = j then rec := else {i < j} if s[i] = s[j] then rec := rec(i+1,j-1)+2 else {i < j & s[i] ≠ s[j]} rec := max(rec(i,j-1),rec(i+1,j)); end; Dùng một mảng hai chiều Gọi đệ quy sẽ phát sinh lời gọi hàm trùng lặp Khắc phục điều cách sử dụng mảng hai chiều để tính trước giá trị hàm p(i, j), giá trị tính tối đa lần Nếu dùng mảng hai chiều, thí dụ mảng p[0 n, n] giá trị p[i, j] sẽ điền theo cột, từ cột thứ đến cột thứ n Tại cột ta điền từ lên Ta lưu ý: - Phần tử cột i, dòng j giá trị p[i, j] chính chiều dài dãy đối xứng dài khảo sát dãy s[i j] 20 - Với trị i > j, ta quy định p[i, j] = Như nửa tam giác ma trận p sẽ chứa toàn - Nếu i = j p[i, j] = Như vậy, trị đường chéo chính ma trận p sẽ - Với cịn lại, toạ độ (i, j) sẽ thoả điều kiện i < j, nên p[i, j] sẽ tính sau: 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]); Ta thực điền vài giá trị cho bảng để rút quy luật Hãy bắt đầu với cột 1: p[1, 1] = 0; Sau đến cột 2: p[2, 2] = 1; p[1, 2] = max(p[1, 1], p[2, 2]) = 1, s[1] ≠ s[2] Rồi đến cột 3: p[3,3]=1; p[2,3] = max(p[2, 2], p[3, 3]) = 1, s[2] ≠ s[3]; p[1,3] = max(p[1,2], p[2,3]) = 1, s[1] ≠ s[3],… Dùng hai mảng một chiều Ta sẽ không theo đuổi phương án dùng mảng hai chiều mà vào quy luật điền mảng hai chiều để vận dụng cho hai mảng chiều v[0 (n + 1)] d[0 (n + 1)] Theo kinh nghiệm, ta nên khai báo kích thước mảng rộng chừng hai phần tử để sử dụng phần tử lính canh chứa giá trị khởi đầu phục vụ cho trường hợp số i, j nhận giá trị n + Giả sử mảng v chứa giá trị điền cột j – mảng hai chiều p Ta sẽ điền giá trị cho cột j mảng p vào mảng chiều d Như vậy, bước j, phần tử v[i] sẽ ứng với phần tử p[j – 1, i] phần tử d[i] sẽ ứng với p[j, i] Thủ tục điền trị cho cột d bước j dựa theo kết lưu cột v bước j – sẽ sau: for i := j-1 downto begin if s[i] = s[j] then d[i] := v[i+1]+2 else d[i] := max(v[i],d[i+1]); end; Sau lần lặp với j := n ta chuyển giá trị d cho v để chuẩn bị cho bước procedure QHD; 21 var i,j: integer; begin fillchar(v,sizeof(v),0); for j := to n begin d[j] := 1; for i := j-1 downto begin if s[i]= s[j] then d[i] := v[i+1]+2 else d[i] := max(v[i],d[i+1]); end; v := d; end; writeln(nl,n-d[1]); {dap so} end; Một số tập Bài 1: Xâu đối xứng Tên chương trình: PALINDR.PAS Palindrome xâu ký tự mà đọc từ trái sang phải từ phải sang trái ta xâu Một xâu ký tự ln biểu diễn dãy palindrome ta coi xâu gồm ký tự palindrome Ví dụ: Xâu ‘bobseesanna’ biểu diễn dạng dãy palindrome theo nhiều cách, chẳng hạn: ‘bobseesanna’ = ‘bob’ + ‘sees’ + ‘anna’ ‘bobseesanna’ = ‘bob’ + ‘s’ + ‘ee’ + ’s’ + ‘anna’ ‘bobseesanna’ = ‘b’ +’o’ + ‘b’ + ‘sees’ + ‘a’ + ‘n’ + ‘n’ + ‘a’ Yêu cầu: Cho xâu ký tự s, cần tìm cách biểu diễn xâu s dạng dãy gồm số ít palindrome Dữ liệu: tệp văn PALINDR.INP, gồm dịng chứa xâu ký tự s gồm khơng q 1000 ký tự Kết quả: tệp văn PALINDR.OUT số nguyên dương k số lượng ít palindrome biểu diễn tìm Ví dụ: PALINDR.INP bobseesanna PALINDR.OUT Bài 2: Người thợ lặn 22 Tên chương trình: PROGMAN.PAS Mỗi thợ lặn sử dụng trang thiết bị đặc biệt lặn Có xylanh với bình chứa: chứa ôxy chứa Nitơ Phụ thuộc vào thời gian lặn nước độ sâu việc lặn anh dùng đến lượng oxy nitơ khác Anh ta tuỳ ý sử dụng số xylanh Mỗi xylanh miêu tả trọng lượng dung tích mà chứa Anh biết trước việc lặn cần oxy nitơ Yêu cầu: Bạn tìm xylanh có trọng lượng nhỏ anh mang theo để hoàn thành việc lặn Dữ liệu: tệp văn PROGMAN.INP - Dòng đầu ghi số nguyên: t, a (1

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

TỪ KHÓA LIÊN QUAN

w