KỸ THUẬT THIẾT KẾ THUẬT TOÁN

134 9 0
KỸ THUẬT THIẾT KẾ THUẬT TOÁN

Đ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

Định lý 41 Trong số các phương án tối ưu, chắc chắn có một phương án mà nhiệm vụ đầu tiên được chọn là nhiệm vụ kết thúc sớm nhất. Chứng minh Gọi là nhiệm vụ kết thúc sớm nhất. Với một phương án tối ưu bất kỳ, giả sử thứ tự các nhiệm vụ cần thực hiện trong phương án tối ưu đó là ( ). Do là nhiệm vụ kết thúc sớm nhất nên chắc chắn nó không thể kết thúc muộn hơn , vì vậy việc thay bởi trong phương án này sẽ không gây ra sự xung đột nào về thời gian thực hiện các nhiệm vụ. Sự thay thế này cũng không làm giảm bớt số lượng nhiệm vụ thực hiện được trong phương án tối ưu, nên ( ) cũng sẽ là một phương án tối ưu. Yêu cầu của bài toán là chỉ cần đưa ra một phương án tối ưu, vì thế ta sẽ chỉ ra phương án tối ưu có nhiệm vụ đầu tiên là nhiệm vụ kết thúc sớm nhất trong số nhiệm vụ. Điều này có nghĩa là chúng ta không cần thử khả năng chọn nhiệm vụ đầu tiên, đi giải các bài toán con, rồi mới đánh giá chúng để đưa ra quyết định cuối cùng. Chúng ta sẽ đưa ngay ra quy t định tức thời: chọn ngay nhiệm vụ kết thúc sớm nhất làm nhiệm vụ đầu tiên. Sau khi chọn nhiệm vụ , bài toán lớn quy về bài toán con: Chọn nhiều nhiệm vụ nhất trong số các nhiệm vụ được bắt đầu sau khi kết thúc. Phép chọn tham lam lại cho ta một quyết định tức thời: nhiệm vụ tiếp theo trong phương án tối ưu sẽ là nhiệm vụ bắt đầu sau thời điểm và có thời điểm kết thúc sớm nhất, gọi đó là nhiệm vụ . Và cứ như vậy chúng ta chọn tiếp các nhiệm vụ  Cài đặt giải thuật tham lam Tư tưởng của giải thuật tham lam có thể tóm tắt lại: Chọn là nhiệm vụ kết thúc sớm nhất Chọn là nhiệm vụ kết thúc sớm nhất bắt đầu sau khi kết thúc: Chọn là nhiệm vụ kết thúc sớm nhất bắt đầu sau khi kết thúc: … Cứ như vậy cho tới khi không còn nhiệm vụ nào chọn được nữa. Đến đây ta có thể thiết kế một giải thuật lặp:  Sắp xếp các nhiệm vụ theo thứ tự không giảm của thời điểm kết thúc  Khởi tạo thời điểm  Duyệt các nhiệm vụ theo danh sách đã sắp xếp (nhiệm vụ kết thúc sớm sẽ được xét trước nhiệm vụ kết thúc muộn), nếu xét đến nhiệm vụ có thì chọn ngay nhiệm vụ vào phương án tối ưu và cập nhật thành thời điểm kết thúc nhiệm vụ :

