汉诺塔是典型的递归问题,这个问题可以这样描述:
完成目标:将n个block块从A搬运到C,求需要移动多少次完成?
约束条件:搬运的过程中每次只能移动一个block块,且不能出现大的block块在小的block块之上。
详细分析如下:
为了分析将A中的n个block搬到C中,我们先分析一下n分别等于1,2,3的简单情况,在进行搬运之前我们有如下约定:
1、move(n,A,B,C)表示将n个block从A借助B搬到C中
2、move(1,A,C,B)表示将1个block从A搬到B中
第一种情况:
n = 1,将A中的①直接移动到C move(1,A,B,C) (直接从一个柱移动到另一个柱)
第二种情况:
n = 2,分3步
第一步:将①从A移动到B move(1,A,C,B) (直接从一个柱移动到另一个柱)
第二步:将②从A移动到C move(1,A,B,C) (直接从一个柱移动到另一个柱)
第三步:将①从B移动到C move(1,B,A,C) (直接从一个柱移动到另一个柱)
第三种情况:
n = 3,分三步
第一步:将①和②从A借助C搬到B move(2,A,C,B)
第二步:将③从A搬到C move(1,A,B,C) (直接从一个柱移动到另一个柱)
第三步:将①和②从B借助A搬到C move(2,B,A,C)
在这里我们进一步看一下第一步的move(2,A,C,B)和第三步的move(2,B,A,C)
1、将①和②从A借助C搬到B,move(2,A,C,B),其实又包含3个简单的步骤:
先将①从A搬到C,move(1,A,B,C);然后将②从A搬到B,move(1,A,C,B);最后将①从C搬到B,move(1,C,A,B)
2、将①和②从B借助A搬到C, move(B,A,C),其实也包含3个简单的步骤:
先将①从B搬到A,move(1,B,C,A);然后将②从B搬到C,move(1,B,A,C);最后将①从A搬到C,move(1,A,B,C)
好了,到这里就已经实现了n = 3的汉诺塔移动 是不是有点绕?其实自己在本子上画一下挺简单的,只是我把他写复杂了而已...
画了个图,假装看起来简洁点:
可以看到最后的每一步操作都是到位的,也就是可以直接将block块从一个柱移动到另一个柱。
第四中情况:
block为n的时候,分三步
第一步:将A中前n-1个block块借助C搬到B中 move(n-1,A,C,B)
第二步:将A中的第n个block块搬到C中 move(1,A,B,C)
第三步:将B中的n-1个block块借助A搬到C中 move(n-1,B,A,C)
那么第一步move(n-1,A,C,B)和第三步move(n-1,B,A,C)的实现又可以重复利用同样的思想,直到n-2,n-3,,,3,2,1就可以直接一步到位如move(1,A,B,C).
C++实现:
#include <iostream>
using namespace std;
void move(int n,char A,char B,char C);
int step;
int main()
{
int n;
cout<<"请输入block数n:"<<endl;
cin>>n;
move(n,'A','B','C');
return 0;
}
void move(int n,char A,char B,char C)
{
if(n==1)
{
step++;
cout<<"["<<step<<"]move 1# from "<<A<<" to "<<C<<endl;
}
else
{
move(n-1,A,C,B);
cout<<"["<<step<<"]move "<<n<<"# from "<<A<<" to "<<B<<endl;
step++;
move(n-1,B,A,C);
}
}
参考连接:https://wenku.baidu.com/view/dba81a9ecf2f0066f5335a8102d276a2002960a1.html?from=search