zoukankan      html  css  js  c++  java
  • 枚举-子集生成法1

    紫书P188-7.3子集生成

    1、增量构造法

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int aim[100];
     5 int psd[100];//核心代码如下
     6 int subset(int cur,int n,int last)//必须使用last元素记录上层函数添加的最后一个元素的序号
     7 {
     8     for(int i=0;i<cur;i++)
     9         printf("%d ",aim[i]);
    10     printf("
    ");
    11     int k=last+1;
    12     for(;k<n;k++)
    13     {
    14         aim[cur]=psd[k];
    15         subset(cur+1,n,k);
    16     }
    17     return 0;
    18 }
    19 
    20 int main()
    21 {
    22     int n;
    23     scanf("%d",&n);
    24     for(int i=0;i<n;i++)
    25         scanf("%d",&psd[i]);
    26     subset(0,n,-1);//初值从-1开始,因为递归中的循环时从last+1开始
    27     return 0;
    28 }

    这是最为常用的一种方法,其思路来源于C++中"枚举法全排列"的函数设计思路。

    2、位向量法

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int aim[100];
     5 int psd[100];
     6 //该代码的核心是利用aim中的0与1情况不同间接地对psd中的值进行挑选
     7 int subset(int cur,int n)
     8 {
     9     if(cur==n)
    10     {
    11         for(int i=0;i<n;i++)
    12             if(aim[i])printf("%d ",psd[i]);
    13         printf("
    ");
    14     }
    15     else
    16     {
    17         aim[cur]=1;
    18         subset(cur+1,n);
    19         aim[cur]=0;
    20         subset(cur+1,n);
    21     }
    22     return 0;
    23 }
    24 //其显著的缺点就是分支太多,递归太多,但多数情形下并没有显著的影响
    25 
    26 int main()
    27 {
    28     int n;
    29     scanf("%d",&n);
    30     for(int i=0;i<n;i++)
    31         scanf("%d",&psd[i]);
    32     memset(aim,0,sizeof(aim));
    33     subset(0,n);
    34     return 0;
    35 }

    3、二进制法(从代码量的角度而言,这是最简单的方法)

    该方法需要有逻辑运算与位运算基础,将单独说明.以下暂时只给出代码

    ->在用二进制表示子集时,位运算中的按位与、或、异或对应集合中的交、并和对称差。

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 //以下代码用来打印{0,1,2~n-1}集合的子集
     5 void subset(int n,int s)
     6 {
     7     for(int i=0;i<n;i++)
     8         if(s&(1<<i))printf("%d ",i);
     9         //非0即真
    10     printf("
    ");
    11 }
    12 
    13 int main()
    14 {
    15     int n;
    16     scanf("%d",&n);
    17     //枚举各子集对应的编码为0到2^n-1
    18     for(int i=0;i<(1<<n);i++)
    19         subset(n,i);
    20     return 0;
    21 }
  • 相关阅读:
    svn常用命令
    mysql5.6 sql_mode设置
    centos6.5 mysql5.6主从复制
    linux 挂载windows共享文件夹
    hadoop+hive+hbase+zookeeper安装
    Linux踢出登陆用户的正确姿势
    个人博客项目部署到腾讯云记录(私人记录)
    Python中的单例模式的几种实现方式和优化以及pyc文件解释(转)
    关于window.location.hash的理解及其应用(转)
    Django model反向关联名称的方法(转)
  • 原文地址:https://www.cnblogs.com/savennist/p/12197930.html
Copyright © 2011-2022 走看看