暴力法(蛮力法)枚举集合子集

版权声明:博主的博客不值钱随便转载但要注明出处 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;
}

猜你喜欢

转载自blog.csdn.net/easylovecsdn/article/details/82789858