【递归】Fibonacci数列 | 全排列 | n皇后问题

Fibonacci数列

斐波那契数列(Fibonacci sequence),指的是这样一个数列:1、1、2、3、5、8、13、21、34、...

它满足 F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)

//求解Fibonacci数列第n项 (从第0项开始)
 
#include

int f(int n)
{
	if(n==1||n==0) return 1;
	return f(n-1)+f(n-2);
}

int main()
{
	int n;
	scanf("%d",&n);
	printf("%d",f(n));
} 

 

全排列

从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。全排列数f(n)=n!(定义0!=1)。

例如对1、2、3来说,其全排列是(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)。

//按递增顺序输出1-n的全排列 
#include

//定义全局变量,n:省事儿少传一个参数,Used和pos数组:每一次递归都要用到上一层的数据,若是在函数里定义,则一直在刷新= =  
int n,Used[100] = {0},pos[100];

void f(int index)
{
	if(index==n+1) //如果1~n的位置都安插妥当,输出 
	{
		for(int i=1;i

 

n皇后问题

n皇后是指在一个n*n的国际象棋棋盘上放置n个皇后,使得这n个皇后两两均不在同一行、同一列、同一条对角线上,求合法的方案数。对角线不单是最大的那两条,只要满足两个皇后横坐标之差的绝对值与纵坐标之差的绝对值相等即可。

如果枚举每一种情况,则是从n^2个位置中选出其中n个,有C\binom{n}{n*n}

但如果这样想,把三个满足条件的其中两条当作结论来使用,就变成了——因为每行每列只能放置一个皇后,如果把n皇后所在的行号依次写出,那么就会是一个1-n的排列(和上面的全排列十分相似了!)。于是就只需要进行1-n的全排列操作,有n!。

//暴力法
#include
#include

int n,Used[100] = {},pos[100],count = 0,flag;

//在上面的全排列基础上稍作修改 
void f(int index)
{
	if(index==n+1)
	{
		flag = 1; //当前顺序ok的标志(在每次位置排满后归置为合理) 
		for(int i=1;i<=n;i++)
		{
			for(int j=i+1;j<=n;j++)
				//i和j代表行,pos[i]和pos[j]代表列。
				//横纵坐标之差的绝对值相等==在同一条对角线上 
				if(abs(i-j)==abs(pos[i]-pos[j])) flag = 0;
		}
		if(flag) count++;
		return;
	}	
	for(int i=1;i<=n;i++)
	{	
		if(Used[i]==0)
		{
			pos[index] = i;
			Used[i] = 1;
			f(index+1);
			Used[i] = 0;
		}
	}
}

int main()
{
	scanf("%d",&n);
	f(1);
	printf("%d",count);
} 

可以优化下算法,让其一边判断,不行就直接返回,不用全部放置完毕后再来一一筛选了。

//回溯法
#include
#include

int n,count = 0,Used[100] = {0},pos[100],flag;

void f(int index)
{
	//判断在之前已经做好了,到这一步直接++了事 
	if(index==n+1)
	{
		count++;
		return;
	}
	for(int i=1;i<=n;i++)
	{ 
		if(Used[i]==0)
		{	
			flag = 1; //当前皇后不会与之前的皇后冲突 
			for(int pre=1;pre

 

你可能感兴趣的:(数据结构与算法)