Thuật toán Tháp Hà Nội: Python, C++ Code

⚡ Tóm tắt thông minh

Thuật toán Tháp Hà Nội là một bài toán xếp hình đệ quy kinh điển, di chuyển một chồng đĩa giữa ba chốt mà không bao giờ đặt đĩa lớn hơn lên trên đĩa nhỏ hơn, minh họa rõ ràng nguyên tắc chia để trị.

  • 🗼 Cách thiết lập câu đố: Ba chốt và n đĩa được xếp chồng lên nhau theo thứ tự giảm dần kích thước trên chốt nguồn, chờ được di chuyển đến chốt đích thông qua một chốt hỗ trợ.
  • 📜 Quy tắc: Chỉ có một đĩa di chuyển tại một thời điểm, chỉ đĩa trên cùng của mỗi chốt mới có thể di chuyển, và đĩa lớn hơn không thể đặt lên đĩa nhỏ hơn.
  • 🔁 Ý tưởng đệ quy: Di chuyển n-1 đĩa đến vị trí hỗ trợ, di chuyển đĩa lớn nhất đến vị trí đích, sau đó di chuyển n-1 đĩa từ vị trí hỗ trợ đến vị trí đích.
  • 🇧🇷 Độ phức tạp về thời gian: Giải n đĩa yêu cầu 2^n – 1 bước di chuyển, dẫn đến độ phức tạp thời gian O(2^n) theo cấp số mũ, tăng rất nhanh khi n tăng lên.
  • 🧠 Không gian phức tạp: Ngăn xếp đệ quy chứa tối đa n khung cùng một lúc, do đó độ phức tạp không gian của giải pháp đệ quy là O(n).
  • 🛠️ Ứng dụng Giảng dạy về đệ quy, các lược đồ xoay vòng sao lưu, di chuyển dữ liệu dựa trên ngăn xếp, lập trình trình tự trong robot và hiểu về thiết kế thuật toán chia để trị.

Thuật toán Tháp Hà Nội

Tháp Hà Nội là gì?

Tháp Hà Nội là một trò chơi giải đố toán học gồm ba thanh và một chồng đĩa có kích thước giảm dần được đặt chồng lên nhau. Nó còn được biết đến với tên gọi Tháp Brahma hoặc Tháp Lucas, vì nhà toán học người Pháp Edouard Lucas đã giới thiệu nó vào năm 1883. Trò chơi giải đố này dựa trên những truyền thuyết về việc di chuyển những chiếc đĩa vàng giữa ba thanh.

Câu đố này có ba thanh và một số lượng đĩa xếp chồng lên nhau có thể thay đổi. Các thanh được sắp xếp thành các tháp tuần hoàn, do đó các đĩa lớn hơn được xếp ở dưới cùng và các đĩa nhỏ hơn được xếp ở trên cùng.

Ban đầu, chúng ta được cho ba cái chốt hoặc thanh. Một trong số đó (chốt A trong ví dụ) có tất cả các đĩa được xếp chồng lên nhau. Mục tiêu là di chuyển toàn bộ chồng đĩa từ thanh này (A) sang thanh khác (C) trong khi tuân theo một vài quy tắc cụ thể.

Đây là cách thiết lập ban đầu của câu đố:

Bài toán Tháp Hà Nội

Bài toán Tháp Hà Nội

Và đây là mục tiêu cuối cùng:

Tháp Hà Nội

Quy định của Tháp Hà Nội

Dưới đây là những quy tắc cơ bản của trò chơi Tháp Hà Nội:

  • Ở trạng thái ban đầu của câu đố, tất cả các đĩa đều được xếp chồng lên thanh thứ nhất.
  • Ở trạng thái cuối cùng, tất cả các đĩa từ thanh thứ nhất được xếp chồng lên thanh thứ hai hoặc thanh thứ ba.
  • Tại một thời điểm, chỉ có một đĩa có thể di chuyển từ thanh này sang thanh khác.
  • Chỉ có đĩa trên cùng trên thanh mới có thể di chuyển được.
  • Không thể đặt một đĩa lên trên một đĩa nhỏ hơn.

