您的位置:首页 > 编程语言 > C语言/C++

c++ bitset与位压缩

2015-07-27 13:54 543 查看
bitset是c++的一个类模板,声明方法为

#inlcude <bitset>

bitset<n>p; //此处的n必须为常数


表示一串长度为n的0或1的串

以下是它的一些成员函数的用法

b.any()

b中是否存在置为1的二进制位?
b.none()
b中不存在置为1的二进制位吗?
b.count()
b中置为1的二进制位的个数
b.size()
b中二进制位的个数
b[pos]
访问b中在pos处的二进制位
b.test(pos)
b中在pos处的二进制位是否为1?
b.set()
把b中所有二进制位都置为1
b.set(pos)
把b中在pos处的二进制位置为1
b.reset()
把b中所有二进制位都置为0
b.reset(pos)
把b中在pos处的二进制位置为0
b.flip()
把b中所有二进制位逐位取反
b.flip(pos)
把b中在pos处的二进制位取反
b.to_ulong()
用b中同样的二进制位返回一个unsigned long值
os << b
把b中的位集输出到os流
最神奇的是它还可以使用位运算,这样可以用来优化一些dp的状态转移,即位压缩。

例如HDU5313

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <bitset>

using namespace std;
const int maxn = 20051;

vector<int>G[10001];
int id[10001];
int col[maxn];
bool vis[10001];
bitset<10001>dp;

struct node{
int a;
int b;
}tuan[10001];

void dfs(int u,int g){
id[u] = g;
vis[u] = 1;
for(int i = 0;i < G[u].size();i++){
int v = G[u][i];
if(!vis[v]){
dfs(v,g^1);
}
}
}

bool cmp(node a,node b){
return a.a-a.b>b.a-b.b;
}

int main()
{
int T,n,m;
//freopen("1004.txt","r",stdin);
cin>>T;
while(T--){
int nn = 0;
memset(id,0,sizeof(id));
memset(vis,0,sizeof(vis));
memset(col,0,sizeof(col));
scanf("%d%d",&n,&m);
int u,v;
for(int i = 0;i < m;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = 1;i <= n;i++){
if(!vis[i]){
dfs(i,nn);
nn+=2;
}
}
for(int i = 1;i <= n;i++){
col[id[i]]++;
}
int cnt = 0;
for(int i = 0;i < nn;i += 2){
tuan[cnt].a = col[i];
tuan[cnt].b = col[i+1];
if(tuan[cnt].a < tuan[cnt].b) swap(tuan[cnt].a,tuan[cnt].b);
cnt++;
}
int a;
dp[tuan[0].a] = 1;
dp[tuan[0].b] = 1;
for(int i = 1;i < cnt;i++){
dp = (dp << tuan[i].a) | (dp << tuan[i].b);//状态转移
}
int maxx = 100100,k = n/2;
for(int i = 0;i < n;i++){
if(dp[i]){
if(maxx > abs(k-i)){
a = i;
maxx = abs(k-i);
}
}
}
int ans = a*(n-a)-m;
cout<<ans<<endl;
for(int i = 0;i <= n;i++) {G[i].clear(); }
dp.reset();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: