借助堆栈以非递归(循环)方式求解汉诺塔的问题(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)将最小圆盘移动到下一个柱子上。
(2)对剩余两柱子进行顶上最小的元素判断,把小一点的圆盘移动到大一点的圆盘上(有空柱则摞在空柱子上)。
重复上述两步就可以得到答案。
注意:这样得到的最后的答案不一定是摞在 c 上,如果 N 是奇数将摞在 b 上,所以如果 N 是奇数我们就令第二个柱子为 c ,第三个柱子为 b ,这样就一定最后是摞在 c 上的。
AC代码:
#include<stack>
#include<cstdio>
#include<iostream>
using namespace std;
stack<int> s[3];
char c[3] = { 'a','b','c' };
void Move(int x, int y) {
//ios_base::sync_with_stdio(false);
if ((s[x].empty() && !s[y].empty()) || (!s[x].empty() && !s[y].empty() && s[x].top() > s[y].top())) {
s[x].push(s[y].top());
s[y].pop();
//cout << c[y] << " -> " << c[x] << endl;
printf("%c -> %c\n", c[y], c[x]);
return;
}
if ((!s[x].empty() && s[y].empty()) || (!s[x].empty() && !s[y].empty() && s[y].top() > s[x].top())) {
s[y].push(s[x].top());
s[x].pop();
//cout << c[x] << " -> " << c[y] << endl;
printf("%c -> %c\n", c[x], c[y]);
return;
}
}
int main() {
int k1, k2, k3;
k1 = 0, k2 = 1;
int n;
//cin >> n;
scanf("%d", &n);
for (int i = n; i >= 1; i--) {
s[0].push(i);
}
if (n % 2 == 1) {
c[1] = 'c', c[2] = 'b';
}
while (1) {
Move(k1, k2);
if (s[k2].size() == n) {
break;
}
k3 = k1;
k1 = k2;
k2 = (k1 + 1) % 3;
Move(k3, k2);
}
return 0;
}