集合的整数表示

在稍微有难度一点的动态规划或者其他问题中,经常会使用用整数表示集合。在程序中表示集合的方法有很多种,当元素数比较少时,像这样用二进制码来表示比较方便。集合 { 0 , 1 , 2 , . . . , n − 1 } \{0,1,2,...,n-1\} {0,1,2,...,n1}的子集 S S S可以用如下方式编码。
f ( S ) = ∑ i ∈ S 2 i f(S)=\sum_{i\in S}2^i f(S)=iS2i,即 { 0 , 1 , 10 , 100 , . . . , 100000000... } \{0,1,10,100,...,100000000...\} {0,1,10,100,...,100000000...}存在即1,其余位为0。

这样表示之后,一些集合运算可以通过如下方式高效的进行。

  • 空集 ∅ \emptyset ————————————————————————0
  • 只含有第 i i i个元素的集合 { i } \{i\} {i}:———————————— 1 < < i 1<<i 1<<i
  • 含有全部 n n n个元素的集合 { 0 , 1 , . . . , n − 1 } \{0,1,...,n-1\} {0,1,...,n1}:———— ( 1 < < n ) − 1 (1<<n)-1 (1<<n)1
  • 判断第 i i i个元素是否属于集合 S S S:—————————— S > > i & 1 S>>i \&1 S>>i&1
    (也就是将 S S S的第 i i i位移到了个位,这样如果第 i i i存在,那么个位就会为1)。
  • 向集合中加入第 i i i个元素 S ∪ { i } S\cup\{i\} S{i}—————————— S ∣ 1 < < i S|1<<i S1<<i
  • 从集合中去除第 i i i个元素 S / { i } S/ \{i\} S/{i}—————————— S & ! ( 1 < < i ) S\& !(1<<i) S&(1<<i)
    ( 1 < < i ) (1<<i) (1<<i) i i i元素的编码,将其取非,得到第 i i i为0,其余位为1的集合,与运算即将第 i i i位置零。
  • 集合 S S S T T T的并集———————————————— S ∣ T S|T ST
  • 集合 S S S T T T的交集———————————————— S & T S\&T S&T
  • S S S最低位的1独立出来的值———————————— S & ( − S ) S\&(-S) S&(S)
    这是由于计算机中负数采取二进制补码形式表示, − x -x x其实对应于 ( ! x ) + 1 (!x)+1 (!x)+1(按位取反,末尾加1),也就是最低位1不变,高位全部取反。
    在这里插入图片描述

枚举集合的所有子集

按照下列方式进行枚举的话, S S S就会从空集开始,然后按照 { 0 } , { 1 } , { 0 , 1 } . . . \{0\},\{1\},\{0,1\}... {0},{1},{0,1}...的升序枚举出来。

for(int s = 0; s < 1<<n; s++){
	//对s的操作
}

枚举子集的子集

上面枚举子集采取了升序枚举,不断+1的手法,那是因为我们知道,所有 s < 1 < < n s<1<<n s<1<<n肯定都是 S S S的子集。但是如果我们现在有一个子集,比如 100101 100101 100101,要枚举他的子集,有一个难点

  • +1之后不一定就是他的子集,比如100110就不是他的子集。这个问题我们可以采用集合的交集运算,将它改为子集。
  • 但是如果对100110而言,+1之后100111,取交集依然是100110,没有变化,此时我们采取降序枚举的方式,每次给-1然后和原集合取交集。
	int sub = 7, sup = sub;
	do {
		//对子集的处理
		sub = (sub - 1)&sup;
	} while (sub != sup);//处理完0之后,会有-1&sup=sup,-1的补码全为1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值