• HDU 3006 The Number of set(位运算 状态压缩)


    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=3006

    题目大意:给定n个集合,每个集合都是由大于等于1小于等于m的数字组成,m最大为14。由给出的集合可以组成多少个不同的集合。

    输入描述:第一行为n,m,接下来n行,每行包含k+1个数字,第一个为k,表示该集合的元素个数,接下来k行表示集合元素。

    Sample Input
    4 4
    1 1
    1 2
    1 3
    1 4
    2 4
    3 1 2 3
    4 1 2 3 4
     
    Sample Output
    15
    2
     
    分析:以为m的规模很小,可以用二进制表示集合。借助位运算的或( | )来达到集合合并的目的。
       比如一个集合中有两个元素   1  3   那就用5 (101)表示这个集合
      比如一个集合(1 4 )和一个集合(1 2 3)进行合并 那就是  (9)1001 | 111(7)=1111  就是15 
     
    代码如下:
     1 # include<stdio.h>
     2 # include<string.h>
     3 int n,m,k;
     4 int dp[1<<15];
     5 int main(){
     6     int i;
     7     while(scanf("%d%d",&n,&m)!=EOF){
     8         memset(dp,0,sizeof(dp));
     9         while(n--){
    10             scanf("%d",&k);
    11             int set = 0;
    12             int temp;
    13             for(i=1;i<=k;i++){    //得到这个集合的二进制表示
    14                 scanf("%d",&temp);
    15                 set = set|(1<<(temp-1));
    16             }
    17             
    18             dp[set] = 1;
    19             for(i=0; i<(1<<m); i++)    //将新的集合与以往得到的集合合并
    20                 if(dp[i])
    21                     dp[i|set] = 1;
    22         }
    23         int ans = 0;
    24         for(i=0; i<(1<<m); i++)    //判断可以组成集合的个数
    25             if(dp[i])
    26                 ans++;
    27             printf("%d
    ",ans);
    28     }
    29     return 0;
    30 }
  • 相关阅读:
    [转].NET委托:一个C#睡前故事
    有关睡觉的学问
    [转]电话号码规范化规则正则表达式
    验证邮件地址的正则表达式
    初学UML之用例图
    没有不可突破的系统……
    生成树协议Spanning Tree Protocol
    两种图片漂浮的代码
    转:静态路由实际应用
    Cisco 2600 NAT 配置 实例
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3283315.html
Copyright © 2020-2023  润新知