集合整数表示

当元素数较少时,使用二进制码表示集合比较方便。
集合{0,1,…,n-1}的子集S可以用下式编码成整数。
f ( S ) = ∑ i ∈ S 2 i f(S)=\sum_{i\in S}2^i f(S)=iS2i
这样表示后,一些集合运算对应写成如下方式
空集 ∅ \varnothing … … … … … … … … … … … …0
只含有第i个元素的集合{i}… … … … … .1<<i
含有全部n个元素的集合{0,1,…,n-1}… …(1<<n)-1
判断第i个元素是否属于集合S… … … …if(S>>i&1)
向集合中加入第i个元素S ∪ \cup {i}… … … …S|1<<i
从集合中删除第i个元素S|{i}… … … … .S&~(1<<i)
集合S和T的并集S ∪ \cup T… … … … … … .S|T
集合S和T的交集S ∩ \cap T… … … … … … .S&T

将集合{0,1,…,n-1}的所有子集枚举

for(int S=0;S<1<<n;S++){
  //对子集的处理	
} 

按照该顺序进行循环,S会从空集开始,按照{0},{1},{0,1},…,{0,1,…,n-1}的升序顺序枚举出来。

将某个集合sup的所有子集枚举

int sub=sup;
do{
	//对子集的处理
	sub=(sub-1)&sup;
}while(sub!=sup);//处理完0后会有-1&sup=sup 

从sup开始每次减1直到0为止。由于sub-1并不一定是sup的子集,所以我们把它与sup进行按位与&。这样的话就可以将sup所有子集按照降序列举出来。(sub-1)&sup会忽略sup中的0而从sub中减去1。

枚举{0,1,…,n-1}所包含所有大小为k的子集

int comb=(1<<k)-1;
while(comb<1<<n){
	//这里针对组合的处理
	int x=comb&-comb,y=comb+x;
	comb=((comb&~y)/x>>1)|y;
}

按照字典序,最小的子集是(1<<k)-1,用它作为初始值。接下来求出comb其后的二进制码,列如0101110之后0110011,0111110之后1001111,下面是求出comb下一个二进制码的方法。
(1).求出最低位的1开始的连续的1的区间(0101110–>0001110)
(2).将这一区间全部变为0,并将区间左侧那个0变为1(0101110–>0110000)
(3).将第(1)步里取出的区间右移,知道剩下的1的个数减少了1个(0001110–>0000011)
(4).将第(2)步和第(3)步的结果按位取异或(0110000|0000011=0110011)

对于非零整数,x&(-x)的值就是将其最低位的1独立出来后的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值