注 : 部分内容参考自 李煜东《算法竞赛 进阶指南》
简析 (bitset)
本质上, (bitset) 就是一个封装了一堆奇奇怪怪操作并支持状态压缩的 (bool) 数组,而且支持基本的位运算,那么我们该如何使用她(她?)呢?
-
头文件 :
#include<bitset>
不过,使用时不要忘了命名空间,或者加上:
std::xxxxx(); using namespace std;
-
声明 :
如何声明一个 (bitset) ?
bitset<50> s;
以上代码声明了长度为 (50) 的 (bitset) 并用 (0) 填充
还有一些神奇的操作,例如:
bitset<50> s1(12); string str = "100110"; bitset<50> s2(str);
括号中的内容会自动填充到 (bitset) 的末位中,超出 (50) 位的部分会被
残忍舍弃(注意:如果是整型,那么填充时会自动转换为二进制,如果是字符串,但是其中出现了 (0/1) 以外的字符,就会
爆炸) -
一些操作 :
基本位运算操作符都能用在这里,以本题为例
(你终于想起来还有个题了):s |= s << w[i];
以上代码将 (s) 左移了 (w[i]) 位并与原来的 (s) 取了并集
同时,她也支持像数组一样的使用 (s[i]) 直接访问 (s) 的第 (i) 位
-
一些好用的函数:
s.count();
返回 (s) 中 (1) 的个数
s.any(); s.none();
当 (s) 全为 (0) 时,第一个函数返回 (false) , 第二个函数返回 (true)
当 (s) 中有任何一位是 (1) 时,第一个函数返回 (true),第二个函数返回 (false)
s.set(); s.reset(); s.flip();
以上三个函数分别将 (s) 全部设为 (1),全部设为 (0),全部取反
值得注意的是,每一个函数都可以传入一个位置参数 (i),可以只对该位进行操作
参考代码
了解完 (bitset) 的基本操作之后,聪明的你(?)会做这题了吗?
#include<bitset>
#include<iostream>
using namespace std;
bitset<1001> s;
int w[] = {1,2,3,5,10,20};
int main(){
int n;
s[0] = 1;
for(int i = 0;i < 6;i++){
cin >> n;
for(int j = 0;j < n;j++) s |= s << w[i];
}
cout << "Total="<< s.count() - 1;
return 0;
}