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

文章介绍了C++中状态压缩时如何利用数学上的集合关系,如交集、并集、对称差、差集等进行操作,以及标准函数库如__builtin_popcount、__builtin_clz和__builtin_ctz在处理二进制表示和集合中的元素位置中的应用。
摘要由CSDN通过智能技术生成

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

交集:a&b

并集:a|b

对称差:a异或b

差集:a&~b

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

集合与元素的关系:

全集:{0,1,……,n-1} 二进制表示为 (1<<n)-1如果存在,那一位为1

补集:~s or ((1<<n)-1)异或s

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

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

添加:s |(1<<i)

删除:s&~(1<<i)

删除最后一个元素:

#include<iostream>
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 的逻辑
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值