001汉诺塔问题
一、问题描述
有A、B、C三根柱子,在A杆自下而上、由大到小按顺序放置64个圆盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:把一个圆盘从一根柱子移到另一根柱子称作1次移动,在移动和放置时允许使用B柱,但在移动过程中三根杆上都始终保持大盘在下,小盘在上。问把所有圆盘从A盘移到C盘上总共需要进行多少次移动?
二、算法分析
让我们把问题简化一下:
当A柱上只有一个圆盘时,只需移动一次,即A—>C.
当A柱上有两个圆盘时,需移动三次,即A—>B,A—>C,B—>C
当A柱上有三个圆盘时,需移动七次,即
A—>C,A—>B,C—>B
A—>C
B—>A,B—>C,A—>C
不难发现,A柱上的圆盘先移动到B盘上,再将A柱上的大圆盘移到C柱上,最后再将B柱上的圆盘移到C盘上。整个过程类似于第二种情况,只不过是两个盘子移到B柱上而不是一个。
因此,可以将问题用类似第二种情况的步骤去解决:
底层大圆盘上的圆盘移到B柱上
大圆盘移到C柱上
B柱上的圆盘移到C柱上
而第一步采用同样的方法,既然要将圆盘移到B柱上,那就先把关注的圆盘中底层之上的圆盘移到C柱上,再将大圆盘移到B柱上,最后把C柱上的圆盘移到B柱上。这样,圆盘的数量就减一。
以此类推,最后就只剩最后一个圆盘。移动过程中,柱的地位不一样。要把圆盘从当前柱移到目标柱,则把第三根柱当作中转站。其核心思想是,要移动n个盘,就要先将n-1个盘移到第三根柱上,这样层层递进,直到只剩一个盘。
移n个盘
移n-1个盘
移(n-1)-1个盘
…
移1个盘
三、算法代码
void Move(char x, char y) //输出移动步骤
{
printf("%c-->%c\n", x, y);
}
int Hanoi(char one, char two, char three, int n, int &flag)
{
//one two three 分别代表三根柱,形参的次序代表当前柱,中转柱和目标柱
if(n == 1) //递归终止的条件
{
Move(one, three);
flag++;
}
else
{
Hanoi(one, three, two, n-1, flag); //第一大步
Move(one, three);
flag++;
Hanoi(two, one, three, n-1, flag); //第三大步
}
return 0;
}
运行结果