取子集

</pre><pre name="code" class="cpp">#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
void print(int n)//二进制观察,从左到右对应低位到高位
{
    for(int i=0;(1<<i)<=n;i++)
        if(n&(1<<i))
            cout<<1;
        else cout<<0;
    cout<<endl;
}

int main()
{
    int sum;
    while(scanf("%d",&sum)!=EOF)
    {
        cout<<"sum : ";print(sum);
        for(int i=sum;i;i=(i-1)&sum)
            print(i);
        cout<<endl;
    }
    return 0;
}

关键代码

 for(int i=sum;i;i=(i-1)&sum)

附:这段代码源于我在大白上看到的类似代码

对于集合sum。1表示该物品可取,0表示不可取,求出所有的可取状态。

上述代码不重复地取出了所有的子集!

下面给出i=(i-1)&sum这一表达式的证明

1.不重复性

证明:      设j=(i-1)&sum;( i 是已知的正确的状态)

由于取了&sum说明 j 也是正确的状态。

而  j是由(i-1)和某数按位与得到的,

则    j<i-1<i

得证(i-1)&sum能取出不重复的正确的状态来。

2.完整性

证明:    上面谈到了不重复性的证明,其实就是 i 的单调递减的证明

现在我们只需要证明   j=(i-1)&sum  得到的 j 是第一个比 i 小的状态。

设 状态 i  是  abcdef 10000   ;

i-1     是        abcdef  01111   ;

那么   (i-1)&sum会得到什么呢

我们将  i-1 分解来看  为  (abcdef 00000  + 000000 01111)&sum =(abcdef 00000&sum) + (000000 01111&sum)

= abcdef 00000 + (000000 01111&sum)

注意到    i&sum=i  ( i 是已知的正确状态)

将 i 也分解来看看             (abcdedf 00000  + 000000 10000) &sum = abcdef 00000 + (000000 10000&sum)

假设   状态   s=abcdef 0****是第一个比 i 小的状态

可得:

①    s>=j

②    s<i<(abcdef 10000&sum)  <=  (abcdef 01111&sum)  =  (i-1)&sum  =  j            即   s<=j

由①②可得    s=j  ;

得证  j  是第一个比  i  小的状态

得证 完整性

由1,2可以证明该算法的正确性 ,并可算出时间复杂度为( 2^n , n为可选物品数)。而所有的子集也为 2^n 个,因此该算法相当的好啊。

这神奇的取子集方法~~

时间: 2024-10-23 02:07:47

取子集的相关文章

Mysql 截取字符串取子集的函数应用

MySQL 字符串截取函数:left(),right(), substring(), substring_index(), mid(), substr() . 语法: left(str, length) #str 原字符串: length 截取长度:从左到右,截取length长度的子串.eg:select left('BJAA6024-Cara', 3); 结果:‘BJA’ right(str, length) #str 原字符串: length 截取长度:从右到左,截取length长度的子串.

R取子集(dplyr方法)

首选用dplyr包 查看hr有哪些字段名 > names(hr) [1] "satisfaction" "evaluation" "project" "monthlyhour" "serviceyear" "accident" "left" "promotion" "dept" "salary" &qu

R语言取子集

https://haoeric.gitbooks.io/r-advanced/content/qu_zi_ji.html http://adv-r.had.co.nz/Subsetting.html

文本挖掘之文本推荐(子集合生成)

刘 勇   Email:[email protected] 简介 在研究文本推荐算法时,需要挖掘关键字之间的规则,其中比较重要的一步是构建关键字的集合,即需要求取一个集合的所有子集.因此本文根据需求,采用3种方式实现该算法,以期对后续算法研究提供帮助. 本文下面从二叉树递归.位图和集合3个角度,对该算法进行研究与实现. 二叉树递归 为简要描述,采用数据集为:A= {1,2,3}.二叉树递归如下图-1所示. 图-1 二叉树递归过程 对图-1采用二叉树递归解释为:集合中每个元素有2中状态,属于某个集

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

R提高篇(三): 数据管理一

目录: 创建新变量 变量重编码 日期值 数据排序 数据集合并 数据子集 随机取样 创建新变量 算术运算函数:x%%y [求余 x mod y,  5%%2的结果为1], x%/%y  [整数除法,5% / %2 结果为2], ^或 ** 求幂 如下示例数据,在对象中增加平均.合计变量(场景不大合适,主要为了说明问题) 有多种方式来实现新增变量的处理,推荐使用 transform 示例代码如下: > mydata <- transform(mydata,avg = (age + weight)/

Python初学者的捷径[译]

下面列出的都是这些年总结的Python的有用的知识点和一些工具.希望对你有所帮助! 交换变量值 x = 6 y = 5 x, y = y, x print x >>> 5 print y >>> 6 内联if语句 print "Hello" if True else "World" >>> Hello 联接 nfc = ["Packers", "49ers"] afc =

R语言实战 - 基本数据管理(3)

8. 数据排序 > leadership$age [1] 32 45 25 39 NA > newdata <- leadership[order(leadership$age),] > newdata manager testDate country gender age item1 item2 item3 item4 item5 3 3 2008-10-01 UK F 25 3 5 5 5 2 1 1 2008-10-24 US M 32 5 4 5 5 5 4 4 2008-

《R语言实战》(中文完整版)pdf

下载地址:网盘下载 基本介绍 编辑 原作名: R in Action[2] 作者: Robert I. Kabacoff 译者: 高涛 / 肖楠 / 陈钢 出版社: 人民邮电出版社 出版年: 2013-1 页数: 388 定价: 79.00元 装帧: 平装 ISBN: 978-711-529-990-1 内容简介 编辑 数据时代已经到来,但数据分析.数据挖掘人才却十分短缺.由于"大数据"对每个领域的决定性影响,相对于经验和直觉,在商业.经济及其他领域中基于数据和分析去发现问题并作出科学