很惭愧,本来打算把八皇后一口气也整理出来,但是看鬼畜耽误了学习时间一会还要背单词,今天就简单整理一下汉诺塔问题。
一个函数调用自己就是递归,递归和普通函数调用一样是通过栈实现的。
现实生活中的例子就是“我三分钟就到,如果没到,请再读一遍这个短信”。
如求n!
int Factorial(int n)
{
if(n == 0) return 1;
else return n*Factorial(n-1);
}
递归主要用处有三类。
①替代多重循环
②解决以递归形式定义的问题
③将问题分解为规模更小的子问题进行求解
汉诺塔问题,就是一种典型的递归问题。
汉诺塔是根据一个传说形成的一个问题:有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须尊循上述两条规则。问:如何移?最少要移动多少次?
其实通过汉诺塔问题的计算,我们不难发现,汉诺塔和数学归纳法有异曲同工之妙。
第一数学归纳法
一般地,证明一个与自然数n有关的命题P(n),有如下步骤:
(1)证明当n取第一个值n0时命题成立。n0对于一般数列取值为0或1,但也有特殊情况;
(2)假设当n=k(k≥n0,k为自然数)时命题成立,证明当n=k+1时命题也成立。
综合(1)(2),对一切自然数n(≥n0),命题P(n)都成立。
上个月听宇哥的课时候,宇哥还讲了一下(笑
**对于n > 1的时候,又可以得出这3步:
1)将底盘n以上的环(n-1个)移动到B
2)将底盘n从A移动到C
3)将B上的环(n-1个)移动到C**
在把n个盘子从A移动到C的过程中,必然存在一步,那就是把最大的盘子从A拿出来。
要想把最大的盘子从A移动到C上,就必须保证剩下的n-1个盘子不能碍事,得好好堆在剩下B杆上。要保证n-1个盘子都在B杆上,至少得付出F(n-1)次移动。
在把n个盘子从A移动到C的过程中,必然存在一步,那就是最大的盘子被放到了C上,而且此后再也没动过。
在这步实施之后,我们只要花至少F(n-1)的步数把n-1个盘子从BC上就行了。这些步数必然和1)中的步数不重叠,因为这时候最大盘子在C上,而1)中最大盘子在A上。
所以就是1+F(n-1)+F(n-1)次。
#include<iostream>
using namespace std;
void Hanoi(int n,char src,char mid,char dest)
//将src座上的n个盘子 以mid为中转,移动到dest座
{
if( n == 1){
cout << src <<"->"<<dest<<endl;
return;
}
Hanoi(n-1,src,dest,mid);
//将n-1个盘子从src移动到mid所需要的步骤
cout << src <<"->"<<dest<<endl;
// 将最后一个移动到dest
Hanoi(n-1,mid,src,dest);
//将n-1个盘子从mid移动到dest所需要的步骤
return ;
}
int main()
{
int n;
cin >>n;
Hanoi(n,'A','B','C');
return 0;
}