zoukankan      html  css  js  c++  java
  • bitset 优化01背包 处理集合

    好博客: https://www.cnblogs.com/cjjsb/p/9751384.html

    例题1:Newcoder 132C 简单瞎搞题

    题目链接:https://www.nowcoder.com/acm/contest/132/C

    题意:

    分析:核心就在于看作01背包的形式,枚举种类n,每个范围(L-R+1),以及所有的可能值 1~1e6,

    然后直接做的话又会超时,所以要用到 bitset 的位运算,将b[0][0]设置为1,每次向左移动 j*j 位,最后就可以得到经过所有组合后的可能取值。

    #include <cstdio>
    #include <bitset> 
    using namespace std;
    bitset<1000005>b[105];
    int n,l[105],r[105];
    int main()
    {
        scanf("%d",&n);
        int Min=0;
        for(int i=1;i<=n;i++) {scanf("%d%d",&l[i],&r[i]); Min+=l[i]*l[i];}
        b[0].set(0);
        //上面那句就等同于 -> b[0][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=l[i];j<=r[i];j++)
                b[i]|=(b[i-1]<<(j*j));
        
        // int ans=0;
        // for(int i=Min; i<=1000005; i++){
        //     if(b[n][i]) ans++;
        // }
        // printf("%d
    ", ans);
        printf("%d
    ",b[n].count());
        return 0;
    }

     例题2:POJ-2443

    题目链接:https://vjudge.net/problem/POJ-2443

    题意:分析某两个元素是否存在于共同的集合。

    #include <cstdio>
    #include <cstring>
    #include <bitset>
    using namespace std;
    
    const int maxn = 1e5+3;
    bitset<1000> a[10000],t; 
    int main(){
        int q,n,m,k;
        scanf("%d",&n);
        for(int i=0; i<n; i++){
            scanf("%d",&m);
            for(int j=0; j<m; j++){
                scanf("%d",&k);
                a[k][i] = 1;
            }
        }
        scanf("%d",&q);
        int x,y;
        for(int i=0; i<q; i++){
            scanf("%d%d",&x,&y);
            t = a[x]&a[y];
            if( t.count() ){
                printf("Yes
    ");
            }
            else{
                printf("No
    ");
            }
        }
    }

    例题3:HDU 5036

    题意:一个人要打开或者用炸弹砸开所有的门,每个门里面有一些钥匙,一个钥匙对应一个门,有了一个门的钥匙就能打开相应的门,告诉每个门里面有哪些门的钥匙,问需要用的炸弹为多少。

    我们考虑对于每一扇们单独计算期望,根据期望的线性性质最后累加起来就是答案。

    分析:利用 bitset 优化 floyed 传递闭包 (利用 bitset 优化计算个数的过程)

    就是不需要用到三重循环,而是把一个节点的父亲节点的所有父亲节点累计在这个孙子 bitset 上。

    (即如果一个点是另一个点的父亲,那么父亲的父亲也都能够到达这个点,那就可以全部记录在这个孙子 bitset 上了 )

    #include <cstdio>
    #include <cstring>
    #include <bitset>
    using namespace std;
    
    const int maxn = 1e3+3;
    bitset<maxn> a[maxn];
    
    int main(){
        int T,kase=1;
        scanf("%d",&T);
        while(T--){
            int n,x,y;
            scanf("%d",&n);
            for(int i=1; i<=n; i++) a[i].reset();
            for(int i=1; i<=n; i++){
                a[i].set(i);
                scanf("%d",&x);
                for(int j=1; j<=x; j++){
                    scanf("%d",&y);
                    a[y].set(i);
                }
            }
            for(int i=1; i<=n; i++){
                for(int j=1; j<=n; j++){
                    if(a[j].test(i)){
                        a[j] |= a[i];
                    }
                }
            }
            double ans = 0;
            for(int i=1; i<=n; i++){
                ans += 1.0/(a[i].count());
                // printf("%d %lf
    ", i,ans);
            }
            printf("Case #%d: %.5lf
    ",kase++, ans);
        }
    }
  • 相关阅读:
    创建和发送事件
    (实战)为系统类添加NameValueTable属性,并且添加到相关对话框
    使用GetUniqueIndentifier为某类对象连续编码
    中秋小感
    数据库中取随机数的方法讨论
    CVS添加用户的过程和命令列表
    Mysql中获取刚插入的自增长id的三种方法归纳
    关于Action重复执行两遍的原因
    td内容空的时候,如何显示边框线
    2003下 tomcat 连mysql问题的解决
  • 原文地址:https://www.cnblogs.com/-Zzz-/p/11489494.html
Copyright © 2011-2022 走看看