借助堆栈以非递归(循环)方式求解汉诺塔的问题(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<stdio.h>
#include<stack>
#include<stdlib.h>
#include<iostream>
/*
* 算法步骤:
* 第一步:将最小盘子移动到下一个柱子上,比如最小盘子编号为a,那么就调用move(a, (a+1)%3)
* 第二步:对剩下两个杆子顶上元素进行判断,将小的那个圆盘移动到较大那个圆盘上;如果有空杆则移动到空杆上
* 注意:如果盘子数n为偶数则会从a移动到c,但是如果n为奇数,则会从a移动到b,所以需要将bc两个杆子交换
*
*/
using namespace std;
char s[3] = { 'a', 'b', 'c' }; //abc三个柱子 (用于输出)
stack<int> a[3]; //这个栈用来记录圆盘数
bool move(int before, int after) //将选中柱子上最小的盘底从before移动到after
{
if (a[before].empty()) //如果before柱子为空则返回false退出
return false;
if (!a[after].empty()){ //如果after柱子不为空
if (a[after].top() - a[before].top() < 0) //如果after柱子顶上的元素比before柱子顶上元素小则返回
return 0;
}
a[after].push(a[before].top()); //移动
a[before].pop();
printf("%c -> %c\n", s[before], s[after]); //输出
return true;
}
int main()
{
int N, count = 0;
cin >> N;
for (int i = 0; i < N; i++)
a[0].push(N - i); //在第一个柱子上加入n个盘子
if (N % 2 == 1) //如果是盘子数是奇数的话则交换bc
{
s[1] = 'c';
s[2] = 'b';
}
while (++count){
move((count - 1) % 3, count % 3); //将最小圆盘移动到下一个杆上
//判断退出条件
//下面两个移动会执行一个,因为move里面有一个判断,如果before比after顶上元素小则不会移动
//所以下面两个move只会执行一个移动
if (!move((count - 1) % 3, (count + 1) % 3))
if (!move((count + 1) % 3, (count - 1) % 3))
break; //执行到这里说明 (count - 1) % 3和 (count + 1) % 3都为空,结束循环
}
return 0;
}