递归实现指数型枚举
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int n;
const int N = 15;
int st[N]; //状态:记录每个位置当前的状态,0表示还没有考虑,1表示选,2表示不选。
void dfs(int u)
{
if(u > n)
{
for(int i = 1; i <= n; i ++ )
{
if(st[i] == 1)
cout << i << ' ';
}
cout << endl;
return ;
}
st[u] = 2; //不选
dfs(u + 1);
st[u] = 0; //恢复现场
st[u] = 1; //选
dfs(u + 1);
st[u] = 0;
}
int main()
{
cin >> n;
dfs(1);
return 0;
}
递归实现排列型枚举
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 10;
int n;
int st[N];
bool used[N]; //标记某个数是否枚举过
void dfs(int u) //枚举第u个位置
{
if(u > n)
{
for(int i = 1; i <= n; i ++ )
cout << st[i] << ' ';
puts(" ");
return ;
}
for(int i = 1; i <= n; i ++ )
{
if(!used[i])
{
st[u] = i;
used[i] = true;
dfs(u + 1);
st[u] = 0; //恢复现场
used[i] = false;
}
}
}
int main()
{
cin >> n;
dfs(1);
return 0;
}
递归实现组合型枚举
输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 30;
int n,m;
int way[N];
void dfs(int u,int start)
{
if(u == m + 1) //边界:枚举到最后一个位置
{
for(int i = 1; i <= m; i ++ )
cout << way[i] << ' ';
puts(" ");
return;
}
for(int i = start; i <= n; i ++ )
{
way[u] = i;
dfs(u + 1,i + 1);
way[i] = 0; //恢复现场,用0表示空
//这条语句可以省略,因为下一次枚举,后面的值会覆盖已经有的值
}
}
int main()
{
cin >> n >> m;
dfs(1,1); //从第一个位置开始,从1开始枚举
return 0;
}
优化
剪枝:提前发现递归搜索树中某些分支是无解的,提前把它剪掉。
例如:我们正在选第u个数,那么已经选的就是u-1个数,而后面可以从start选到n。那么,如果把start到n全部选上还不够m个数的话,就是无解的。即 u - 1 + n - start + 1 < m,即 u + n - start < m;
只需加一条语句 if(u + n - start < m) return即可,会发现,明显快了很多。