【保姆级教程】递归

本文图片和部分材料来源网络,如有侵权,请联系我删除,谢谢!

递归

首先我们先要知道递归是什么:

递归,是在运行的过程中调用自己 

然而,递归也可能导致性能问题,因为每次函数调用都会占用一定的内存空间,如果递归深度过大,可能会导致栈溢出错误(递归使用栈来完成的)。

但,递归也是要有条件的:

1.子问题须与本来的问题是做同样的事。
2.有递归边界(化简为非递归状况处理)。

常见的几种用递归解决的问题:

1.斐波那契数列的第X项

2.X的阶乘

3.汉诺塔

那么,作为初学者,我们先来学习最简单的:阶乘

(递归简介)

以下,是阶乘的递归过程图解

1.阶乘

我们不难发现,n在<=1的时候,返回的值是1,而其它情况则都是“n*fact(n-1);”

那我们可以得到递归部分是:

int f(int n)//这里我将函数名简写了一下,不影响实际作用
{
	if(n<=1)
	{
		return 1;
	}
	else
	{
		return n*f(n-1);
	}
}

最后我们再加上输入输出、基本框架就可以了

#include<bits/stdc++.h>
using namespace std;
int f(int n)
{
	if(n<=1)
	{
		return 1;
	}
	else
	{
		return n*f(n-1);
	}
}
int main()
{
	int n;
	cin>>n;
	cout<<f(n);
	return 0;
}

 2.八皇后问题

那我们再看经典问题——八皇后问题和查找路线问题;

 我们首先来看他的递归边界是什么;

我们知道,八皇后问题中如果我们摆放了八个棋子以上,我们就要退出(return)

那么摆放八个棋子以上就是我们的递归边界

我们知道,如果摆放八个棋子以上,那么这种方法成立,所以我们就要输出这种方法并且退出;

反之,就继续调用本身搜索

我们继续来思考,我们从几开始调用?

我们知道,我们首先要摆放第一个棋子,所以就从 dfs (1) 开始调用

而我们可以走一个点,标记一个点,这样就不会重复了。

可我们要输出多种方法,如果使用上述的算法,确实不会重复了,可也会少走许多路线导致WA

于是,我们就可以采用回溯的思想!

我们将这个点标记后搜索一遍,然后再取消标记。这样,我们就可以采用回溯的思想来修复BUG了

那么我们上代码:

#include<bits/stdc++.h>
using namespace std;
int cnt,n=8,a[15],b[105],c[105],d[105];
void dfs(int x)
{
	if(x==9)
	{
		cnt++;
		for(int i=1;i<=n;i++)
		{
			cout<<a[i]<<" ";
		}
		cout<<endl;
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(b[i]==0&&c[i+x]==0&&d[i-x+7]==0)
		{
			b[i]=1;
			c[i+x]=1;
			d[i-x+7]=1;
			a[x]=i;
			dfs(x+1);
			b[i]=0;
			c[i+x]=0;
			d[i-x+7]=0;
		}
	}
}
int main()
{
	dfs(1);
	cout<<cnt;
	return 0; 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值