Thuật toán Steinhauss–Johnson–Trotter

Một phần của tài liệu Bài giảng môn tổ hợp (Trang 69 - 85)

Ý tưởng: sinh các hoán vị trong đó hai hoán vị liên tiếp chỉ khác nhau bởi một phép đổi chỗ kế tiếp.

Ví dụ, các hoán vị của 3 phần tử abcđược sinh như sau:

abc→bac→bca bca→cba→cab cab→acb→abc

Thuật toán Steinhauss–Johnson–Trotter

Thuật toán Steinhauss–Johnson–Trotter được đề xuất bởi Hugo Steinhaus, Selmer M. Johnson và Hale F. Trotter trong các tài liệu

S. M. Johnson, “Generation of permutations by adjacent

transposition,” Mathematics of Computation, vol. 17, pp. 282–285, 1963

H. Steinhaus, One hundred problems in elementary mathematics. New York, 1964

H. F. Trotter, “Algorithm 115: Perm,” Communications of the ACM, vol. 8, no. 5, pp. 434–435, 1964

Thuật toán này còn được gọi là thuật toán Johnson–Trotter hoặc thuật toán đổi chỗ đơn giản (“plain changes”).

Thuật toán Steinhauss–Johnson–Trotter

Thực ra thuật toán này đã được phát minh từ thế kỉ thứ 17 bởi những người thợ kéo chuông nhà thờ ở Anh.

Thuật toán này là thuật toán tốt và rất hiệu quả.

Tương tự như thuật toán đệ quy, ưu điểm lớn nhất là ta có thể tăng tốc các tính toán kế tiếp nhau vì hai hoán vị liên tiếp chỉ khác nhau 2 vị trí,n−2 vị trí còn lại là giống nhau.

Thuật toán Steinhauss–Johnson–Trotter

Cấu trúc đệ quy: Chuỗi các hoán vị của nphần tử có thể được sinh

từ chuỗi các hoán vị của n−1phần tử bằng cách đặt phần tử thứ n

vào từng vị trí của các chuỗi hoán vị đó theo cách sau:

Nếu hoán vị của n−1phần tử là mộthoán vị chẵn thì phần tử thứ

nđược đặt vào mọi vị trí có thể theo thứ tự giảm dần, từ n tới1; Nếu khi hoán vị củan−1 phần tử là một hoán vị lẻ thì phần tử thứ nđược đặt vào mọi vị trí có thể theo thứ tự tăng dần, từ1 tới

Thuật toán Steinhauss–Johnson–Trotter

Ta giả sử các phần tử là các số nguyên dương. Từ hoán vị với một phần tử 1ta có thể đặt 2vào mọi vị trí có thể theo thứ tự giảm dần để lập các hoán vị của hai phần tử:

1 2

2 1

Sau đó, ta có thể đặt phần tử 3vào một trong các vị trí khác nhau của các hoán vị này, theo thứ tự giảm dần với hoán vị(1,2) và theo thứ tự tăng dần với hoán vị(2,1):

1 2 31 3 2 1 3 2 3 1 2 3 2 1 2 3 1 2 1 3

Thuật toán Steinhauss–Johnson–Trotter

Ở bước tiếp theo, phần tử4 sẽ lần lượt được đặt vào hoán vị

(1,2,3) theo thứ tự giảm dần, đặt vào hoán vị (1,3,2) theo thứ tự tăng dần, đặt vào hoán vị (3,1,2) theo thứ tự giảm dần. . . .

Việc đặt phần tử cứ được tiếp tục theo cách như vậy, luân phiên giữa thứ tự tăng dần và giảm dần, áp dụng cho các giá trị nlớn bất kì.

Như vậy, mỗi hoán vị đứng sau chỉ khác với hoán vị trước nó hoặc bởi sự di chuyển của phần tử thứ n, hoặc bởi sự thay đổi của hai phần tử nhỏ hơnn trong dãy hoán vị gồmn−1phần tử trước đó. Trong cả hai trường hợp này, sự khác nhau giữa hai hoán vị trước và sau chỉ là sự hoán đổi vị trí của hai phần tử kề nhau.

Thuật toán Steinhauss–Johnson–Trotter

Ở bước tiếp theo, phần tử4 sẽ lần lượt được đặt vào hoán vị

