zoukankan      html  css  js  c++  java
  • 枚举所有子集的三种算法详解-《算法入门经典》

    方法一:增量构造法

      理解递归必须得理解函数到底是做什么的。

    #include<cstdio>
    
    void print_subset(int n,int *a,int cur)  //print_subset的功能是打印集合{0,1,...,n-1}的cur个元素的子集,并且目前a数组中已经存储了要打印的集合 
    {
        printf("{ ");
        for (int i=0;i<cur;i++) printf("%d ",a[i]);
        printf("}
    ");
        int mi=cur?a[cur-1]+1:0;  //利用字典序避免重复打印 
        for (int i=mi;i<n;i++)  //枚举下一位可以添加什么元素 
        {
            a[cur]=i;
            print_subset(n,a,cur+1);  //递归打印cur+1个元素的子集 
        }
    }
    
    int main()
    {
        int n;
        int a[10]={};
        scanf("%d",&n);
        print_subset(n,a,0); //初始时a中存储了0个元素的子集,开始递归打印 
        return 0;
    }

    方法二:位向量法

      枚举每一位选或者不选,复杂度比方法一略高但更好理解,因为与输出全排列思路差不多,满n位就输出。

    #include<cstdio>
    
    int a[10];
    
    void print_subset(int n,int *b,int cur)  //确定第cur位选或者不选 
    {
        if (cur==n)  //如果确定好了n位,打印结果 
        {
            printf("{ ");
            for (int i=0;i<n;i++)
                if (b[i]) printf("%d ",a[i]);
            printf("}
    ");
        } 
        else
        {
            b[cur]=1;  //这一位选 
            print_subset(n,b,cur+1);  //递归下一位 
            b[cur]=0;  //这一位不选 
            print_subset(n,b,cur+1);  //递归下一位 
        }
    }
    
    int main()
    {
        int n;
        int b[10]={};
        scanf("%d",&n);
        for (int i=0;i<n;i++) a[i]=i;
        print_subset(n,b,0);
        return 0;
    }

      缺点是输出不是按照字典序。

    方法三:二进制法

      稍加思考就会发现,方法二其实与二进制是对应的。

    #include<cstdio>
    
    int a[10];
    
    void print_subset(int n,int b)  //n位的集合,b状态打印 
    {
        printf("{ ");
        for (int i=0;i<n;i++)
            if (b&(1<<i)) printf("%d ",a[i]);
        printf("}
    ");
    }
    
    void p_s(int n)
    {
        for (int i=0;i<(1<<n);i++) print_subset(n,i);  //枚举所有状态 
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for (int i=0;i<n;i++) a[i]=i;
        p_s(n);
        return 0;
    }

      这个方法优点就是代码简单。

    注意:以上三种方法输出顺序不同。

  • 相关阅读:
    hdu 2647 (拓扑)
    iOS 陀螺仪
    GetMessage()函数使用时的注意
    Button按钮释放时的事件
    深入理解递归:全排列问题
    json实现jsp分页
    EJB事务管理bug修改记
    hdu1159Common Subsequence
    HDOJ 4512 吉哥系列故事——完美队形I
    随机生成长度为100的数组,数组元素为1到10,统计出现次数最多和最少的元素
  • 原文地址:https://www.cnblogs.com/acmsong/p/8157307.html
Copyright © 2011-2022 走看看