递归
直接或间接调用自身的算法称为递归算法,在一个函数的内部直接或间接的出现有对自身的引用,称它是递归函数。简单来说,递归就是把一个复杂的大问题分解成一堆的小问题,再把这些小问题继续分解,直到问题小到能够得出结果,然后逐一解决,最后解决最开始的问题。
递归主要有四个结构:函数类型,边界,参数,递归调用,伪代码如下:
函数类型 dfs(参数){
if(边界条件){
返回值;
}
函数内容;
dfs(参数);
}
Copy
递归常被用于通过枚举找出最优解或和合法解的个数的题目,其本质是暴力枚举的思想,递归主要有三种枚举方式:
子集枚举
子集枚举又称01枚举,就是枚举每个物体,对于这个物体选还是不选,时间复杂度为O(2^n) 例题:超级书架 代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,h;
int a[50];
int sum=1e9;
void dfs(int step,int k){
if(step==n+1){
if(k>=h){
k-=h;
sum=min(sum,k);
}
return ;
}
if(k>=h){
k-=h;
sum=min(sum,k);
return ;
}
dfs(step+1,k+a[step]);
dfs(step+1,k);
}
int main()
{
freopen("shelf2.in","r",stdin);
freopen("shelf2.out","w",stdout);
cin>>n>>h;
for(int i=1;i<=n;i++){
cin>>a[i];
}
dfs(1,0);
cout<<sum;
return 0;
}
Copy
全排列枚举
需要把一个集合所有的排列方式输出,需要枚举每一个位置,看这个位置可以放什么。 例题:全排列输出 代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[20];
bool f[20];
void dfs(int step){
if(step==n+1){
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<endl;
return ;
}
for(int i=1;i<=n;i++){
if(!f[i]){
f[i]=1;
a[step]=i;
dfs(step+1);
f[i]=0;
}
}
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cin>>n;
dfs(1);
return 0;
}
Copy
注意,在全排列中,进行递归调用后需要回溯 当然,这种写法略显幼稚,没有强者风范,如果想要装逼进步的的话,可以用c++内置函数next_permutation(下一个)或prev_permutation(上一个)
组合枚举
组合枚举就是从一个集合中挑选固定个数的元素然后输出情况 例题:组合输出 代码如下:
#include<bits/stdc++.h>
using namespace std;
int a[10000010];
int n,m;
void dfs(int step,int k){
if(step==m+1){
for(int i=1;i<=m;i++){
cout<<a[i]<<' ';
}
cout<<endl;
return ;
}
for(int i=k;i<=n;i++){
a[step]=i;
dfs(step+1,i+1);
}
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cin>>n>>m;
dfs(1,1);
return 0;
}
Copy
DFS
DFS又称为深度优先搜索,就是用递归的形式进行暴力枚举,简单来说,就是一条路走到黑,走到头再返回。 例题:自然数拆分 代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[50];
void dfs(int x,int num,int k){
if(x==0){
if(num==2) return ;
cout<<n<<'=';
for(int i=1;i<num-1;i++)
cout<<a[i]<<'+';
cout<<a[num-1]<<endl;
return ;
}
for(int i=k;i<=x;i++){
a[num]=i;
dfs(x-i,num+1,i);
a[num]=0;
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
cin>>n;
dfs(n,1,1);
return 0;
}
Copy
递归和dfs在以后的学习中有很大的作用,应该多加练习