lOMoARcPSD|15547689 Chương I KỸ THUẬT THIẾT KẾ THUẬT TOÁN “It is not the strongest of the species that survives, nor the most intelligent that survives It is the one that is the most adaptable to change” Charles Darwin Chương giới thiệu số kỹ thuật quan trọng việc tiếp cận tốn tìm thuật tốn Các lớp thuật toán thảo luận chương là: Vét cạn (exhaustive search), Chia để trị (divide and conquer), Quy hoạch động (dynamic programming) Tham lam (greedy) Các tốn thực có mn hình mn vẻ, khơng thể đưa cách thức chung để tìm giải thuật cho toán Các phương pháp “chiến lược” kinh điển Khác với thuật toán cụ thể mà biết QuickSort, tìm kiếm nhị phân,…, vấn đề chương học theo kiểu “thuộc cài đặt”, khơng thể tìm thấy thuật tốn thư viện lập trình Chúng ta khảo sát vài tốn cụ thể học cách nghĩ, cách tiếp cận vấn đề, cách thiết kế giải thuật Từ rèn luyện kỹ linh hoạt giải toán thực tế lOMoARcPSD|15547689 Bài Liệt kê Có số toán thực tế yêu cầu rõ: tập đối tượng cho trước có đối tượng thoả mãn điều kiện định đối tượng Bài tốn gọi toán liệt kê hay toán duyệt Nếu ta biểu diễn đối tượng cần tìm dạng cấu hình biến số để giải toán liệt kê, cần phải xác định thuật tốn để theo xây dựng tất cấu hình quan tâm Có nhiều phương pháp liệt kê, chúng cần phải đáp ứng hai yêu cầu đây: Không lặp lại cấu hình  Khơng bỏ sót cấu hình  Trước nói thuật tốn liệt kê, giới thiệu số khái niệm bản: 1.1 Vài khái niệm 1.1.1 Thứ tự từ điển Nhắc lại quan hệ thứ tự toàn phần “nhỏ bằng” ký hiệu “” tập hợp , quan hệ hai thoả mãn bốn tính chất: Với  Tính phổ biến (Universality): Hoặc  Tính phản xạ (Reflexivity):  Tính phản đối xứng (Antisymmetry) : Nếu  , Tính bắc cầu (Transitivity): Nếu có Các quan hệ và tự suy từ quan hệ ; bắt buộc Trên dãy hữu hạn, người ta xác định quan hệ thứ tự: Xét phần “” Khi hai dãy độ dài , phần tử :  Hoặc hai dãy giống nhau:  Hoặc tồn số nguyên dương để có quan hệ thứ tự tồn Thứ tự gọi thứ tự từ điển (lexicographic order) dãy độ dài Khi hai dãy có số phần tử khác nhau, người ta xác định thứ tự từ điển Bằng cách thêm vào cuối dãy dãy nhau, coi phần tử phần tử đặc biệt gọi để độ dài nhỏ tất phần tử khác, ta lại đưa xác định thứ tự từ điển hai dãy độ dài Ví dụ: ( ( ) ) ( ( ) ) lOMoARcPSD|15547689 calculato computer Thứ tự từ điển quan hệ thứ tự toàn phần dãy 1.1.2 Chỉnh hợp, tổ hợp, hoán vị Cho tập hữu hạn gồm phần tử số tự nhiên Gọi tập số nguyên dương từ tới :  Chỉnh hợp lặp Một ánh xạ cho tương ứng phần tử gọi chỉnh hợp lặp chập Do tập hữu hạn ( ( ( ) ( ) phần tử) nên ánh xạ ( )), ta đồng phần tử ( ) xác định qua bảng giá trị với dãy giá trị ( ( ) ( ) dãy giá trị chỉnh hợp lặp chập Ví dụ Một ánh xạ , ( )) coi cho bởi: () tương ứng với tập ảnh ( ) chỉnh hợp lặp Số chỉnh hợp lặp chập tập phần tử  Chỉnh hợp không lặp Mỗi đơn ánh gọi chỉnh hợp khơng lặp chập Nói cách khác, chỉnh hợp không lặp chỉnh hợp lặp có phần tử khác đơi Ví dụ chỉnh hợp khơng lặp chập ( Số chỉnh hợp không lặp chập tập ) tập () phần tử (  Hoán vị Khi song ánh gọi hốn vị Nói cách khác hốn vị chỉnh hợp khơng lặp chập Ví dụ: ( ) ) hoán vị () lOMoARcPSD|15547689 Số hoán vị tập phần tử  Tổ hợp Mỗi tập gồm phần tử gọi tổ hợp chập Lấy tổ hợp chập khơng lặp chập , xét tất hốn vị nó, hốn vị chỉnh hợp Điều tức liệt kê tất chỉnh hợp không lặp chập tổ hợp chập tính Số tổ hợp chập tập lần Như xét mặt số lượng: phần tử ( ) ( Ta có cơng thức khai triển nhị thức: ( ) ) ∑( ) Vì số ( ) gọi hệ số nhị thức (binomial coefficient) thứ , bậc 1.2 Phương pháp sinh Phương pháp sinh áp dụng để giải toán liệt kê hai điều kiện sau thoả mãn:   Có thể xác định thứ tự tập cấu hình tổ hợp cần liệt kê Từ biết cấu hình cấu hình cuối theo thứ tự Xây dựng thuật tốn từ cấu hình chưa phải cấu hình cuối, sinh cấu hình 1.2.1 Mơ hình sinh Phương pháp sinh viết mơ hình chung: «Xây dựng cấu hình đầu tiên»; repeat «Đưa cấu hình có»; «Từ cấu hình có sinh cấu hình cịn»; until «hết cấu hình»; 1.2.2 Liệt kê dãy nhị phân độ dài Một dãy nhị phân độ dài dãy Có thể nhận thấy dãy nhị phân biểu diễn nhị phân giá trị nguyên ) Số dãy nhị phân độ dài , thứ tự từ điển ( ) ( ) ( dãy nhị phân độ dài tương đương với quan hệ thứ tự giá trị số mà chúng biểu diễn Vì vậy, liệt kê dãy nhị phân theo thứ tự từ điển nghĩa phải dãy nhị phân biểu diễn số nguyên theo thứ tự lOMoARcPSD|15547689 Ví dụ với ( ) , có dãy nhị phân độ dài liệt kê: 000 001 010 011 Theo thứ tự liệt kê, dãy ⏟ 100 101 110 111 dãy cuối ⏟ Nếu ta có dãy nhị phân độ dài , ta sinh dãy nhị phân cách cộng thêm (theo số có nhớ) vào dãy 10101111 + ──────── 10110000 Dựa vào tính chất phép cộng hai số nhị phân, cấu hình sinh từ cấu hình cách: xét từ cuối dãy lên đầu day (xet từ hàng đơn vị lên), tìm số gặp đầu tiên…   Nếu thấy thay số số đặt tất phần tử phía sau vị trí Nếu khơng thấy thì tồn dãy số 1, cấu hình cuối Input Số nguyên dương Output Các dãy nhị phân độ dài  Sample Input Sample Output 000 001 010 011 100 101 110 111 BINARYSTRINGS_GEN.PAS  Thuật toán sinh liệt kê dãy nhị phân {$MODE OBJFPC} program BinaryStringEnumeration; var x: AnsiString; n, i: Integer; begin ReadLn(n); SetLength(x, n); FillChar(x[1], n, '0'); //Cấu hình ban đầu x=00 lOMoARcPSD|15547689 repeat WriteLn(x); //Tìm số từ cuối dãy i := n; while (i > 0) and (x[i] = '1') Dec(i); u tìm thấ if i > then begin x[i] := '1'; i b ng số if i < n then t i n FillChar(x[i + 1], n - i, '0'); end else h ng tìm thấ số n o ừng Break; until False; end 1.2.3 Liệt kê tập có phần tử Ta lập chương trình liệt kê tập đien Ví dụ: {1, 2, 3} {1, 2, 4} {1, 2, 5} {1, 3, 4} {1, 3, 5} {1, 4, 5} {2, 3, 4} {2, 3, 5} {2, 4, 5} {3, 4, 5} phần tử tập , phần tử Tập (cấu hình khởi tạo) Tap cuoi cung (cấu hình kết thúc) et mot tap (giá trị lớn nhận) quát: giới hạn quy toán liệt kê Nếu xếp dãy theo thứ tự từ điển, ta nhận thấy: la , ta có nhận xét giới hạn n, , Còn tất nhiên, giới hạn (gia tri nho nhat co the nhan) Tư mot day theo thứ tự từ , có 10 tập con: Bài tốn liệt kê tập dãy phần tử tập la … Tổng đai dien cho mot tap cua S, neu tất phần tử x đạt tới giới hạn tren th x la cau h nh cuoi cung, khơng ta phải sinh dãy tăng dần thoả man: day mơi vừa đủ lớn dãy cũ theo nghĩa khơng có day k phần tử chen chúng thứ tự từ điển Ví dụ: Cấu hình có ( ) Các phần tử đạt tới giới hạn trên, nên để sinh cấu hình ta khơng thể sinh cách tăng phần tử số cac phan tư ( hình lên được, ta phải tăng lên đơn vị Được cấu ) Cấu hình lớn cấu hình trước chưa thoả mãn tính chất vừa đủ lớn Muốn t m cau h nh vưa đu lơn cau h nh cu, can co them thao tac: Thay cac gia tri giới hạn chung Tức là: lOMoARcPSD|15547689 Ta cấu hình lại nhận thấy ( cau h nh mơi ( ) cấu hình Tiep tuc vơi cau h nh nay, ta chưa đạt giới hạn trên, cần tăng ) Thuật toan sinh day từ day co Tìm từ cuối dãy lên đầu gặp phần tử  Nếu tìm thấy:    xây dựng sau: Tăng lên Đặt tất phần tử chưa đạt giới hạn giới hạn cua chung … Nếu khơng tìm thấy tức phần tử đạt giới hạn trên, cấu hình cuối Input Hai số nguyên dương Output ( ) Các tập k phần tử tập Sample Input  lên Sample {1, 2, {1, 2, {1, 2, {1, 3, {1, 3, {1, 4, {2, 3, {2, 3, {2, 4, {3, 4, Output 3} 4} 5} 4} 5} 5} 4} 5} 5} 5} SUBSETS_GEN.PAS  Thuật toán sinh liệt kê tập {$MODE OBJFPC} program SubSetEnumeration; const max = 100; var x: array[1 max] of Integer; n, k, i, j: Integer; begin ReadLn(n, k); for i := to k x[i] := i; repeat In cấu hình t i Write('{'); for i := to k begin h it o , , , phần tử lOMoARcPSD|15547689 Write(x[i]); if i < k then Write(', '); end; WriteLn('}'); u ệt từ cuối n tìm i ch a đ t giới h n tr n n – k + i i := k; while (i > 0) and (x[i] = n - k + i) Dec(i); if i > then u tìm thấ begin Inc(x[i]); ăng i n t i b ng giới h n ới ch ng for j := i + to k x[j] := x[j - 1] + 1; end else Break; until False; end 1.2.4 Liệt kê hoán vị Ta lập chương trình liệt kê hốn vị tập theo thứ tự từ điển Ví dụ với n = 3, có hốn vị: ( Mỗi hoán vị tập thứ tự từ điển, ta nhận thấy: Hoán vị cần liệt kê: ( ) ( ) ( ) ( ) biểu diễn dạng một dãy số Hoán vị cuối cần liệt kê: ( Bắt đầu từ hoán vị ( ) ( ) ( ) Theo ) ), ta sinh hốn vị cịn lại theo quy tắc: Hoán vị sinh phải hoán vị vừa đủ lớn hoán vị theo nghĩa khơng thể có hốn vị khác chen chúng thứ tự Giả sử hoán vị ( ), xét phần tử cuối cùng, ta thấy chúng xếp giảm dần, điều có nghĩa cho dù ta có hốn vị phần tử nào, ta hoán vị bé hoán vị Như ta phải xét đến thay giá trị khác Ta thay giá trị nào?, hoán vị nhỏ hơn, khơng thể có (phần tử sau không chọn vào giá trị mà phần tử trước chọn) Còn lại giá trị: 4, Vì cần hốn vị vừa đủ lớn nên ta chọn Còn giá trị lấy tập Cũng tính vừa đủ lớn nên ta tìm biểu diễn nhỏ số gán cho ( ) Vậy hoán vị ( ) tức Ta có nhận xét qua ví dụ này: Đoạn cuối hoán vị xếp giảm dần, số số nhỏ đoạn cuối giảm dần thoả mãn điều kiện lớn Nếu đảo ), đoạn cuối giá trị ta hoán vị ( xếp giảm dần Khi muốn biểu diễn nhỏ cho giá trị đoạn cuối ta cần đảo ngược đoạn cuối lOMoARcPSD|15547689 Trong trường hợp hoán vị ( thể coi hốn vị ( ) hốn vị ( ) Ta có ) có đoạn cuối giảm dần, đoạn cuối gồm phần tử (4) Thuật toán sinh hoán vị từ hốn vị xây dựng sau: ác định đoạn cuối giảm dần dài nhất, tìm số phần tử đứng liền trước đoạn cuối Điều đồng nghĩa với việc tìm từ vị trí sát cuối dãy lên đầu, gặp số thỏa mãn  Nếu tìm thấy số     Trong đoạn cuối giảm dần, tìm phần tử nhỏ vừa đủ lớn cuối giảm dần, điều thực cách tìm từ cuối dãy lên đầu gặp số thoả mãn Đảo giá trị (có thể dùng tìm kiếm nhị phân) Lật ngược thứ tự đoạn cuối giảm dần ( ), đoạn cuối trở thành tăng dần Nếu khơng tìm thấy tức tồn dãy giảm dần, cấu hình cuối Input Số nguyên dương Output Các hoán vị dãy (  Do đoạn ) Sample Input Sample (1, 2, (1, 3, (2, 1, (2, 3, (3, 1, (3, 2, Output 3) 2) 3) 1) 2) 1) PERMUTATIONS_GEN.PAS  Thuật toán sinh liệt kê hoán vị {$MODE OBJFPC} program PermutationEnumeration; const max = 100; var x: array[1 max] of Integer; n, i, k, l, h: Integer; //Thủ tục đảo giá trị hai tham bi n x, y procedure Swap(var x, y: Integer); var temp: Integer; begin temp := x; x := y; y := temp; end; begin ReadLn(n); lOMoARcPSD|15547689 for i := to n x[i] := i; repeat //In cấu hình t i Write('('); for i := to n begin Write(x[i]); if i < n then Write(', '); end; WriteLn(')'); //Sinh cấu hình k ti p //Tìm i số đứng tr ớc đo n cuối giảm dần i := n - 1; while (i > 0) and (x[i] > x[i + 1]) Dec(i); if i > then //N u tìm thấy begin //Tìm từ cuối dãy phần tử (x[k]) lớn i k := n; while x[k] < x[i] Dec(k); ảo giá trị x[k] x[i] Swap(x[k], x[i]); //Lật ng ợc thứ tự đo n cuối giảm dần, đo n cuối tr th nh tăng ần l := i + 1; h := n; while l < h begin Swap(x[l], x[h]); Inc(l); Dec(h); end; end else Break; //Cả dãy giảm dần, h t cấu hình until False; end Nhược điểm phương pháp sinh khơng thể sinh cấu hình thứ chưa , điều làm phương pháp sinh tính phổ dụng thuật có cấu hình thứ tốn duyệt hạn chế Hơn nữa, khơng phải cấu hình ban đầu lúc dễ tìm được, khơng phải kỹ thuật sinh cấu hình cho tốn đơn giản (Sinh chỉnh hợp khơng lặp chập theo thứ tự từ điển chẳng hạn) Ta sang chuyên mục sau nói đến phương pháp liệt kê có tính phổ dụng cao hơn, để giải tốn liệt kê phức tạp là: Thuật toán quay lui (Back tracking) 1.3 Thuật toán quay lui Thuật toán quay lui dùng để giải toán liệt kê cấu hình Thuật tốn làm việc theo cách:   Mỗi cấu hình xây dựng cách xây dựng phần tử Mỗi phần tử chọn cách thử tất khả Giả sử cấu hình cần liệt kê có dạng nhận, thử cho xét tất giá trị , thuật tốn quay lui xét tất giá trị nhận giá trị Với giá trị thử gán cho nhận, lại thử cho , thuật toán nhận giá trị Với giá lOMoARcPSD|15547689 ( ) ( ) Từ suy ( ) ( ) ( ) Giả sử phản chứng ( ) với tần suất ( ) Vậy ( ̂ ) chứng minh ( ) ( ) ( ( ) ( ) ) ( )) ( ) (4.3) ( ) không tối ưu, gọi ̂ tối ưu tập ký tự Xét ̂ , không anh-em (Bổ đề 4-4) Đưa ký tự vào nút cha chung ( ) cắt bỏ hai nút ̂ Ta ( ) ̂ tương ứng với mã phi tiền tố (̂ ) ( ) ( ))( ( ) hay ( ) ( ) giảm tính tổng qt, coi ( ( ) ( ̂) ( ) ( ) ( ) ( ) Trong đó: ( ) ( ) (do T khong toi ưu) ( ), mâu thuẫn với giả thiết tối ưu tập ký tự (4.4) Ta có điều phải Tính đắn thuật tốn Huffman suy trực tiếp từ Định lý 4-5: Để tìm tối ưu tập ký tự , ta tìm hai ký tự có tần suất thấp ký tự Sau thiết lập quan hệ cha-con ưu tập  Cài đặt có lực lượng nhập chúng lại thành , ta quy tốn con: Tìm tối phần tử Chúng ta cài đặt chương trình tìm mã phi tiền tố tối ưu để mã hóa ký tự xâu ký tự đầu vào Input Xâu ký tự Output Các từ mã tương ứng với ký tự lOMoARcPSD|15547689 Sample Input abcdefabcdefabcdeabcdabdadaaaaaaaa Sample Output = a 100 = c 101 = b 1100 = f 1101 = e 111 = d 30 14 20 a 11 c b f e d Hàng đợi ưu tiên nút chương trình tổ chức dạng Binary Heap Trên ( ) để vun nhánh Heap gốc thành đống điều kiện ta cài đặt thao tác hai nhánh (gốc ) đống Tại bước thuật toán Huffman, thay cài đặt chế “ra hai vào một”, ta sử dụng mẹo nhỏ: Lấy khỏi Heap ( ) nút , đọc nút gốc Heap đè lên nút  gốc Heap ( ), tạo nút cha chung ( ) thực vun đống từ gốc: HUFFMAN.PAS  Mã hóa Huffman {$MODE OBJFPC} program HuffmanCode; const MaxLeaves = 256; //Các ký tự kiểu AnsiChar, cần đổi ích th ớc n u dùng kiểu liệu khác type TNode = record //Cấu trúc nút Huffman f: Integer; c: AnsiChar; l, r: Pointer; end; PNode = ^TNode; //Kiểu trỏ tới nút THeap = record //Cấu trúc liệu Binary Heap items: array[1 MaxLeaves] of PNode; nItems: Integer; end; var s: AnsiString; //Xâu ký tự đầu vào Heap: THeap; H ng đợi u ti n TreeRoot: PNode; //Gốc Huffman bits: array[1 MaxLeaves] of Integer; //T o nút chứa tần suất fq, ký tự ch, hai nhánh left, right function NewNode(fq: Integer; ch: AnsiChar; left, right: PNode): PNode; begin New(Result); with Result^ , đưa nút vào lOMoARcPSD|15547689 begin f:= fq; c := ch; l := left; r := right; end; end; ịnh nghĩa quan hệ u ti n quan hệ < n t u ti n n t n u tần suất x nhỏ operator < (const x, y: TNode): Boolean; begin Result := x.f < y.f; end; //Vun nhánh Heap gốc r th nh đống procedure Heapify(r: Integer); var c: Integer; temp: PNode; begin with Heap begin temp := items[r]; repeat c := r * 2; if (c < nItems) and (items[c + 1]^ < items[c]^) then Inc(c); if (c > nItems) or not (items[c]^ < temp^) then Break; items[r] := items[c]; r := c; until False; items[r] := temp; end; end; // ọc nút gốc Heap function Get: PNode; begin with Heap Result := items[1]; end; //Lấy nút có tần suất nhỏ khỏi Heap function Pop: PNode; begin with Heap begin Result := items[1]; items[1] := items[nItems]; Dec(nItems); Heapify(1); end; end; //Thay nút gốc Heap b i node procedure UpdateRootHeap(node: PNode); begin with Heap lOMoARcPSD|15547689 begin items[1] := node; Heapify(1); end; end; procedure InitHeap; //Kh i t o Heap ban đầu chứa nút var c: AnsiChar; i: Integer; freq: array[AnsiChar] of Integer; begin FillDWord(freq, Length(freq), 0); for i := to Length(s) Inc(freq[s[i]]); m tần suất with Heap begin nItems := 0; for c := Low(AnsiChar) to High(AnsiChar) if freq[c] > then //Xét ký tự S begin Inc(nItems); items[nItems] := NewNode(freq[c], c, nil, nil); //T o nút chứa ký tự end; for i := nItems div downto Vun đống từ ới lên Heapify(i); end; end; procedure BuildTree; //Thuật toán Huffman var x, y, z: PNode; begin while Heap.nItems > //Chừng Heap nhiều phần tử begin x := Pop; //Lấy nút tần suất nhỏ khỏi Heap y := Get; ọc nút tần suất nhỏ ti p theo gốc Heap z := NewNode(x^.f + y^.f, #0, x, y); //T o nút z cha x y a z v o gốc Heap thực vun đống:  Ra x y, vào z UpdateRootHeap(z); end; TreeRoot := Heap.items[1]; //Giữ l i gốc Huffman end; //Thủ tục in từ mã Huffman gốc no e, epth độ sâu node procedure Traversal(node: PNode; depth: Integer); //Duyệt Huffman gốc node var i: Integer; begin if node^.l = nil then //N u node nút begin //In dãy bit biểu diễn ký tự for i := to depth Write(bits[i]); WriteLn(' = ', node^.c); Dispose(node); end else //N u node nút nhánh begin bits[depth + 1] := 0; //Các từ mã nhánh trái có bit ti p theo lOMoARcPSD|15547689 Traversal(node^.l, depth + 1); //Duyệt nhánh trái bits[depth + 1] := 1; //Các từ mã nhánh phải có bit ti p theo Traversal(node^.r, depth + 1); //Duyệt nhánh phải end; end; begin ReadLn(s); InitHeap; BuildTree; Traversal(TreeRoot, 0); end Xét riêng thuật toán Huffman thủ tục BuildTree Ta thấy số ký tự (số nút Huffman) vịng lặp while lặp lần Các lời gọi thủ tục bên vòng lặp ) Vậy thuật tốn Huffman có thời gian thực ( ) có thời gian thực ( Chúng ta khảo sát vài tốn mà đó, thuật tốn tham lam thiết kế dựa mơ hình chia để trị Thuật tốn tham lam cần đưa định tức bước lựa chọn Quyết định ảnh hưởng tới lựa chọn bước Chính vậy, đơi phân tích kỹ hai định liên tiếp cho ta tính chất nghiệm tối ưu từ xây dựng thuật tốn hiệu 4.3.4 Lịch xử lý lỗi Bạn người quản trị hệ thống thông tin, hệ thống lúc xảy lỗi đánh số từ tới Lỗi gây thiệt hại sau ngày để khắc phục lỗi cần ngày Tại thời điểm, bạn xử lý lỗi Hãy lên lịch trình xử lý lỗi cho tổng thiệt hại lỗi nhỏ Input   Dòng chứa số nguyên dương dòng tiếp theo, dòng chứa hai số nguyên dương Output Lịch xử lý lỗi Sample Input 3 Sample Output Bug 4: fixed time = Bug 2: fixed time = Bug 3: fixed time = Bug 1: fixed time = Minimum Damage = 44 1; 3; 6; 9; damage damage damage damage = = = = 24 2 lOMoARcPSD|15547689 Do lỗi ngưng gây thiệt hại khắc phục, nên dễ thấy lịch trình cần tìm phải có tính chất: Khi bắt tay vào xử lý lỗi, ta phải làm liên tục lỗi ) tương ứng với thứ tự khắc phục Tức ta cần tìm hốn vị dãy số ( lịch trình khắc phục lỗi ( Giả sử lịch trình ( ưu Ta lấy lịch trình khác hai lỗi liên tiếp: ) xử lý lỗi từ tới ) có cách đảo thứ tự xử lý lịch trình Ta nhận xét hai lỗi , thời điểm lỗi khác khắc phục giống hai lịch trình, có nghĩa khác biệt tổng thiệt hại lịch trình nằm thiệt hại hai lỗi Gọi thời điểm lỗi ( Nếu theo lịch trình Thiệt hại theo lịch trình thiệt hại ( ( lịch trình gây khắc phục (trên hai lịch trình ( Nếu theo lịch trình lịch trình tối ) ( ) ) Khi đó: ), thiệt hại hai lỗi ) ), thiệt hại hai lỗi ( ) lớn thiệt hại theo lịch trình gây là: (4.5) gây là: (4.6) (do tối ưu), tức không lớn thiệt hại Loại bỏ hạng tử giống cơng thức tính , ta có: (4.7) ( Vậy lịch trình Ngồi thấy ) tối ưu, phải thỏa mãn: , hai lịch trình sửa chữa thiệt hại Trong trường hợp này, việc sửa lỗi trước hay có mức độ trước cho phương án tối ưu Từ suy phương án tối ưu cần tìm phương án khắc phục lỗi theo thứ tự tăng dần tỉ số  () () Lời giải lặp đơn thuật toán xếp BUGFIXSCHEDULING.PAS  Lịch xử lý lỗi {$MODE OBJFPC} program BugFixes; const max = 100000; type TBug = record d, t: Integer; lOMoARcPSD|15547689 end; var bugs: array[1 max] of TBug; id: array[1 max] of Integer; n: Integer; procedure Enter; //Nhập liệu var i: Integer; begin ReadLn(n); for i := to n with bugs[i] begin ReadLn(d, t); id[i] := i; end; end; ịnh nghĩa i toán tử < lỗi Lỗi x gọi “nhỏ hơn” ỗi y n u x.t/x.d < y.t/y.d operator < (const x, y: TBug): Boolean; begin Result := x.t * y.d < y.t * x.d; end; //Sắp x p lỗi bugs[L H] theo quan hệ thứ tự “nhỏ hơn” định nghĩa procedure QuickSort(L, H: Integer); var i, j: Integer; pivot: Integer; begin if L >= H then Exit; i := L + Random(H - L + 1); pivot := id[i]; id[i] := id[L]; i := L; j := H; repeat while (bugs[pivot] < bugs[id[j]]) and (i < j) Dec(j); if i < j then begin id[i] := id[j]; Inc(i); end else Break; while (bugs[id[i]] < bugs[pivot]) and (i < j) Inc(i); if i < j then begin id[j] := id[i]; Dec(j); end else Break; until i = j; id[i] := pivot; QuickSort(L, i - 1); QuickSort(i + 1, H); end; procedure PrintResult; //In k t var i: Integer; Time, Damage: Integer; lOMoARcPSD|15547689 TotalDamage: Int64; begin Time := 0; TotalDamage := 0; for i := to n with bugs[id[i]] begin Time := Time + t; Damage := Time * d; WriteLn('Bug ', id[i], ': fixed time = ', Time, '; damage = ', Damage); Inc(TotalDamage, Damage); end; WriteLn('Minimum Damage = ', TotalDamage); end; begin Enter; QuickSort(1, n); PrintResult; end 4.3.5 Thuật toán Johnson  Bài toán Bài toán lập lịch gia công hai máy (Two-machine flow shop model): Có từ tới hai máy trước chuyển sang gia Một chi tiết cần gia công máy công máy Thời gian gia công chi tiết máy chi tiết đánh số và Tại thời điểm, máy gia cơng chi tiết Hãy lập lịch gia công chi tiết cho việc gia cơng tồn Input    chi tiết hồn thành thời gian sớm Dịng chứa số nguyên dương Dòng chứa Dòng chứa Output số nguyên dương số nguyên dương ( ) ( ) Lịch gia công tối ưu Sample Input 4 Sample Job 2: Job 1: Job 4: Job 3: Time = Output A[0, 1]; B[1, 3] A[1, 4]; B[4, 8] A[4, 8]; B[8, 11] A[8, 10]; B[11, 12] 12 10 11 12 2 4 lOMoARcPSD|15547689  Thuật toán Nhận xét tồn lịch gia công tối ưu mà chi tiết gia công máy theo thứ tự gia công máy hoạt động liên tục không nghỉ máy theo thứ tự Máy có khoảng thời gian chết chờ chi tiết từ máy Như ta cần tìm lịch gia cơng tối ưu dạng hốn vị dãy số ( ) Định lý 4-6 (Định lý Johnson) Một lịch gia công tối ưu cần thỏa mãn tính chất: Nếu chi tiết gia cơng trước chi tiết ( cơng chi tiết phương án ) ( chi tiết Định lý 4-7 ) Hơn ( ) ( ) việc đảo thứ tự gia phương án tối ưu trì tính tối ưu Xét quan hệ hai ngơi “nhỏ bằng” (ký hiệu ) xác định tập chi tiết Quan hệ định nghĩa sau: nếu:  Hoặc  Hoặc ( ( Khi quan hệ ) ) ( ( ) ) quan hệ thứ tự tồn phần (có đầy đủ tính chất: phổ biến, phản xạ, phản đối xứng, bắc cầu) Việc chứng minh cụ thể hai định lý dài dịng, bạn tham khảo tài liệu khác  Cài đặt Định lý 4-6 (Định lý Johnson) Định lý 4-7 thuật tốn Johnson cài đặt thuật toán xếp so sánh Tuy nhiên cài đặt thuật toán xếp so sánh, cần cài đặt phép toán : cho biết chi tiết bắt buộc phải gia công trước chi tiết  ( việt kiểm tra bất đẳng thức ( ) ), gia công chi tiết trước hay trước JOHNSONALG.PAS  Thuật toán Johnson {$MODE OBJFPC} program JohnsonAlgorithm; uses Math; const maxN = 100000; type TJob = record a, b: Integer; end; var jobs: array[1 maxN] of TJob; id: array[1 maxN] of Integer; ( ) Bởi ( ) lOMoARcPSD|15547689 n: Integer; procedure Enter; //Nhập liệu var i: Integer; begin ReadLn(n); for i := to n Read(jobs[i].a); ReadLn; for i := to n Read(jobs[i].b); for i := to n id[i] := i; end; ịnh nghĩa toán tử "phải m tr ớc": < Chi ti t x phải m tr ớc chi ti t y n u Min(x.a, y.b) < Min(y.a, x.b) operator < (const x, y: TJob): Boolean; //Toán tử dùng cho x p begin Result := Min(x.a, y.b) < Min(y.a, x.b); end; //Thuật toán QuickSort x p b ng số procedure QuickSort(L, H: Integer); var i, j: Integer; pivot: Integer; begin if L >= H then Exit; i := L + Random(H - L + 1); pivot := id[i]; id[i] := id[L]; i := L; j := H; repeat while (jobs[pivot] < jobs[id[j]]) and (i < j) Dec(j); if i < j then begin id[i] := id[j]; Inc(i); end else Break; while (jobs[id[i]] < jobs[pivot]) and (i < j) Inc(i); if i < j then begin id[j] := id[i]; Dec(j); end; else Break; until i = j; id[i] := pivot; QuickSort(L, i - 1); QuickSort(i + 1, H); end; procedure PrintResult; //In k t var StartA, StartB, FinishA, FinishB: Integer; i, j: Integer; begin StartA := 0; StartB := 0; for i := to n //Duyệt anh sách đ x p begin j := id[i]; lOMoARcPSD|15547689 FinishA := StartA + jobs[j].a; StartB := Max(StartB, FinishA); FinishB := StartB + jobs[j].b; WriteLn('Job ', j, ': ', 'A[', StartA, ', ', FinishA, ']; B[', StartB, ', ', FinishB, ']'); StartA := FinishA; StartB := FinishB; end; WriteLn('Time = ', FinishB); end; begin Enter; QuickSort(1, n); PrintResult; end Thời gian thực thuật toán Johnson cài đặt theo cách đánh giá thời gian )) Có thể cài đặt thực giải thuật xếp Ở ta dùng QuickSort (Trung bình ( thuật tốn Johnson theo cách khác để tận dụng thuật tốn xếp dãy khóa số, cách làm sau: Chia chi tiết làm hai nhóm: Nhóm chi tiết có gồm chi tiết có Sắp xếp chi tiết nhóm xếp chi tiết nhóm gồm theo thứ tự tăng dần theo thứ tự giảm dần xếp lại nhóm , nối hai danh sách Bài tập 4-1 Bạn người lập lịch giảng dạy cho điểm chuyên đề, chuyên đề thứ cần bắt đầu sau thời ] Mỗi chuyên đề thời gian diễn gia hoạt động kết thúc thời điểm : ( giảng dạy cần phòng học riêng Hãy xếp lịch giảng dạy cho số phịng học phải sử ) dụng Tìm thuật tốn ( Bài tập 4-2 Trên trục số cho điểm đen điểm trắng hoàn toàn phân biệt Hãy tìm đoạn, đoạn nối điểm đen với điểm trắng, cho khơng có hai đoạn thẳng có chung đầu ) mút tổng độ dài đoạn nhỏ Tìm thuật tốn ( Bài tập 4-3 ký tự Nếu ký tự xếp sẵn theo thứ tự không giảm tuần suất xây dựng Huffman thời gian ( ) cách Xét mã phi tiền tố tập sử dụng hai hàng đợi: Tạo nút chứa ký tự đẩy chúng vào hàng đợi theo thứ tự từ nút tần suất thấp tới nút tần suất cao Khởi tạo hàng đợi rỗng, lặp lại thao tác sau  lần: Lấy hai nút có tần suất thấp khỏi hàng đợi cách đánh giá phần tử đầu hai hàng đợi lOMoARcPSD|15547689  Tạo nút làm nút cha hai nút  Đẩy vào cuối hàng đợi với tần suất tổng tần suất Chứng minh tính đắn cài đặt thuật tốn Bài tập 4-4 Bài tốn xếp ba lơ (Knapsack) khảo sát chuyên đề kỹ thuật nhánh cận quy hoạch động toán 0/1 Knapsack: Với sản phẩm có hai trạng thái: chọn hay không chọn Chúng ta khảo sát toán Fractional Knapsack: Cho phép chọn phần sản phẩm: Với sản phẩm trọng lượng lượng giá trị , ta lấy phần trọng sản phẩm giá trị Chỉ hàm mục 1.4.3 cho kết tối ưu toán Fractional Knapsack Bài tập 4-5 Giáo sư lái xe chuyến hành trình “ uyên Việt” từ Cao Bằng tới Cà Mau dài km Dọc đường có trạm xăng trạm xăng thứ cách Cao Bằng đổ đầy km Bình xăng xe km Hãy xác định điểm dừng để đổ xăng trạm xăng cho số lần phải dừng đổ xăng hành trình Bài tập 4-6 Cho điểm thực trục số: số nguyên để phủ hết Bài tập 4-7 Bạn có điểm cho Hãy đoạn dạng [ ] với nhiệm vụ, nhiệm vụ cần làm đơn vị thời gian Nhiệm vụ thứ có thời điểm phải hồn thành (deadline) phải khoản phạt bạn hồn thành nhiệm vụ sau thời hạn Bạn thời điểm thời điểm thực nhiệm vụ Hãy lên lịch thực nhiệm vụ cho tổng số tiền bị phạt Bài tập 4-8  Một lần Tôn Tẫn đua ngựa với vua Tề Tôn Tẫn vua Tề người có từ tới , ngựa thứ Tơn Tẫn có tốc độ     Luật chơi sau: Có tất ngựa đánh số , ngựa thứ vua Tề có tốc độ cặp đua, cặp đua có ngựa Tôn Tẫn ngựa vua Tề Con ngựa phải tham gia cặp đua Trong cặp đua, ngựa tốc độ cao thắng, hai ngựa có tốc độ kết cặp đua hồ Trong cặp đua, ngựa bên thắng bên điểm, hồ thua khơng có điểm Hãy giúp Tơn Tẫn chọn ngựa đấu - Điểm vua Tề lớn cặp đua với vua Tề cho hiệu số: Điểm Tôn Tẫn lOMoARcPSD|15547689 Tài liệu tham khảo Adelson-Velsky, Georgy Maximovich and Landis, Yevgeniy Mikhailovich An algorithm for the organization of information In Proceedings of the USSR Academy of Sciences ( 1962), 263-266 Aho, Alfred V., Hopcroft, John E., and Ullman, Jeffrey D Data Structures and Algorithms Addison Wesley, 1983 Barahona, Francisco and Tardos, Éva Note on Weintraub's Minimum-Cost Circulation Algorithm SIAM Journal on Computing, 18, (1989), 579-583 Bayer, Rudolf Symmetric binary B-Trees: Data structure and maintenance algorithms Acta Informatica, (1972), 290–306 Bellman, Richard On a Routing Problem Quarterly of Applied Mathematics, 16, (1958), 87-90 Bentley, J.L Solution to Klee's rectangle problems Carnegie-Mellon university, Pittsburgh, PA, 1977 Coppersmith, Don and Winograd, Shmuel Matrix multiplication via arithmetic progressions In STOC '87: Proceedings of the nineteenth annual ACM symposium on Theory of computing (New York, United States 1987), ACM, 1-6 Cormen, Thomas H., Leiserson, Charles Eric, Rivest, Ronald Linn, and Stein, Clifford Introduction to Algorithms MIT Press, 2009 de Berg, Mark, Cheong, Otfried, van Kreveld, Marc, and Overmars, Mark Computational Geometry: Algorithms and Applications Springer-Verlag, 2008 10 Dijkstra, Edsger Wybe A note on two problems in connexion with graphs Numerische Mathematik, (1959), 269-271 11 Ding, Yuzheng and Weiss, Mark A Best case lower bounds for heapsort Computing, 49, (1993), 1-9 12 Dinic, E A Algorithm for solution of a problem of maximum flow in networks with power estimation Soviet Mathematics Doklady, 11, (1970), 1277-1280 13 Edmonds, Jack and Karp, Richard Manning Theoretical improvements in the algorithmic efficiency for network flow problems Journal of the ACM, 19 (1972), 248-264 lOMoARcPSD|15547689 14 Fenwick, Peter M A New Data Structure for Cumulative Frequency Tables Software: Practice and Experience, 24 (1994), 327-336 15 Fische, Johannes and Heun, Volker A New Succinct Representation of RMQ-Information and Improvements in the Enhanced Suffix Array Lecture Notes in Computer Science, 4614 (2007), 459-470 16 Floyd, Robert W Algorithm 245 - Treesort Communications of the ACM, 7, 12 (1964), 701 17 Ford, Lester Randolph and Fulkerson, Delbert Ray Flows in Networks Princeton University Press, 1962 18 Ford, Lester Randolph and Johnson, Selmer M A Tournament Problem The American Mathematical Monthly, 66, (1959), 387-389 19 Fredman, Michael Lawrence and Tarjan, Robert Endre Fibonacci heaps and their uses in improved network optimization algorithms Journal of the ACM, 34, (1987), 596-615 20 Goldberg, Andrew Vladislav Efficient graph algorithms for sequential and parallel computers MIT, 1987 21 Goldberg, Andrew Vladislav and Robert, Endre Tarjan Finding minimum-cost circulations by canceling negative cycles Journal of the ACM (JACM), 36, (1989), 873886 22 Hoare, Charles Antony Richard QuickSort Computer Journal, 5, (1962), 10-15 23 Hopcroft, John Edward and Karp, Richard Manning An n^(5/2) algorithm for maximum matchings in bipartite graphs SIAM Journal on Computing, 2, (1973), 225-231 24 Hopcroft, John Edward and Tarjan, Robert Endre Efficient algorithms for graph manipulation Communications of the ACM, 16, (1973), 372-378 25 Huffman, David Albert A Method for the Construction of Minimum-Redundancy Codes Proceedings of the Institute of Radio Engineers, 40, (1952), 1098-1101 26 Karatsuba, Anatolii Alexeevich and Ofman, Yu Multiplication of Many-Digital Numbers by Automatic Computers Doklady Akad Nauk SSSR, 145 (1962), 293-294 Translation in Physics-Doklady 7, 595-596, 1963 27 Karp, Manning Richard A characterization of the minimum cycle mean in a digraph Discrete Mathematics , 23, (1978), 309-311 lOMoARcPSD|15547689 28 Klein, Morton A Primal Method for Minimal Cost Flows with Applications to the Assignment and Transportation Problems Management Science, 14, (1967), 205-220 29 Kruskal, Joseph Bernard On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem Proceedings of the American Mathematical Society, 7, (1956), 48-50 30 Kuhn, Harold The Hungarian Method for the assignment problem 31 Lacey, Stephen and Box, Richard A fast, easy sort BYTE, 16, (1991), 315-ff 32 Musser, David R Introspective Sorting and Selection Algorithms Software: Practice and Experience, 27, (1997), 983 - 993 33 Nguyễn, Đức Nghĩa and Nguyễn, Tơ Thành Tốn Rời R c NXB Giáo Dục, 1999 34 Prim, Robert Clay Shortest connection networks and some generalizations Bell System Technical Journal, 36 (1957), 1389-1401 35 Seidel, Raimund G and Aragon, Cecilia R Randomized search trees Algorithmica, 16 (1996), 464-497 36 Shell, Donald L A high-speed sorting procedure Communications of the ACM, 2, (1959), 30-32 37 Sleator, Daniel Dominic and Tarjan, Robert Endre Self-Adjusting Binary Search Trees Journal of the ACM, 32, (1985), 652-686 38 Sokkalingam, P T., Ahuja, Ravindra K., and Orlin, James B New Polynomial-Time CycleCanceling Algorithms for Minimum Cost Flows Network, 36 (1996), 53-63 39 Stoer, Mechthild and Wagner, Frank A simple min-cut algorithm Journal of the ACM (JACM), 44, (1997), 585-591 40 Strassen, Volker Gaussian Elimination is not Optimal Numerische Mathematik, 13, (1969), 354-356 41 Tarjan, Robert Endre Depth first search and linear graph algorithms SIAM Journal on Computing, 1, (1972), 146-160 42 Vuillemin, Jean A data structure for manipulating priority queues Communications of the ACM, 21, (1978), 309-314 43 Williams, J.W.J Algorithm 232: Heapsort Communications of the ACM, 7, (1964), 347348 ... giải toán Knapsack cho đời nhiều thuật toán gần đúng, thuật toán tối ưu trường hợp đặt biệt (chẳng hạn thuật toán quy hoạch động số nguyên tương đối nhỏ) Dưới ta xây dựng thuật toán quay lui kỹ thuật. .. phổ dụng cao hơn, để giải toán liệt kê phức tạp là: Thuật tốn quay lui (Back tracking) 1.3 Thuật toán quay lui Thuật toán quay lui dùng để giải toán liệt kê cấu hình Thuật tốn làm việc theo cách:... ta khảo sát kỹ thuật nhánh cận áp dụng thuật toán quay lui để giải số toán tối ưu Kỹ thuật cịn áp dụng cho lớp tốn duyệt nói chung để hạn chế bớt khơng gian tìm kiếm Khi cài đặt thuật tốn quay

Ngày đăng: 12/12/2022, 10:39

Tài liệu cùng người dùng

Tài liệu liên quan