(1,2,3) theo thứ tự giảm dần, đặt vào hoán vị (1,3,2) theo thứ tự tăng dần, đặt vào hoán vị (3,1,2) theo thứ tự giảm dần. . . . Việc đặt phần tử cứ được tiếp tục theo cách như vậy, luân phiên giữa thứ tự tăng dần và giảm dần, áp dụng cho các giá trị nlớn bất kì.

Như vậy, mỗi hoán vị đứng sau chỉ khác với hoán vị trước nó hoặc bởi sự di chuyển của phần tử thứ n, hoặc bởi sự thay đổi của hai phần tử nhỏ hơnn trong dãy hoán vị gồmn−1phần tử trước đó. Trong cả hai trường hợp này, sự khác nhau giữa hai hoán vị trước và sau chỉ là sự hoán đổi vị trí của hai phần tử kề nhau.

Thuật toán Steinhauss–Johnson–Trotter

Ở bước tiếp theo, phần tử4 sẽ lần lượt được đặt vào hoán vị

(1,2,3) theo thứ tự giảm dần, đặt vào hoán vị (1,3,2) theo thứ tự tăng dần, đặt vào hoán vị (3,1,2) theo thứ tự giảm dần. . . . Việc đặt phần tử cứ được tiếp tục theo cách như vậy, luân phiên giữa thứ tự tăng dần và giảm dần, áp dụng cho các giá trị nlớn bất kì.

Như vậy, mỗi hoán vị đứng sau chỉ khác với hoán vị trước nó hoặc bởi sự di chuyển của phần tử thứ n, hoặc bởi sự thay đổi của hai phần tử nhỏ hơnn trong dãy hoán vị gồmn−1phần tử trước đó.

Trong cả hai trường hợp này, sự khác nhau giữa hai hoán vị trước và sau chỉ là sự hoán đổi vị trí của hai phần tử kề nhau.

Thuật toán Steinhauss–Johnson–Trotter

Ở bước tiếp theo, phần tử4 sẽ lần lượt được đặt vào hoán vị

(1,2,3) theo thứ tự giảm dần, đặt vào hoán vị (1,3,2) theo thứ tự tăng dần, đặt vào hoán vị (3,1,2) theo thứ tự giảm dần. . . . Việc đặt phần tử cứ được tiếp tục theo cách như vậy, luân phiên giữa thứ tự tăng dần và giảm dần, áp dụng cho các giá trị nlớn bất kì.

Như vậy, mỗi hoán vị đứng sau chỉ khác với hoán vị trước nó hoặc bởi sự di chuyển của phần tử thứ n, hoặc bởi sự thay đổi của hai phần tử nhỏ hơnn trong dãy hoán vị gồmn−1phần tử trước đó. Trong cả hai trường hợp này, sự khác nhau giữa hai hoán vị trước và sau chỉ là sự hoán đổi vị trí của hai phần tử kề nhau.

Thuật toán Steinhauss–Johnson–Trotter

Ta có thể viết một hàm đệ quy đơn giản để cài đặt thuật toán. Nhưng hàm đó là không hiệu quả vì nó có độ phức tạp thời gian và không gian rất lớn:

Các cấu trúc hoán vị trung gian bị lặp lại nhiều lần;

Để sinh được các hoán vị cấpnthì cần sinh trước các hoán vị cấp n−1.

Vì vậy, ta sẽ cài đặt thuật toán bằng phương pháp lặp thay vì đệ quy.

Thuật toán Steinhauss–Johnson–Trotter

Steinhauss, Johnson và Trotter độc lập nhau đề xuất thuật toán sinh các hoán vị củanphần tử bằng phương pháp hoán đổi kế tiếp. Mỗi phần tử (số nguyên) trong dãy hoán vị được gắn thêm thông tin về hướng di chuyển của nó.

Hướng di chuyển có thể nhận một trong hai giá trị logic ứng với “trái” và “phải”.

Nếu hướng di chuyển của số klà sang trái thì ta viết hk; nếu hướng của nó là sang phải thì ta viếtki.

Thuật toán Steinhauss–Johnson–Trotter

Một số nguyên có hướng được gọi là di động nếu nó lớn hơn số bên cạnh theo chiều di chuyển của nó.

Thuật toán Steinhauss–Johnson–Trotter:

1 Khởi tạo hoán vị đầu tiên là h1 h2 · · · hn;

