二进制状态压缩

一. 集合运算基础

使用二进制表示集合的选取状态
同样我们能快速的运用二进制实现一些遍历、交集、补集的操作
也能使用二进制存储对应状态,实现动态规划和剪枝

1. 集合与集合运算

A&B //求集合交集操作
A|B //求集合并集操作
A&∼B //做差,在集合A中剔除B的元素

A^B
//在B⊆A情况下,等价于做差
//否则,求对称差,即A与B的独有元素并集

2. 集合与元素运算

1 << i  // 第i位元素存在的状态(从0开始)
(1 << n) − 1  //所有元素存在的状态

判断第i位元素是否存在
(s >> i) & 1 == 1 //存在
(s >> i) & 1 == 0 //不存在

给集合添加增减元素
s ∣ (1 << i)  //添加元素
s & ∼ (1 << i) //删除元素
s ^ (1 << i) //存在则删除,不存在则添加

s & (s−1) //删除最小元素
s & (-s) //获取最小元素

3. 常用操作

string s = bitset<32>(n).to_string();//将整型数转化为二进制字符串
int dp[1<<n]; //存储所有状态的数组

//遍历所有状态
for (int mask = 0; mask < (1 << n); mask++) { 
}
//由大到小遍历s的所有非空子集
for (int sub = s; sub; sub = (sub - 1) & s) {
}
//遍历判断处理状态中第i个元素
for (int i = 0; i < n; i++) {
    if ((s >> i) & 1) { // i 在 s 中
    }
}

二. 状态压缩 + 暴力枚举

1. 子集、组合

三. 状态压缩 + 动态规划

1. 连接两组点的最小成本

2. 完成任务的最少工作时间

3. 划分k个相等的子集

4. 最小不兼容性

5. 数组的最大与和

6. 最小的必要团队

7. 并行课程II

8. 两个数组最小的异或值之和

四. 数位dp中的状态压缩(记忆化搜索)

1. 至少有一位重复的数字

2. 特别的排列

posted @ 2023-06-16 01:09  失控D大白兔  阅读(49)  评论(0编辑  收藏  举报