小技巧—指数形式的枚举
指数形式的枚举一般使用递归来实现。
通常,求一个集合的全组合(也就是全部子集)的时候,常用指数型枚举。
原理很简单,每层递归只有两个分支:选还是不选。
然后对于每次到达递归出口的时候,对当前的组合判断一下合不合法即可。
对于回溯来讲,可以使用各种STL实现(反正都是暴力,不用在意删除的那点时间复杂度)
比如vector,完全可以实现回溯(删除队尾),或者set(erase)。
所以基本代码如下:(以vector为例)
#include<cstdio>
#include<vector>
using namespace std;
vector<int> vec;
int n;
void calc(int x)
{
if(x==n+1)
{
for(int i=0;i<vec.size();i++)
printf("%d ",vec[i]);
puts("");
return;
}
calc(x+1);
vec.push_back(x);
calc(x+1);
vec.pop_back();
}
int main()
{
scanf("%d",&n);
calc(1);
return 0;
}
这里要注意,因为是暴力枚举,所以不要在没到达递归出口的时候加剪枝。拿可行性剪枝来讲,你的想法很美好:如果这里不可行就退回去。但是这么”退“就会导致枚举不全。丢答案。
基础暴力板子吧。还是算个小技巧的。谁让我太菜了