目录
前言
代码风格不好,也是第一次写博客,还请大佬们谅解,有简便写法希望不吝赐教
搜了很久发现大佬们汉诺塔写的都很好,也清楚,但是有一道题要求把编号也打印出来,没有搜到对应的博客,所以写了此篇。
方法一:(简单粗暴)
首先定义,
hanoit(int num, char a, charb, char c)
表示将num
个盘子从a
经过b
移动到c
move(char a, char c)
表示将a
最上面的盘子移动到c
每次只是移动最上面的,所以也就保证了,移动是符合规则的。
代码和注释写的应该比较直观了,get()函数写的比较复杂了,但是其实道理很简单
#include<stdio.h>
int cnt = 0, no;
struct n{
int idx[25]; //存放这个柱子从下到上的盘子, i = 1 开始存放
int tot; //存放有多少个盘子
}A, B, C;
int get(char src, char des){
if(src == 'A'){
if(des == 'B'){
B.tot++; //B上面增加一个
B.idx[B.tot] = A.idx[A.tot]; //B增加的是A最上面的
A.tot--; // A减少一个
}
else if(des == 'C'){
C.tot++;
C.idx[C.tot] = A.idx[A.tot];
A.tot--;
}
return A.idx[A.tot+1]; // 返回A最上面的是几号盘子
}
else if(src == 'B'){
if(des == 'A'){
A.tot++;
A.idx[A.tot] = B.idx[B.tot];
B.tot--;
}
else if(des == 'C'){
C.tot++;
C.idx[C.tot] = B.idx[B.tot];
B.tot--;
}
return B.idx[B.tot+1];
}
else{
if(des == 'A'){
A.tot++;
A.idx[A.tot] = C.idx[C.tot];
C.tot--;
}
else if(des == 'B'){
B.tot++;
B.idx[B.tot] = C.idx[C.tot];
C.tot--;
}
return C.idx[C.tot+1];
}
}
void move(char a, char c){ // 将a此时最上面的盘子移动到c
cnt ++;
no = get(a, c); // a最上面的是什么
printf("step #%d: move %d from %c to %c\n", cnt, no, a, c);
}
void hanoit(int num, char a, char b, char c){
if(num == 1) move(a, c); // 如果只需要移动一个盘子,直接移动即可
else{
hanoit(num-1, a, c, b); //先将a从最上面开始数的num-1个盘子经过c移动到b
move(a, c); // a只剩下最下面的一个盘子了,直接移动
hanoit(num-1, b, a, c); // 回到原问题,将b的num-1个盘子经过a移动到c,结束
}
}
int main(){
int n;
scanf("%d", &n);
no = n;
//初始化
for(int i = 1; i <= n; i++){
A.idx[i] = i;
B.idx[i] = 0;
C.idx[i] = 0;
}
A.tot = n;
B.tot = 0;
C.tot = 0;
hanoit(n, 'A', 'B', 'C');
}
方法二:(简化上面的思路)
首先定义,
hanoit(int low, int high, char a, char b, char c)
表示将a
柱子从low
编号到high
编号的盘子,经过b
移动到c
.
move(int idx, char a, char c)
表示将a
柱子的idx
编号的盘子移动到c
.
#include<stdio.h>
int cnt = 0;
void move(int idx, char a, char c){
cnt ++;
printf("step #%d: move %d from %c to %c\n", cnt, idx, a, c);
}
void hanoit(int low, int high, char a, char b, char c){
if(low == high) move(high, a, c); // 也就是只移动一个盘子的时候
else{
hanoit(low+1, high, a, c, b); // a保留最下面的盘子,上面的全部移动到b
move(low, a, c); //a最下面的盘子直接移动到c
hanoit(low+1, high, b, a, c); // 回到原问题,将b柱子上所有柱子(从low+1到high)全部移动到c
}
}
int main(){
int n;
scanf("%d", &n);
hanoit(1, n, 'A', 'B', 'C');
}
后记
其实两种方法的时空效率接近,只是第二种方法看起来更简单一些。