0
点赞
收藏
分享

微信扫一扫

递归-学习笔记

草原小黄河 2022-03-25 阅读 21
c语言

经典例子:递归求解n的阶乘

n!=12···*n,写成递归形式:n!=(n-1)!*n,即F(n)=F(n-1)*n

#include <cstdio>
int F(int n){
	if(n==0) return 1;	//递归达到边界时,返回1,0!=1 
	else return F(n-1)*n;	//递归式 
}
int main(){
	int n;
	scanf("%d",&n);
	printf("%d\n",F(n));
	return 0;
}

求斐波那契数列

F(0)=1,F(n)=F(n-1)+F(n-2)
数列前几项为:1,1,2,3,5,8,13,21,···

#include <cstdio>
int F(int n){
	if(n==0||n==1)	return 1;
	else return F(n-1)+F(n-2);
}
int main(){
	int n;
	scanf("%d",&n);
	printf("%d\n",F(n));
	return 0;
}

全排列

1~3的全排列:(1,2,3)、(1,3,2)、(2,1,3)、(2,3,1)、(3,1,2)、(3,2,1)

#include <cstdio>
const int maxn = 11;
//p保存当前以x开头的全排列,hashtable标记整数x是否已经在p中
int n,P[maxn],hashTable[maxn] = {false}; //初始化hash
//当前处理排列的第index号位
void generateP(int index){
	//每次写递归时都要先写出口,防止程序陷入死循环 
	if(index ==n+1){ 
		for(int i=1;i<=n;i++){
			printf("%d",P[i]);
		}
		printf("\n");
		return;
	}
	for(int x=1;x<=n;x++){ //枚举1~n,for循环完整执行一次,打印出一组排列完的数
		if(hashTable[x]==false){ 	//x不在p中,即x在本次循环未被使用 
			P[index]=x;		//把x加入当前排列
			hashTable[x]=true;	//x用过后标记已使用 
			generateP(index+1); //开始递归排列第index数以后的数
			
			hashTable[x] = false;  //执行完递归后x还原初始状态,准备进入下一个循环 
		}
	}
} 
int main(){
	n=3;
	generateP(1);
	return 0;
}

n皇后问题

在一个n*n的国际象棋棋盘上放置n个皇后,使得这n个皇后两两均不在同一行,同一列,同一条对角线上,求合法的方案数
每行只能放一个,每列也只能放一个,总共有n!个排列。
生成全排列,在递归边界判断是否符合n皇后条件,即遍历每两个皇后,判断他们是否在同一条对角线上(不在同一行和同一列是显然的),若不是,count+1
代码 v1:

#include <cstdio>
#include <stdlib.h>
int count = 0;
const int maxn=100;
int n,P[maxn],hashTable[maxn]={false};

void generateP(int index){
	if(index == n+1){
		bool flag=true;
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				if(abs(i-j) == abs(P[i]-P[j])){ 	//如果在一条对角线上 
					flag = false; 	//不合法 
				}
			}
		}
		if(flag) count++;
		return;
	}
	for(int x=1;x<=n;x++){
		if(hashTable[x] == false){
			P[index]=x;
			hashTable[x]=true;
			generateP(index+1);
			hashTable[x]=false;
		}
	}
}
int main(){
	n=8;
	generateP(1);
	printf("%d\n",count);
	return 0;
}

//回溯法 
/*void generateP1(int index){
	if(index == n+1){
		count++;
		return;
	}
	for(int x=1;x<=n;x++){
		if(hashTable[x]==false){
			bool flag=true;
			for(int pre=1;pre<index;pre++){
				if(abs(index-pre)==abs(x-P[pre])){
					flag=false;
					break;
				}
			}
			if(flag){
				P[index] = x;
				hashTable[x]=true;
				generateP(index+1);
				hashTable[x]=false;
			}
		}
	}
}
int main(){
	n=5;
	generateP1(n);
	printf("%d",count);
	return 0;
}
*/

代码 v2:

#include <cstdio>
#include <stdlib.h>
#include <iostream>
using namespace std;
const int N=10;
int a[N];	//a[i]表示第i行上的皇后放在a[i]列上
//假设a[3]=7,表示第3行上的皇后放在第7列
int cnt,n;
//检查皇后所在的列和两条对角线,不能再有皇后 
//对角线上,找规律,(x+y)相等,(x-y)相等 
bool check(int x,int y){ 	//第x行上能不能把皇后放在第y列上 
	for(int i=1;i<=x;i++){	//枚举 
		if(a[i]==y) return false;
		if(i+a[i]==x+y) return false;
		if(i-a[i]==x-y) return false;
	}
	return true;
}
void dfs(int row){ 	//第row行的皇后放于何处 
	//出口 
	if(row==n+1){
		//产生了一组解
		cnt++;
		return; 
	}
	for(int i=1;i<=n;i++){
		if(check(row,i)){
			a[row]=i;
			dfs(row+1);
			a[row]=0;
		}
	}
} 
int main(){
	printf("n皇后问题,请输入n=");
	scanf("%d",&n); 
	dfs(1);
	printf("产生了%d组解\n",cnt);
	return 0; 
}

输出

举报

相关推荐

0 条评论