2 Chừng nào còn tồn tại một số nguyên di động:

Tìm số nguyên di độngklớn nhất;

Hoán đổikvới số nguyên bên cạnh nó theo chiều di chuyển của k; Đảo chiều di chuyển của mọi số nguyên lớn hơnk.

Các hoán vị của ba phần tử được sinh bởi thuật toán này:

        h1 h2 h3 h1 h3 h2 h3 h1 h2 3i h2 h1 h2 3i h1 h2 h1 3i        

Thuật toán Steinhauss–Johnson–Trotter

Các hoán vị của 4 phần tử được sinh bởi thuật toán này như sau:

            h1 h2 h3 h4 h1 h2 h4 h3 h1 h4 h2 h3 h4 h1 h2 h3 4i h1 h3 h2 h1 4i h3 h2 h1 h3 4i h2 h1 h3 h2 4i                         h3 h1 h2 h4 h3 h1 h4 h2 h3 h4 h1 h2 h4 h3 h1 h2 4i 3i h2 h1 3i 4i h2 h1 3i h2 4i h1 3i h2 h1 4i                         h2 3i h1 h4 h2 3i h4 h1 h2 h4 3i h1 h4 h2 3i h1 4i h2 h1 3i h2 4i h1 3i h2 h1 4i 3i h2 h1 3i 4i            

Bài tập

Bài tập 9. Viết chương trình cài đặt thuật toán Steinhauss–Johnson–Trotter.

Input: Một số tự nhiênn <20.

Output: Mọi hoán vị của dãy 1..n.

Bài tập 10. Sử dụng chương trình tìm dấu của một hoán vị đã viết ở Bài tập 2 để kiểm tra xem các hoán vị thu được từ chương trình cài đặt thuật toán Steinhauss–Johnson–Trotter có đổi dấu luân phiên hay không.

Input: Các hoán vị sinh bởi thuật toán S–J–T.

Bài tập

Bài tập 11. (Bài toán xếp hậu) Cho một bàn cờ vua kích thước n×n. Hãy tìm mọi cách xếpnquân hậu trên bàn cờ sao cho không quân nào không chế được quân khác.

Ví dụ, vớin= 4, ta có một cách xếp hậu như sau:

1 •

2 •

3 •

4 •

Mỗi cột của bàn cờ chỉ có thể chứa một quân hậu nên mỗi cách xếp hậu tương ứng với một dãy số nguyên a[1..n], trong đó a[j] =i

nếu hậu thứ j được đặt ở hàng thứi.

Cách xếp hậu như trên ứng với dãy a[1..4] = (3,1,4,2). Đây là một hoán vị của dãy (1,2,3,4).

Quy việc tìm cách xếp hậu về việc tìm hoán vị của dãy (1,2, . . . , n) thỏa mãn điều kiện của bài toán.

Bài tập

Bài tập 11. (Bài toán xếp hậu) Cho một bàn cờ vua kích thước n×n. Hãy tìm mọi cách xếpnquân hậu trên bàn cờ sao cho không quân nào không chế được quân khác.

Ví dụ, vớin= 4, ta có một cách xếp hậu như sau:

1 •

2 •

3 •

4 •

Mỗi cột của bàn cờ chỉ có thể chứa một quân hậu nên mỗi cách xếp hậu tương ứng với một dãy số nguyên a[1..n], trong đó a[j] =i

nếu hậu thứ j được đặt ở hàng thứi.

Cách xếp hậu như trên ứng với dãy a[1..4] = (3,1,4,2). Đây là một hoán vị của dãy (1,2,3,4).

Quy việc tìm cách xếp hậu về việc tìm hoán vị của dãy

Tóm lược

Các nội dung chính của bài giảng:

Ba bài toán sắp xếp, tính số cách sắp xếp tương ứng

Các khái niệm cơ bản: hoán vị, nghịch thế, tính chẵn lẻ của hoán vị Bốn thuật toán sinh mọi hoán vị của nphần tử:

1 Thuật toán quay lui

2 Thuật toán đệ quy

3 Thuật toán Heap

4 Thuật toán Steinhauss–Johnson–Trotter

Một phần của tài liệu Bài giảng môn tổ hợp (Trang 69 - 85)

Tải bản đầy đủ (PDF)

(85 trang)