Truyền thuyết gốc kể về việc di chuyển 64 quân cờ. Các thầy tu chỉ được phép di chuyển từng quân cờ một theo luật chơi. Theo truyền thuyết, có một lời tiên tri rằng thế giới sẽ diệt vong nếu họ hoàn thành được việc này. Trong phần độ phức tạp về thời gian, chúng ta sẽ chứng minh rằng một tháp Hà Nội với n quân cờ cần 2^n – 1 nước đi.

Vì vậy, nếu các thầy tế cần 1 giây để di chuyển một chiếc đĩa, tổng thời gian để giải câu đố sẽ là 2^64 – 1 giây, hay xấp xỉ 584,942,417,356 năm, 26 ngày, 7 giờ và 15 giây.

Thuật toán Tháp Hà Nội

Cách phổ biến nhất để giải Tháp Hà Nội là sử dụng thuật toán đệ quy. Đầu tiên, ta chọn hai thanh làm điểm xuất phát và điểm đích; thanh còn lại đóng vai trò là thanh phụ trợ.

Dưới đây là các bước giải câu đố Tháp Hà Nội:

  • Di chuyển n-1 đĩa trên cùng từ chốt nguồn sang chốt trợ giúp.
  • Di chuyển đĩa thứ n từ vị trí nguồn đến vị trí đích.
  • Di chuyển n-1 đĩa còn lại từ vị trí hỗ trợ đến vị trí đích.

Lưu ý: Nếu chỉ có một ổ đĩa duy nhất, chúng ta có thể di chuyển nó trực tiếp từ nguồn đến đích.

Cách giải câu đố Tháp Hà Nội

Chúng ta hãy minh họa thuật toán cho ba đĩa. Coi chốt A là nguồn, chốt B là bộ hỗ trợ và chốt C là đích đến.

Bước 1) Ban đầu, tất cả các đĩa được xếp chồng lên nhau trên cọc A.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = Cọc A, Đích = Cọc C, Cọc hỗ trợ = Cọc B.

Bây giờ, chúng ta cần di chuyển n-1 đĩa hàng đầu từ nguồn sang trợ giúp.

Lưu ý: Mặc dù chúng ta chỉ có thể di chuyển một đĩa tại một thời điểm, bước này giúp giảm bài toán 3 đĩa xuống còn bài toán 2 đĩa, được xử lý bằng một lời gọi đệ quy.

Bước 2) Khi thực hiện cuộc gọi đệ quy từ chốt A với chốt B là đích đến, ta sử dụng chốt C làm công cụ hỗ trợ.

Hãy lưu ý rằng chúng ta quay lại giai đoạn một của bài toán Tháp Hà Nội, nhưng lần này là với hai đĩa. Chúng ta di chuyển n-1 (tức là một) đĩa từ nguồn đến đĩa hỗ trợ, đĩa hỗ trợ này sẽ di chuyển đĩa nhỏ nhất từ ​​cọc A đến cọc C.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc A, Đích = cọc B, Cọc hỗ trợ = cọc C.

Bước 3) Theo thuật toán, đĩa thứ n (thứ 2) hiện được chuyển đến đích, cọc B.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc A, Đích = cọc B, Cọc hỗ trợ = cọc C.

Bước 4) Bây giờ, chúng ta di chuyển đĩa n-1 (đĩa thứ nhất) từ chốt hỗ trợ C đến chốt đích B, theo giai đoạn thứ ba của thuật toán.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc A, Đích = cọc B, Cọc hỗ trợ = cọc C.

Bước 5) Sau khi hoàn thành lời gọi đệ quy, chúng ta quay trở lại thiết lập trước đó ở giai đoạn đầu tiên của thuật toán.

Bước 6) Ở giai đoạn thứ hai, chúng ta di chuyển đĩa 3 từ điểm neo nguồn A đến điểm neo đích C.

