• 枚举子集的几种方法


    程序设计挑战竞赛上156页说了枚举组合和子集的几种方法,我觉得挺好的,收藏一下

    都是利用二进制数的模型来进行枚举子集或者组合

    下面枚举集合都是在二进制位上进行枚举。

    ##枚举k个数的子集

    void EunmSet(int k)//用k个二进制位数枚举k个状态
    {
        for(int i=0;i<1<<k;++i)
        {
            // 对子集的处理
        }
    }
    

    当k等于3时,即EunmSet(3)

    输出:

    000
    001
    010
    011
    100
    101
    110
    111

    枚举一个二进制状态的子集(其实我更喜欢for循环枚举)

    void EnumSubSet(int sup)/*作用:对于二进制状态sup,枚举该状态的子集*/
    {
        int sub=sup;
        do{
            /*对子集的处理*/
            sub=(sub-1)&sup;
        }
        while(sub!=sup);/*当sub=0之后 sub=0-1=-1,退出*/
    }
        /*
        原理:针对sup中的二进制为1的位开始进行减法,假设有k个二进制位,那么像枚举(2^k-1)~0一样枚举其子集
        输出:
            状态为降序输出
        */
    

    当sup=10101,即十进制数21

    输出:

    10101
    10100
    10001
    10000
    00101
    00100
    00001
    00000

    枚举n个状态中,k个状态成立的所有状态

    void EnumK(int k,int n)/*求出总共n个状态中,有k个状态为1的所有情况*/
    {
        int comb=(1<<k)-1;
        while(comb<1<<n)//comb>=2^n退出
        {
            //针对组合的处理
            int x=comb&-comb,y=comb+x;
            comb=((comb&~y)/x>>1)|y;
        }
    }
        /*原理:
            根据当前的符合要求的状态求出第一个大于该状态的符合要求的状态
        输出:
            升序输出
         算法描述:
         按照字典序的话,最小的子集是(1<<k)-1,所以用它作为初始值。现在哦我们求出comb其后的二进制码
         1.求出最低位的1开始连续的1的区间  (x&(-x)的值就是将最低位的1独立出来的值)
         2.将这一区间全部变为0,并将区间最左侧的0变为1
         3.将第1步取出的区间右移,知道剩下的1的个数少了1个
         4.将第2步和第3步的结果按位取或
        */
    

    输入:k=3,n=5

    00111
    01011
    01101
    01110
    10011
    10101
    10110
    11001
    11010
    11100

  • 相关阅读:
    python爬虫学习之MongoDB学习笔记
    python基础学习笔记
    基于python的turtle模块画国旗
    基于tkinter的gui编程基础学习笔记
    python爬虫实现各视频网站vip付费电影下载
    网页模板收藏
    python爬虫实战项目
    python爬取詹姆斯职业生涯数据并生成图标展示
    爬虫框架scrapy学习笔记
    基于python的OpenCV图像处理学习笔记
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/10427230.html
Copyright © 2020-2023  润新知