分治
- 分解:
将原问题分解为若干和原问题结构相同或相似的子问题 - 解决:
递归求解所有子问题 - 合并:
将子问题的解合并为原问题的解
递归实现分治法
- 案例:阶乘
- 案例:斐波那契数列
- 案例:全排列
一般称将1~n这n个整数按某个顺序摆放的结果称为这n个整数的一个排列,而全排列是指这n个整数能够形成的全部排列。现在需要实现按字典序实现 1 ~ n 的全排列。其中,(a1,a2,…,an)字典序小于(b1,b2,…,bn)是指存在一个i,使得a1=b1,a2=b2,…,a(i-1)=b(i-1),ai<bi成立
实现递归的两个要素:①递归式②递归边界
递归案例
阶乘
#include<cstdio>
int F(int n)
{
if (n == 0) return 1;
else return F(n - 1) * n;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",F(n));
return 0;
}
Fibonacii数列
#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;
}
全排列(n = 3)
#include<cstdio>
const int maxn = 11;
//P为存储当前排列的数组, hashTable用于记录整数 x是否已经在 P中
int n, P[maxn], hashTable[maxn] = {false};
//处理排列中的第 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,试图将 x填入P[i]
{
if (hashTable[x] == false)
{
P[index] = x;
hashTable[x] = true;
generateP(index + 1); //处理排列的第 index + 1 号位置
hashTable[x] = false; //已处理完 P[index] 为 x 的子问题,还原状态
}
}
}
int main()
{
n = 3;
generateP(1);
return 0;
}
n皇后问题(基于全排列,n = 8)
#include<cstdio>
#include<cmath>
const int maxn = 11;
//P为存储当前排列的数组, hashTable用于记录整数 x是否已经在 P中
int n, P[maxn], hashTable[maxn] = {false};
int count = 0;
//处理排列中的第 index 号位置
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++) //枚举 1 ~ n,试图将 x填入P[i]
{
if (hashTable[x] == false)
{
P[index] = x;
hashTable[x] = true;
generateP(index + 1); //处理排列的第 index + 1 号位置
hashTable[x] = false; //已处理完 P[index] 为 x 的子问题,还原状态
}
}
}
int main()
{
n = 8;
generateP(1);
printf("%d\n",count);
return 0;
}