1.分治
将原问题划分成若干个规模较小而结构与原问题相同或相似的子问题,求解子问题,最后合并子问题的解,得到原问题的解
子问题相互独立,没有交叉的
2.递归
- 递归边界
- 递归式(递归调用)
使用递归求解n的阶乘
#include<stdio.h>
int Fac(int n){
if(n == 0) return 1;
else return n * Fac(n-1);
}
int main(){
int n;
scanf("%d",&n);
printf("%d\n",Fac(n));
return 0;
}
斐波那契数列
#include<stdio.h>
int Fac(int n){
if(n == 0 || n == 1) return 1;
else return Fac(n - 1) + Fac(n - 2);
}
int main(){
int n;
scanf("%d",&n);
printf("%d\n",Fac(n));
return 0;
}
全排列
按字典序从小到大排列
用一个数组P存放当前的排列,再设定一个散列数组hashTable[],其中hashTable[x]表示整数x已经在数组P中时为true
#include<stdio.h>
const int maxn = 11;
int n,P[maxn],hashTable[maxn]={false};
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++){
if(hashTable[x] == false){
P[index] = x;
hashTable[x] = true;
generateP(index + 1);
hashTable[x] = false;
}
}
}
int main(){
n = 3;
generateP(1);
return 0;
}
n皇后问题
在一个n*n棋盘上放置n个皇后,两两不在同一行,同一列,同一对角线上
思路:枚举工作量太大,考虑使用排列,把每列的皇后的行号写出,总共有n!个排列,判断每个放置方案是否合法,到达递归边界则表示生成了一个排列,由于显示每列的行号,确定(1~n)的排列,于是n个皇后肯定不在同一行同一列,只要判断是否在同一对角线上即可
#include<stdio.h>
#include<math.h>
int count = 0;
const int maxn= 11 ;
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 == true){
count++;
for(int i = 1;i<=n;i++)
printf("%d ",P[i]);
}
if(flag == true)
printf("\n");
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",count);
return 0;
}
这些多多少少都有利用分治的思想,分解为一个小问题,得到每一个子问题的解,再合并解
上述代码是列出所有排列,是非常朴素的思想(暴力法),实际上,当排列好一部分皇后,剩下的如何排列都不符合,此时就没必要往下递归了,直接返回上层(回溯法),这样可以减少很多计算量
#include<stdio.h>
#include<math.h>
int count = 0;
const int maxn= 11 ;
int n,P[maxn],hashTable[maxn]={false};
void generateP(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 = 8;
generateP(1);
printf("%d",count);
return 0;
}