递归详解
递归算法,归纳起来就有这几个特点。
- 它有一个基本部分,即直接满足条件,输出;
- 它有一个递归部分,即 通过改变基数(比如n),来逐步使得n满足基本部分的条件,从而输出;
- 它有一个超级弊端,即效率低(不过递归算法作为入门级算法还是很值得我这样的小白研究的。)。
几个经典问题:
- 全排列
- 阶乘
- hannoi(汉诺塔)
全排列
洛古 全排列问题
- 题目描述
输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
- 输入格式
一个数n(1≤n≤9)
- 输出格式
由1~n组成的所有不重复的数字序列,每行一个序列。
- 输入样例
3
-
输出样例
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int ans[15];//保存当前的方案
int use[15];//表示每个数是否被用过
void dfs(int x)//X表示当前搜索到那个数
{
if(x > n)//如果N位都搜索完了,就输出方案并返回
{
for(int i = 1;i <= n;i++)
cout<<ans[i];//输出方案
cout<<endl;
return;
}
for(int i = 1;i <= n;i++)//从小到大枚举
if(!use[i])//判断这个数是否用过
{
ans[x] = i;//保存到方案中
use[i] = 1;//标记这个数被使用了
dfs(x + 1);//进行下一步搜索
use[i] = 0;//撤销标记
}
}
int main()
{
cin>>n;//输入
dfs(1);//从第一个数开始搜索;
return 0;
}
其实全排列还有一个STL的函数,瞬间AC: 哈哈哈
#include<bits/stdc++.h>
using namespace std;
int x[11];
int main()
{
int n;
cin>>n;
for(register int i=1;i<=n;i++)//register 使循环更快;
x[i]=i,
cout<<i;
while(next_permutation(x+1,x+1+n))
{
cout<<endl;
for(register int i=1;i<=n;i++)
cout<<x[i];
}
}
阶乘
一本通 阶乘问题
- 题目描述
求10000以内n的阶乘。
N阶乘是由1到N相乘而产生
- 输入格式
只有一行输入,整数n(0≤n≤10000)。
- 输出格式
一行,即n!的值。
- 输入样例
4
- 输出样例
24
#include<bits/stdc++.h>// 万能头文件
#define ll long long//直接用ll代替long long
using namespace std;
ll jc(ll x)
{
if(x == 1)
return 1;
return x * jc(x - 1);//每次乘比x小1的数,实现阶乘
}
int main()//主函数,不多说
{
ll n;
cin>>n;
cout<<jc(n)<<endl;
return 0;
}
不过要按照我这样写,超过26就不行了
- 关键还是要用高精度。
hannoi(汉诺塔)
一本通 hannoi(汉诺塔)
此题有改动
-
题目描述
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到中间的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
这是一个著名的问题,几乎所有的教材上都有这个问题。由于条件是一次只能移动一个盘,且不允许大盘放在小盘上面,所以64个盘的移动次数是:18,446,744,073,709,551,615
这是一个天文数字,若每一微秒可能计算(并不输出)一次移动,那么也需要几乎一百万年。我们仅能找出问题的解决方法并解决较小N值时的汉诺塔,但很难用计算机解决64层的汉诺塔。
假定圆盘从小到大编号为1, 2, ...
-
输入格式
输入为一个整数(小于20)后面跟三个单字符字符串。
整数为盘子的数目,后三个字符表示三个杆子的编号。
- 输出格式
输出每一步移动盘子的记录。一次移动一行。
每次移动的记录为例如 a->3->b 的形式,即把编号为3的盘子从a杆移至b杆。
- 输入样例
2 a b c
- 输出样例
a->1->c a->2->b c->1->b
#include<bits/stdc++.h>
using namespace std;
int k=0;//统计步数
void Hanoi(int n,char a,char b,char c)
{
if(n==0)//0的话,没什么好玩的了,直接退出!
return ;
else
{
Hanoi(n-1,a,c,b);
k++;
printf("%d->%c->%c\n",k,a,c);
Hanoi(n-1,b,a,c);
}
}
int main()
{
int n;
cin>>n;
Hanoi(n,'A','B','C');
return 0;
}
当然,如果只计算步数,还是有公式的:2^n-1
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin>>n;
cout<<pow(2,n) - 1<<endl;
}
-
原创,转载请联系。