一般需要枚举所有集合, 且是暴力的方法,则范围会很小,不能超过20。
状态压缩:
状态压缩,其实就是将每个任务 task[i] 看作某个 「 十进制数字 」 的二进制上的第 i 位,1 表示该任务被选择,反之不被选择。
用二进制表示集合
对于集合的子集,可以用(i|j)=j,则i是j的子集
这样,对于所有种集合的组成情况,可以用二进制方法方便遍历:一共有1<<k种。k=元素个数
枚举所有子集
// 枚举所有子集
for(int i =0;i<m;i++){
// 例如i:11001,意思第一个,二个,5个组成的集合
int state = i;
while(state > 0){
int element = state&1;
state >>= 1;
}
}
枚举每个集合的所有子集
// 枚举每个集合的所有子集
// 方法1
for (int i = 1; i < m; i++) {
// 枚举状态 i 的二进制子集
for (int j = i; j > 0; j = (j - 1) & i) {
// To Do..
}
}
// 方法2
for (int i = 1; i < m; i++) {
// 从 [1, i] 就可以了,后面的一定不会是 i 的子集
for (int j = 1; j <= i; j++) {
// 检查状态 j 是不是状态 i 的二进制子集
if ((i | j) == i) {
// To Do...
}
}
}