《算法笔记》4.3递归

一.分治
分治是一种思想,可以用递归的方法实现,也可以用非递归的方法实现;

二.递归
自底向上:
在这里插入图片描述
三.题目
1.全排列:
方法一:

#include<cstdio>
using namespace std ;
int n , P[11] ;
void generateP(int index) {
	if(index == n) {
		for(int i = 0 ; i < n ; i ++) printf("%d",P[i]) ;
		printf("\n") ;
	}
	else {
		for(int i = 1 ; i <= n ; i ++) {
			int t = 0 ;
			for(int j = 0 ; j < index ; j ++) {
				if(P[j] == i) {
					t = 1 ;
					break ;
				}
			}
			if(t == 0) {
				P[index] = i ;
				generateP(index + 1) ;
			}
		}
	}
}
int main() {
	scanf("%d",&n) ;
	generateP(0) ;
	return 0 ;
} 

方法二:
将一重循环换成散列表;

#include<cstdio>
const int maxn = 11 ;
int n , P[maxn] , hashTable[maxn] = {false} ;
void generateP(int index) {
	if(index == n) {
		for(int i = 0 ; i < n ; i ++) printf("%d",P[i]) ;
		printf("\n") ;
	}
	for(int i = 1 ; i <= n ; i ++) {
		if(hashTable[i] == false) {
			P[index] = i ;
			hashTable[i] = true ;
			generateP(index + 1) ;
			hashTable[i] = false ;
		}
	}
}
int main() {
	scanf("%d",&n) ;
	generateP(0) ;
	return 0 ;
}

注意:
已经有全局变量n,则不能在mian里定义一个int n;

2.八妃问题
方法一:
全排列,剔除不满足条件的;如何检查是否有在同一对角线的皇后:行数差 = 列数差(行数:数组下标,列数:数组值);

#include<cstdio>
#include<cmath>
using namespace std ;
const int maxn = 100 ;
int cnt , n , P[maxn] ;
bool hashTable[maxn] = {false} ;
void generateP(int index) {
	if(index == n) {
		int flag = 1 ;
		for(int i = 0 ; i < n ; i ++) {
			for(int j = i + 1 ; j < n ; j ++) {
				if(abs(i - j) == abs(P[i] - P[j])) flag = 0 ;
			}
		}
		if(flag == 1) cnt ++ ;
	}
	for(int i = 0 ; i < n ; i ++) {
		if(hashTable[i] == false) {
			P[index] = i ;
			hashTable[i] = true ;
			generateP(index + 1) ;
			hashTable[i] = false ;
		}
	}
}
int main() {
	scanf("%d",&n) ;
	cnt = 0 ;
	generateP(0) ;
	printf("%d",cnt) ;
	return 0 ;
}

方法二:回溯法
思路:
选出 index 可以放置的位置;

注意:
1).遍历上层选 index 的位置时,要利用 flag 排除不可能的位置(而不是选满足条件的位置);
2).递归式后不用恢复初始化P[maxn];

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std ;
const int maxn = 100 ;
int cnt , n ;
int P[maxn] ;
void generateP(int index) {
	if(index == n) cnt ++ ;
	else {
		for(int i = 0 ; i < n ; i ++) {
			P[index] = i ;
			int flag = 1 ;
			for(int j = 0 ; j < index ; j ++) {
				if(i == P[j] || abs(i - P[j]) == abs(index - j)) {
					flag = 0 ;
					break ;
				}
			}
			if(flag == 1) generateP(index + 1) ;
		}
	}
}
int main() {
	scanf("%d",&n) ;
	cnt = 0 ;
	generateP(0) ;
	printf("%d",cnt) ;
	return 0 ;
}

3.《算法竞赛入门经典》7-4
代码:

#include<cstdio>
#include<cstring>
using namespace std ;
const int maxn = 20 ;
int n , P[maxn] ;
int hashTable[maxn] = {0} ;
int prime(int a) {
	int flag = 1 ;
	for(int i = 2 ; i < a ; i ++) {
		if(a % i == 0) flag = 0 ;
	}
	return flag ;
}
void print_ring(int index) {
	if(index == n && prime(P[n - 1] + 1) == 1) {
		for(int i = 0 ; i < n ; i ++) printf("%d ",P[i]) ;
		printf("\n") ;
	}
	else {
		for(int i = 2 ; i <= n ; i ++) {
			if(prime(i + P[index - 1]) == 1 && hashTable[i] == 0) {
				P[index] = i ;
				hashTable[i] = 1 ;
				print_ring(index + 1) ;
				hashTable[i] = 0 ;
			}
		}
	}
}
int main() {
	scanf("%d",&n) ;
	P[0] = 1 ;
	print_ring(1) ;
	return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值