汉诺塔问题是非常经典的递归问题,之前只知道问题的移动步数的结论是2 ^ n - 1,具体过程并未思考。今天通过做题了解到这是明显的递归,过程如下。
有a b c三根柱子,先从n = 1 的情况开始。先将a 中的盘子移到 c中 ,记作
f
(
1
,
a
,
c
)
.
f(1,a,c).
f(1,a,c).
如果n = 2呢?显然,我们要先将a 中最上面的一个移到b中,再将a中剩下的一个移到c中, 最后将b中的一个移到c中。
那么操作过程是
f
(
1
,
a
,
b
)
−
>
f
(
1
,
a
,
c
)
−
>
f
(
1
,
b
,
c
)
f(1,a,b) -> f(1,a,c) ->f(1,b,c)
f(1,a,b)−>f(1,a,c)−>f(1,b,c)
将情况推广到n。我们需要将a中的n-1个移入b中 将 a中剩下的1个移入c中 在将b中的n-1个移入c中
f
(
n
−
1
,
a
,
b
)
−
>
f
(
1
,
a
,
c
)
−
>
f
(
n
−
1
,
b
,
c
)
f(n-1,a,b) -> f(1,a,c) ->f(n-1,b,c)
f(n−1,a,b)−>f(1,a,c)−>f(n−1,b,c)
发现规律了吗,每次的
f
(
n
)
=
2
∗
f
(
n
−
1
)
+
1
f(n) = 2*f(n-1)+1
f(n)=2∗f(n−1)+1
通过递归,我们可以得到f(n-1) 来更新f(n);
最终过程代码如下
#include<bits/stdc++.h>
using namespace std;
#define int long long
long long read(){
long long ret=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int n;
void dfs(int n,char a,char b, char c){
if(n == 1){
printf("%c----%c\n",a,c);
return;
}
dfs(n-1,a,c,b);
printf("%c----%c\n",a,c);
dfs(n-1,b,a,c);
}
signed main(){
int cnt = 0;
//ios::sync_with_stdio(false);
while(cin >> n){
if(cnt != 0)cout << endl;
cnt++;
dfs(n,'A','B','C');
}
return 0;
}