c++ bitset总结

c++ bitset总结


C++的 bitset 在 bitset 头文件中,bitset大概就是类似于bool数组一样的东西。但是它的每个位置只占1bit(特别特别小)

一般来说bitset会让你的算法复杂度下降很多

1.初始化

//初始化
bitset<24>bit;//bitset类型在定义时就需要指定所占的空间,默认全为0

//bitset类型可以用string和整数初始化(整数转化成对应的二进制),不足位数时会自动在前面补0
bitset<23>bit(string("11101001"));
cout<<bit<<endl;//输出00000000000000011101001
bitset<23>bit(233);
cout<<bit<<endl;输出00000000000000011101001

//用字符串构造时,字符串只能包含 '0' 或 '1' ,否则会抛出异常。
//在进行有参构造时,若参数的二进制表示比bitset的size小,则在前面用0补充(如上面的栗子);若比bitsize大,参数为整数时取后面部分,参数为字符串时取前面部分
bitset<2> bitset1(12);  //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00

string s = "100101";  
bitset<4> bitset2(s);  //s的size=6,而bitset的size=4,只取前面部分,即1001

char s2[] = "11101";
bitset<4> bitset3(s2);  //与bitset2同理,只取前面部分,即1110

cout << bitset1 << endl;  //00
cout << bitset2 << endl;  //1001
cout << bitset3 << endl;  //1110

2.位运算

//bitset支持所有位运算
bitset<23>bita(string("11101001"));
bitset<23>bitb(string("11101000"));

cout<<(bita^bitb)<<endl;//输出00000000000000000000001 
cout<<(bita|bitb)<<endl;//输出00000000000000011101001
cout<<(bita&bitb)<<endl;//输出00000000000000011101000
cout<<(bita<<5)<<endl;//输出00000000001110100100000
cout<<(bita>>5)<<endl;//输出00000000000000000000111

3.常用函数

//对于一个叫做bit的bitset:
bit.size()       返回大小(位数)
bit.count()     返回1的个数
bit.any()       返回是否有1
bit.none()      返回是否没有1

bit.set()       全都变成1
bit.set(p)      将第p + 1位变成1(bitset是从第0位开始的!) 
bit.set(p, x)   将第p + 1位变成x

bit.reset()     全都变成0
bit.reset(p)    将第p + 1位变成0

bit.flip()      全都取反
bit.flip(p)     将第p + 1位取反

bit.to_ulong()  返回它转换为unsigned long的结果,如果超出范围则报错
bit.to_ullong() 返回它转换为unsigned long long的结果,如果超出范围则报错
bit.to_string() 返回它转换为string的结果

4.使用技巧

一般用来优化奇偶性有关的问题,或者判断联通性之类的,(还可以在搜索的时候优化访问标记)

如力扣5852题:

5852. 最小化目标值与所选元素的差

class Solution {
public:
    int minimizeTheDifference(vector<vector<int>>& A, int target) {
        int n=A.size();
        int m=A[0].size();
        bitset<5000> F[n];//设立一个bitset数组,标记到达每一行时能拼凑出的数
        F[0]=0;
        for (int i=0;i<m;++i) F[0][A[0][i]]=1;//矩阵第一行直接标记
        for (int i=1;i<n;++i)
        {
            F[i]=0;
            for (int j=0;j<m;++j) {
                F[i] |= F[i - 1] << A[i][j];//先移位,一次完成矩阵上一行加下一行某个数的计算。再异或,传递到bitset数组对应的当前行记录
            }
        }
        int ans=4900;//最大4900,题目限制
        for (int i=1;i<=4900;++i)
            if (F[n-1][i])
                ans=min(ans,abs(target-i));
        return ans;
    }
};


假如不使用bitset,类似的标记思路,但是复杂度更高

class Solution {
public:
    int minimizeTheDifference(vector<vector<int>> &mat, int target) {

        int s = 0;
        for (auto &v : mat) s += *max_element(v.begin(), v.end());
        vector<int> dp(s + 1);
        dp[0] = 1;

        for (auto &v : mat) {
            vector<int> nxt(s + 1);
            for (int x : v)
                for (int i = x; i <= s; i += 1)//上一个算法的移位操作也大大减少了复杂度
                    if (dp[i - x]) nxt[i] = 1;
            dp.swap(nxt);
        }

        int ans = abs(s - target);
        for (int i = 0; i <= s; i += 1) 
            if (dp[i]) ans = min(ans, abs(i - target));
        return ans;
    }
};
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值