He he! Sorry! Tôi không để ý! Vừa trông bot vừa coi

! Để mà hiểu đoạn code này chắc bạn phải nghiên cứu lại lý thuyết đi thôi! Nếu tui nhớ không nhầm thì để in ra được cái hoán vị này thì phải dùng thuật toán tìm hoán vị kế. Chi tiết và cụ thể thì tui chịu. Đại loại là xây dựng một quy tắc nào đó cho các hoán vị này. Dựa trên quy tắc đó nếu cho ta một hoán vị nào đó thì ta sẽ chỉ ra hoán vị kế ngay sau nó.
Để dễ hiểu hơn ta đi lấy luôn bài tìm hoán vị của (A1,A2,...An) làm ví dụ vừa dễ hiểu lại vừa tổng quát! Trước hết ta tìm hiểu thế nào là hoán vị đứng trước, hoán vị đứng sau.
Ta xây dựng quy tắc so sánh hai hoán vị như sau:
+ So sánh hai phần tử đầu tiên của hai hoán vị với nhau
+ Nếu phần tử đầu tiên bằng nhau thì xét phần tử kế tiếp ngay sau nó.
+ Nếu thực hiện lại bước 2 nếu kết quả là bằng nhau.
+ Giả sử đến phần tử thứ i kết quả không còn bằng nhau nữa thì hoán vị nào có phần tử lớn hơn là hoán vị lớn hơn (hay là hoán vị đứng trước)
- Một phần tử lớn hơn phần tử khác nếu chỉ số của nó lớn hơn.
Lấy một vài ví dụ cho dễ hiểu:
+ So sánh 2 phần tử
- An > An-1
- A5 > A1
- An > An-1 > An-2 > An-3 .... A1
+ So sánh 2 hoán vị:
- A=(A5,A2,A3,A1,A4) > B=(A4,A5,A3,A2,A1) vì phần tử đầu tiên của A lớn hơn phần tử đầu tiên của hoán vị B là A4.
- A=(A5,A4,A3,A2,A1) > B=(A5,A4,A3,A1,A2) dễ thấy 3 phần tử đầu tiên là giống nhau nhưng phần tử thứ 4 của A là A2 lớn hơn phần thử thứ 4 của B là A1.
Từ quy tắc trên ta thấy hoán vị lớn nhất là hoán vị (An,An-1,An-2....A1)
hoán vị nhỏ nhất là hoán vị
(A1,A2,A3,....An)
Câu hỏi đặt ra là làm sao tìm được hoán vị kế tiếp nhỏ hơn ngay sau một hoán vị bất kì dựa vào quy tắc trên? Bây giờ ta sẽ đi tìm một hoán kế ngay sau một hoán vị bất kì!
Dễ thấy rằng một hoán vị bất kì bao giờ cũng thỏa mãn (.....,Ak1,Ak2,Ak3,....,Akm)
Trong đó Aki (i=1-->m) thuộc trong bộ (An,An-1,....A1) và thỏa mãn Aki-1>Aki với m lớn nhất có thể.
+ Lấy vài ví dụ cho dễ hiểu.
- (....A4,A1,A2,A3) m=3
- (....A9,A2,A4,A5,A8) m=4
- (....A4,A9,A2,A5,A1,A6) m=1
Rõ ràng hoán vị bất kì nào cũng có dạng trên, tối thiểu là m= 1.
Ta lại còn thấy m là lớn nhất thỏa mãn điều trên từ đây => ngay trước Ak1 là một Ax nào đó mà chắc chắn một điều là Ax > Ak1
Ta sẽ hình dung như sau:
Ax > Ak1 < Ak2 < Ak3 < .... Akm
Đằng trước của Ax là gì ta không cần quan tâm vì ta không thay đổi gì cả.
Ta làm một việc như sau. Thử chèn Ax vào dãy Ak1 < Ak2 ... < Akm mà vẫn đảm bảo tính tăng dần của dãy xem Ax nó nằm ở chỗ nào!
Rõ ràng Ax có thể nằm giữa Ak1 và Ak2 như thế này : Ak1 < Ax < Ak2
hoặc Ax nằm ở cuối dãy Akm < Ax
Không quan trọng ta giả sử nó nằm giữa 2 phần tử Aki và Aki+1 như thế ta sẽ có dãy như thế này:
Ak1 < Ak2 < Ak 3 < .... < Aki < Ax < Aki+1 < ... Akm
Ok! Hiển nhiên chẳng khó khăn gì khi xác định i nếu ta dùng vòng lặp. Khi có được i ta làm thao tác như sau. Đưa Aki lên đầu dãy như thế ta sẽ có dãy:
Aki > Ak1 < Ak2 < Ak3 <... < Ax < Aki+1 <... Akm
Và thêm một thao tác cuối cùng là giữ nguyên Aki vào đảo ngược dãy đằng sau thành giảm giần như sau:
Aki Akm > Akm-1 > .... > Aki+1> Ax > ....> Ak2 > Ak1
Đến đây ta để ý:
- Hoán vị (Aki,Akm,Akm-1,....Ax,...Ak2,Ak1) là hoán vị lớn nhất bắt đầu bằng Aki (đố ai tìm được hoán vị lớn hơn mà bắt đầu bằng Aki đấy)
- Hoán vị (Ax,Ak1,Ak2,Ak3...Ai,...Akm) là hoán vị nhỏ nhất bắt đầu bằng Ax (tìm được cái nào nhỏ hơn mà bắt đầu bằng Ax chết liền)
- Có tìm được hoán vị nào nằm giữa 2 hoán vị này không? Thử xem! Nếu có thì nó phải bắt đầu bằng Aki hoặc Ax bởi vì chẳng có cái Ax nào thỏa mãn Aki<Az<Ax trong bộ (Ax,Ak1,Ak2,...Akm) cả.
- Không có ai chen vào giữa thì hai thằng này là kế tiếp nhau rồi. Vậy là xong nhé!
Lấy vị dụ cụ thể cho dễ hiểu nào: Hoán vị của 9 số từ 1 --> 9 nhé!
Giả sử cho ta hoán vị: (4,2,1,8,6,3,5,7,9) dễ thấy ngay 3<5<7<9 ok! Nhưng 6>3<5<7<9! Chèn thằng 6 vào dãy 3<5<7<9 thành 3<5<6<7<9 . Lúc này Aki chính là thằng 5, đưa thằng 5 lên đầu dãy thành 5>3<6<7<9 và giữ nguyên 5 đảo dãy đằng sau thành: 5 9>7>6>3
Có ngay hoán vị sau thằng (4,2,1,8,6,3,5,7,9) là (4,2,1,8,6,5,9,7,6,3)
Bạn thử bỏ đoạn đầu giống nhau (4,2,1,8) và tìm thử xem có thằng nào chen nổi vào vữa hai thằng (6,3,5,7,9) và (5,9,7,6,3) ko?
Vậy nếu ta tìm đc thằng ngay đằng sao để làm gì? Thử nghĩ xem nếu ta cho hoán vị ban đầu là hoán vị lớn nhất. Và lặp tìm hoán vị kế cho đến khi ra được thằng nhỏ nhất có phải là liệt kê hết được hoán vị của n phần tử ko? Đây chính là cơ sở để viết đoạn code này!
Hàm h(1,v) chính là nạp hoán vị lớn nhất vào và cứ thể tìm hoán vị kết sau nó cho đến khi hết!