Ở giai đoạn này: Nguồn = cọc A, Đích = cọc C, Cọc hỗ trợ = cọc B.

Bước 7) Nhiệm vụ tiếp theo là di chuyển các đĩa còn lại từ vị trí hỗ trợ (cọc B) đến vị trí đích (cọc C). Lần này, chúng ta sẽ sử dụng vị trí nguồn ban đầu (cọc A) làm vị trí hỗ trợ.

Giải câu đố Tháp Hà Nội

Bước 8) Vì chúng ta không thể di chuyển hai đĩa cùng một lúc, nên chúng ta thực hiện một lời gọi đệ quy cho đĩa 1. Theo như chúng ta... thuật toánĐiểm đến trong bước này là cọc A.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc B, Đích = cọc A, Cọc hỗ trợ = cọc C.

Bước 9) Lời gọi đệ quy của chúng ta đã hoàn tất. Bây giờ chúng ta di chuyển đĩa 2 từ vị trí nguồn đến vị trí đích.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc B, Đích = cọc C, Cọc hỗ trợ = cọc A.

Bước 10) Chúng ta hoàn tất bằng cách di chuyển đĩa n-1 còn lại (đĩa 1) từ máy hỗ trợ sang máy đích.

Giải câu đố Tháp Hà Nội

Ở giai đoạn này: Nguồn = cọc A, Đích = cọc C, Cọc hỗ trợ = cọc B.

Biệt danh Code cho Tháp Hà Nội

START
Procedure Tower_Of_Hanoi(disk, source, dest, helper)
    IF disk == 1 THEN
        move disk from source to dest
    ELSE
        Tower_Of_Hanoi(disk - 1, source, helper, dest)
        move disk from source to dest
        Tower_Of_Hanoi(disk - 1, helper, dest, source)
    END IF
END Procedure

Mã chương trình trong C++

#include <bits/stdc++.h>
using namespace std;
void tower_of_hanoi(int num, string source, string dest, string helper) {
    if (num == 1) {
        cout << " Move disk 1 from tower " << source << " to tower " << dest << endl;
        return;
    }
    tower_of_hanoi(num - 1, source, helper, dest);
    cout << " Move disk " << num << " from tower " << source << " to tower " << dest << endl;
    tower_of_hanoi(num - 1, helper, dest, source);
}
int main() {
    int num;
    cin >> num;
    printf("The sequence of moves :\n");
    tower_of_hanoi(num, "I", "III", "II");
    return 0;
}

Đầu ra:

3
The sequence of moves :
Move disk 1 from tower I to tower III
Move disk 2 from tower I to tower II
Move disk 1 from tower III to tower II
Move disk 3 from tower I to tower III
Move disk 1 from tower II to tower I
Move disk 2 from tower II to tower III
Move disk 1 from tower I to tower III

Mã chương trình trong Python

def tower_of_hanoi(n, source, destination, helper):
    if n == 1:
        print("Move disk 1 from peg", source, "to peg", destination)
        return
    tower_of_hanoi(n - 1, source, helper, destination)
    print("Move disk", n, "from peg", source, "to peg", destination)
    tower_of_hanoi(n - 1, helper, destination, source)
# n = number of disks
n = 3
tower_of_hanoi(n, 'A', 'B', 'C')

Đầu ra:

Move disk 1 from peg A to peg B
Move disk 2 from peg A to peg C
Move disk 1 from peg B to peg C
Move disk 3 from peg A to peg B
Move disk 1 from peg C to peg A
Move disk 2 from peg C to peg B
Move disk 1 from peg A to peg B

Sự phức tạp của Tháp Hà Nội

Dưới đây là độ phức tạp về thời gian và không gian của Tháp Hà Nội:

1) Độ phức tạp về thời gian:

Nhìn lại thuật toán, chúng ta thực hiện một lời gọi đệ quy cho (n-1) đĩa hai lần mỗi lần gọi. Mỗi (n-1) lời gọi đệ quy được chia thành ((n-1)-1) lời gọi đệ quy, và cứ thế tiếp tục cho đến khi chúng ta đạt đến trường hợp cơ sở một đĩa.

