题目《20级计科ACM程序设计》–递归与递推 - Virtual Judge (sdtbu.edu.cn)
思路
-
汉诺塔问题:
-
如果n==1,A->C
-
如果n>1,分三步:
-
1.将n-1块,借助A移动到B,终点是B
-
2.将A最底下的那一块移动到C
-
3.将刚才的n-1借助A移动到C,终点是C
而在完成第三步时,显然又回到1,2两步
那么,问题的关键就在于,为什么形参要这样写,先a c b 后b a c ,依据是什么?
我们先看第一步,我们要借助C将n-1块石板从A移动到B,显然我们的终点是B,那么将起点A放到开始,将B放到尾部。
第二步,直接输出即可。
第三步,借助A从B移动到C,起点是B,终点是C,这样写也没有问题。
那么,依据是什么呢?我还没办法给出很清晰的解释,但在翻看各种解释之后,我觉得有个博主说的很有道理:如何理解汉诺塔的递归? - Fireman A的回答 - 知乎 https://www.zhihu.com/question/24385418/answer/257751077
对递归的理解的要点主要在于放弃!
放弃你对于理解和跟踪递归全程的企图,只理解递归两层之间的交接,以及递归终结的条件。
放弃的基础在于信任,信任数学归纳法。
-
#include<map> #include<queue> #include<cmath> #include<string>//使用to_string必须加该头文件 #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long #define itn int const int array_size = (int)1e6 + 50; const int INF = 0x3f3f3f3f; using namespace std; /* * 汉诺塔问题: * 如果n==1,A->C * 如果n>1,分三步: * 1.将n-1块,借助A移动到B,终点是B * 2.将A最底下的那一块移动到C * 3.将刚才的n-1借助A移动到C,终点是C * 而在完成第三步时,显然又回到1,2两步 */ void slove(int n,char a,char b,char c) { if (n == 1)cout <<"Move disk "<<1<<" from " << a << " to " << c << endl; else { slove(n - 1, a, c, b); cout << "Move disk " << n << " from " << a << " to " << c << endl; slove(n - 1, b, a, c); } } int main() { int n; cin >> n; slove(n,'A','B','C'); return 0; }