递归,dfs总结

递归

直接或间接调用自身的算法称为递归算法,在一个函数的内部直接或间接的出现有对自身的引用,称它是递归函数。简单来说,递归就是把一个复杂的大问题分解成一堆的小问题,再把这些小问题继续分解,直到问题小到能够得出结果,然后逐一解决,最后解决最开始的问题。

递归主要有四个结构:函数类型,边界,参数,递归调用,伪代码如下:

函数类型 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在以后的学习中有很大的作用,应该多加练习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值