借助堆栈以非递归(循环)方式求解汉诺塔的问题(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
1.递归调用思想
递归问题要注意的不是整个计算过程的实现而是关注完成最后一步所需要的条件再依次向上递归
代码如下:
#include<iostream>
using namespace std;
void move(int n, char A, char C, char B);
int main()
{
int N;
char A = 'a', B = 'b', C ='c';
cin >> N;
move(N,A,C,B);
system("pause");
return 0;
}
void move(int n, char A, char C, char B)
{
if (n == 0)return;
move(n - 1, A, B, C);//将n层从a移动到c需要将n-1层从a移动到b
cout << A << "->" << C << endl;
move(n - 1, B, C, A);//然后再将n-1层从b移动到c
}
2.非递归实现
主要依据是:所有的汉诺塔移动可以总结为重复的两步,我们假设现在最小的圆盘在a柱子上,柱子a,b,c顺时针放置
第一步:将最小圆盘移动到下一个柱子上,也就是b第二步:对a柱子和c柱子进行顶上最小的元素进行判断,把小一点的那个圆盘移动到大一点的那个圆盘(有空则摞在空柱子上)。重复上述两步就可以得到答案。
注意:如果N是偶数将b柱放在a后,所以如果N是奇数则将c柱放在a后面。
代码如下(N最大超时,等待修改):
#include<iostream>
using namespace std;
const int MAX = 64;
struct st
{
int s[MAX];//柱子上的圆盘数量
int top;//最上面的的圆盘
char name;//柱子的名字(a b c)
int Top()//取栈顶
{
return s[top];
}
int pop()//出栈
{
return s[top--];
}
int push(int x)//入栈
{
return s[++top] = x;
}
};
void creat(st ta[], int n);
long pow(int x, int y);
void hanoi(st ta[], long max);
int main()
{
int n;
cin >> n;
st ta[3];
creat(ta, n);
long max = pow(2, n) - 1;
hanoi(ta, max);
system("pause");
return 0;
}
void creat(st ta[], int n)
{
ta[0].name = 'a';
ta[0].top = n - 1;
for (int i = 0; i < n; i++)
ta[0].s[i] = n - i;
ta[1].top = ta[2].top = 0;
for (int i = 0; i < n; i++)
ta[1].s[i] = ta[2].s[i] = 0;
if (n % 2 == 0)
{
ta[1].name = 'b';
ta[2].name = 'c';
}
else
{
ta[1].name = 'c';
ta[2].name = 'b';
}
}
long pow(int x, int y)
{
long sum = 1;
for (int i = 0; i < y; i++)
sum *= 2;
return sum;
}
void hanoi(st ta[], long max)
{
int k = 0, i = 0;
int ch;
while (k < max)
{
ch = ta[i % 3].pop();
ta[(i + 1) % 3].push(ch);
cout << ta[i % 3].name << " -> " << ta[(i + 1) % 3].name << endl;
i++;
k++;//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
if (k < max)
{
if (ta[(i + 1) % 3].Top() == 0 || ta[(i - 1) % 3].Top() > 0 && ta[(i + 1) % 3].Top() > ta[(i - 1) % 3].Top())
{
ch = ta[(i - 1) % 3].pop();
ta[(i + 1) % 3].push(ch);
k++;
cout << ta[(i - 1) % 3].name << " -> " << ta[(i + 1) % 3].name << endl;
}
else
{
ch = ta[(i + 1) % 3].pop();
ta[(i - 1) % 3].push(ch);
k++;
cout << ta[(i + 1) % 3].name << " -> " << ta[(i - 1) % 3].name << endl;
}//把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
}
}
}