c++ bitset與位壓縮

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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章