动态规划状态压缩二进制基础

在状态压缩时,注意考虑数学上集合之间的关系:

交集:a&b

并集:a|b

对称差:a异或b

差集:a&~b

包含:a属于b时 ,a&b = a or a| b = b

集合与元素的关系:

全集:{0,1,……,n-1} 二进制表示为 (1<

补集:~s or ((1<

属于:(s>>i)&1=1

不属于:(s>>i)&1 !=1

添加:s |(1<

删除:s&~(1<

删除最后一个元素:

#include
using namespace std;
int main()
{
	//删除最小元素
	int s = 4;//101
	//s - 1 100
	//cout << (s&(s-1)); 
	//101
	//100
	//=>100 
	return 0;
} 

标准的函数库:

C++;

 __builtin_popcount(s)返回s中二进制1的个数

二进制长度:32-__builtin_clz(s)   //__builtin_clz(s) 返回从最高位 0到遇到第一个1的多少位

集合中的最小元素:__builtin_ctz(s)

只包含最小元素的子集,即二进制最低 11 及其后面的 00,也叫 lowbit (经常在树状数组中见到)

s = 10010

~s=01101

(~s)+1 = 01110 //根据补码的定义,这就是 -s 最低 1 左侧取反,右侧不变

s&-s =00010

遍历集合

for (int i = 0; i < n; i++) {
    if ((s >> i) & 1) { // i 在 s 中
        // 处理 i 的逻辑
    }
}

 设集合为 s,从大到小枚举 s 的所有非空子集 subsub:

for (int sub = s; sub; sub = (sub - 1) & s) {
    // 处理 sub 的逻辑
}

你可能感兴趣的:(动态规划,动态规划,算法)