问题描述:有三根杆子A、B、C,A杆上有若干个大小不等的圆盘,大的在下,小的在上。要求将A杆上的圆盘全部移到C杆上,每次只能移动一个圆盘,且在移动过程中,三根杆子上的圆盘都要保持大的在下、小的在上。
其实就是移动圆盘,要求:1.每次只移动一个圆盘 2.保证大圆盘不会在小圆盘下面
相信很多刚接触这个问题的coder都会有点发懵,但是不用慌。我们先从最简单的情况看:
首先A(起始杆)上有3个圆盘
将最上面的圆盘移动到C(目标杆)上
再将第二个圆盘移动到B(辅助杆)上。
再将C上的圆盘移动到B上去。此时可以发现A杆剩下一个最大的圆盘,现在就将最大的圆盘显露出来了
然后将最大的圆盘移动至C杆上
现在B杆上是不是当n = 2时汉诺塔的最初情况,也就是说上面的步骤是为了将n = 3的情况变成n = 2的情况,此时我们可以将B杆看作起始杆,A杆看作辅助杆,而C杆上的最大圆盘对后续圆盘的移动不会产生影响。
后续操作:
同理,此时可以发现n = 2的情况又变成了n = 1的情况
这样就完成了
代码:
#include <iostream>
using namespace std;
//模拟圆盘的移动
void move(char pos1, char pos2) {
cout << pos1 << " -> " << pos2 << '\n';
}
int Hanoi(int n, char pos1, char pos2, char pos3, int& cnt) {
//当n = 0时,无需操作
if(n == 0) return 0;
cnt++;
//当n = 1时,直接将圆盘从起始移动到目标杆,需要操作1次
if(n == 1) {
move(pos1, pos3);
return cnt;
}
//当n != 1时,我们需要将 n 盘问题变成 n - 1 盘问题
//此时pos2相当于起始杆,pos1相当于辅助杆,pos3还是目标杆
Hanoi(n - 1, pos1, pos3, pos2, cnt);
//将当前最大的圆盘(n盘时)从起始杆移动到目标杆
move(pos1, pos3);
//经过上面的操作后,我们的问题变成了 n - 1 盘问题,
//也就是需要将 n - 1 盘问题变成 n - 2 盘问题
//此时pos1相当于起始杆,pos2相当于辅助杆,pos3还是目标杆
Hanoi(n - 1,pos2, pos1, pos3,cnt);
//觉得不好理解的可以结合我上面画的图来看
}
int main(){
int n;//n个盘
char pos1, pos2, pos3;//起始杆,辅助杆,目标杆
cin >> n;
cin >> pos1 >> pos2 >> pos3;
//参数的含义依次是:盘子数,起始杆,辅助杆,目标杆,操作次数
int cnt = Hanoi(n, pos1, pos2, pos3, cnt);
cout << cnt << '\n';
return 0;
}
感谢各位观众老爷的阅读,有不好的地方请发在评论区(由于作者是第一次发博客,如有不对请直接在评论区反馈,谢谢!)