Dành cho ba đĩa:

  • Đĩa 3 gọi hàm đệ quy của đĩa 2 hai lần.
  • Đĩa 2 gọi hàm đệ quy của đĩa 1 hai lần.
  • Đĩa 1 di chuyển với thời gian không đổi, cho phép có đủ thời gian để giải bài toán cho ba đĩa.

Được biểu diễn dưới dạng công thức lặp lại:

= 2 × (Thời gian giải cho hai đĩa) + thời gian không đổi để di chuyển đĩa 3

= 2 × (2 × thời gian giải cho một đĩa + thời gian không đổi để di chuyển đĩa 2) + thời gian không đổi để di chuyển đĩa 3

= (2 × 2) × thời gian không đổi để di chuyển đĩa 1 + 2 × thời gian không đổi để di chuyển đĩa 2 + thời gian không đổi để di chuyển đĩa 3

Với n đĩa, điều này trở thành:

2n-1 × thời gian không đổi để di chuyển đĩa 1 + 2n-2 × thời gian không đổi để di chuyển đĩa 2 + ….

Cấp số nhân này có tổng là O(2)n – 1), được đơn giản hóa thành O(2n), độ phức tạp thời gian theo cấp số mũ.

2) Độ phức tạp về không gian:

Độ phức tạp không gian của Tháp Hà Nội là O(n). Đệ quy sử dụng ngăn xếp gọi hàm, và độ sâu tối đa của ngăn xếp bằng n, số đĩa. Đó là lý do tại sao độ phức tạp không gian là O(n).

Câu Hỏi Thường Gặp

Thuật toán Tháp Hà Nội là một quy trình đệ quy di chuyển n đĩa từ một cọc nguồn đến một cọc đích bằng cách sử dụng một cọc hỗ trợ, đồng thời không bao giờ đặt một đĩa lớn hơn lên trên một đĩa nhỏ hơn.

Số bước di chuyển tối thiểu cho n đĩa là 2^n – 1. Ba đĩa cần 7 bước, bốn đĩa cần 15 bước, và mười đĩa cần 1,023 bước.

Độ phức tạp thời gian là O(2^n) vì mỗi đĩa bổ sung làm tăng gấp đôi công việc. Công thức truy hồi T(n) = 2T(n-1) + 1 giải ra 2^n – 1, là hàm mũ.

Độ phức tạp không gian là O(n) vì ngăn xếp gọi đệ quy chứa một khung cho mỗi đĩa đang được xử lý. Độ sâu đệ quy tối đa đạt tới n, do đó bộ nhớ phụ trợ cần thiết tỷ lệ thuận với số lượng đĩa.

Đúng vậy. Một giải pháp lặp sử dụng một vòng lặp với một mô hình cố định: ở các nước đi lẻ, hoán đổi đĩa nhỏ nhất theo chu kỳ giữa các cọc, và ở các nước đi chẵn, thực hiện nước đi hợp lệ duy nhất không phải là nước đi nhỏ nhất.

Thuật toán này dạy về đệ quy, mô hình hóa các sơ đồ sao lưu-xoay vòng để lưu trữ, hướng dẫn trình tự hoạt động của cánh tay robot và xuất hiện trong các bài kiểm tra tâm lý thần kinh đo lường khả năng lập kế hoạch.

Các thuật toán học tăng cường giải quyết bài toán Tháp Hà Nội bằng cách coi mỗi cấu hình đĩa là một trạng thái và mỗi nước đi là một hành động. Đây là một tiêu chuẩn phổ biến để lập kế hoạch và học chính sách phân cấp.

Đúng vậy. GitHub Copilot, ChatGPT và... Gemini Tạo ra các giải pháp đệ quy cho bài toán Tháp Hà Nội trong Python, C++và JavaCác nhà phát triển vẫn nên kiểm tra lại các trường hợp cơ bản và thứ tự đối số.

Tóm tắt bài viết này với: