浅谈递归算法的两道例题

1.全排列算法

全排列是数学中很常见的名词,既然有这个名词,相对应一定有这样的算法,那么如何通过程序实现这个算法呢?

下面给出了全排列的算法!

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=11;
int n,p[maxn],hash[maxn]={false};//h为散列,相关请参考散列的有关知识,p为存储当前排列中的数
void generate(int index){//求全排列的算法,整个算法可以通过图示来进行理解
	if(index==n+1){
		for(int i=1;i<=n;i++){
			cout<<p[i]<<" ";
		}
		cout<<endl;
		return;
	}
	for(int x=1;x<=n;x++){
		if(hash[x]==false){
			p[index]=x;
			hash[x]=true;
			generate(index+1);
			hash[x]=false;
		}
	}
}
int main(){
	n=3;
	generate(1);
	return 0;
}
2.n皇后问题

题目大意为在n*n的方格中,每一行每一列只能存在一个皇后,且这些皇后不能在同一对角线上,求这样的方案有多少种?

思路一:从n平方个方格中选取n个进行排列,然后排除,显然这种方法较为繁琐,而且很多本身就不符合题意,增大了排除的方案数,所以不是一种好的算法。

思路二:使用全排列,这样就能保证每一行每一列都只能存在一个皇后。

(1)第一种方法是先找出排列方法,再排除这些皇后不能在同一对角线上。(不是很好的算法)

(2)第二种方法是先判断已有的皇后所在的位置是否满足不在同一对角线上,先排除后进行加入皇后的位置,比较好的算法

方法一:

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=11;
int n,p[maxn],hash[maxn]={false};
int c=0;
void generate(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){
			c++;
			return;
		}
	}
	for(int x=1;x<=n;x++){
		if(hash[x]==false){
			p[index]=x;
			hash[x]=true;
			generate(index+1);
			hash[x]=false;
		}
	}
}
int main(){
	n=8;
	generate(1);
	cout<<c;
	return 0;
}
方法二:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=11;
int n,p[maxn],hash[maxn]={false};
int c=0;
void generate(int index){
void generate(int index){
	if(index==n+1){		
		c++;
		return;
	}
	for(int x=1;x<=n;x++){
		if(hash[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;
				hash[x]=true;
				generate(index+1);
				hash[x]=false;
			}
		}		
	}
}
int main(){
	n=8;
	generate(1);
	cout<<c;
	return 0;
}
以上的方法都不能算是最优算法,只能说是一种暴力破解的方法,所以大家如果有很好的方法,欢迎留言!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值