借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。
输入格式:
输入为一个正整数N,即起始柱上的盘数。
输出格式:
每个操作(移动)占一行,按柱1 -> 柱2
的格式输出。
输入样例:
3
输出样例:
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
#include <bits/stdc++.h>
void Hanoi(int n, char a, char b, char c){
if(1 == n){ //可以直接移动
printf("%c -> %c\n", a, c);
}else{
Hanoi(n-1,a,c,b); //第一步 1~n-1号盘,从a柱移到b柱上
Hanoi( 1 ,a,b,c); //第二步 直接将n号盘,从a柱移到c柱上
Hanoi(n-1,b,a,c); //第三步 1~n-1号盘,从b柱移到c柱的n号盘上
}
} //其实也可以第二步替换为 printf("%c -> %c\n",a,c); 只是为了描述原理,统一更方便
main() {
int N;
scanf("%d", &N);
Hanoi(N,'a','b','c');
}
cout << a << " -> " << c << endl;
这里用cout在PTA平台上输出会超时,即便加上 ios::sync_with_stdio(false) 和 cin.tie(0) 并没有解决问题,不晓得为什么,所以改成了 scanf 和 printf。
//非递归实现
#include<bits/stdc++.h>
//测试点3 的N最大,达到20
#define MAX_N 20
//恰好能够解决问题的栈容量。
//如N=4时, 栈s最满时的Stack.n分别为[3,1,2,1,1,1,1 ] ;以此类推 N=n时为:[n-1,1,n-2,1,n-3,1,...,3,1,2,1,1,1,1]
#define MAX_SIZE (2*(MAX_N)-1)
typedef struct{
char n,a,b,c;
}Stack;
Stack s[MAX_SIZE]; //栈
int top=-1; //栈顶指针
void push(char n,char a,char b,char c){
#define PUSH_S(x) s[top].x=x
++top;
PUSH_S(n);
PUSH_S(a);
PUSH_S(b);
PUSH_S(c);
}
main() {
int N;
scanf("%d",&N);
push(N,'a','b','c'); //初始状态
while(top>=0){
//弹出元素
Stack TOP = s[top]; --top;
if(1==TOP.n){ //可以直接移动
printf("%c -> %c\n",TOP.a,TOP.c);
}
else{
//注意栈是先入后出的,递归按照实际操作顺序执行,按顺序不断拆解步骤直到任务完成
//入栈会把最初的元素压入栈底,而top栈顶指针从上往下顺序弹出并执行任务
//比如按顺序递归顺序压入栈的话 1 2 3(top) 那么最先执行的就是第三步而不是第一步
//故入栈顺序和调用递归函数顺序颠倒 按反顺序入栈 3 2 1(top) 这样就能够按实际操作顺序执行
push(TOP.n-1, TOP.b ,TOP.a ,TOP.c); //第三步 1~n-1号盘,从b柱移到c柱的n号盘上
push(1 , TOP.a ,TOP.b ,TOP.c); //第二步 直接将n号盘,从a柱移到c柱上
push(TOP.n-1, TOP.a ,TOP.c ,TOP.b); //第一步 1~n-1号盘,从a柱移到b柱上
}
}
}
//非递归实现 改成用自带的stack
//不需要自己移动栈顶指针 不需要自己计算堆栈容量 除此以外操作没什么差别
#include<bits/stdc++.h>
using namespace std;
typedef struct{
char n, a, b, c;
}Hanoi;
stack<Hanoi> s;
Hanoi hanoi(char n, char a, char b, char c){
Hanoi tmp;
tmp.n = n;
tmp.a = a;
tmp.b = b;
tmp.c = c;
return tmp;
}
main() {
int N;
scanf("%d", &N);
s.push(hanoi(N, 'a', 'b', 'c'));
while(!s.empty()){
Hanoi TOP = s.top();
s.pop();
if(TOP.n == 1){
printf("%c -> %c\n", TOP.a, TOP.c);
}
else{
s.push(hanoi(TOP.n - 1, TOP.b, TOP.a, TOP.c));
s.push(hanoi(1 , TOP.a, TOP.b, TOP.c));
s.push(hanoi(TOP.n - 1, TOP.a, TOP.c, TOP.b));
}
}
}