版权声明:博主的博客不值钱随便转载但要注明出处 https://blog.csdn.net/easylovecsdn/article/details/82789858
1.二进制数枚举法:
感觉很好用的一种方法,之前没有使用过,今天老师上课提到了就试了一下,一个二进制数的每一位0、1代表该位的元素选入或不选入该集合,通过位运算的方法暴力枚举,下面是枚举1——6数组的子集。
下面是输出的结果(第一个空行代表空集):
#include <bits/stdc++.h>
using namespace std;
int a[] = {1, 2, 3, 4, 5, 6}; //在此只列举了几何中有6个元素的情况
void print(int flag) //采用二进制方法输出集合元素
{
int temp = flag;
for (int i = 0; i < 6; i++) {
if (temp & 1 >= 1) cout << a[i] << " ";
temp >>= 1;
}
cout << endl;
}
int main()
{
int flag = 0;
while (flag < pow(2, 6)) { //加上空集一共有2^n个集合
print(flag);
flag++;
}
cout << "Subset nums = " << flag <<endl; //flag即为子集个数
return 0;
}
2.暴力的经典:DFS+回溯
说到暴力,我们都能想到dfs,对于集合中的每一个元素,都有两种状态,要么被选入集合,要么不被选入集合,这正好满足dfs的使用特征,我们用vis数组标记一个元素是否被选入集合,通过深度搜索输出结果最后注意dfs的终止条件即可。
#include <bits/stdc++.h>
using namespace std;
int a[] = {1, 2, 3, 4, 5, 6}; //在此只列举了几何中有6个元素的情况
int vis[6]; //vis数组代表选中该元素或者不选
int sum; //记录子集个数
void dfs(int n)
{
if (n == 5) {
sum++;
for (int i = 0; i < 6; i++) {
if (vis[i] == true) cout << a[i] << " ";
}
cout << endl;
return ;
}
int i = n+1;
vis[i] = true;
dfs(i);
vis[i] = false;
dfs(i);
}
int main()
{
memset(vis, false, sizeof(vis));
sum = 0;
vis[0] = true;
dfs(0);
vis[0] = false;
dfs(0);
cout << "Subset nums = " << sum <<endl;
return 0;
}