hdu 3006(状态压缩)

本文讨论了如何使用状态压缩技术解决集合合并问题,包括输入格式、问题描述、算法实现和输出结果的详细解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Number of set

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1301    Accepted Submission(s): 795


Problem Description
Given you n sets.All positive integers in sets are not less than 1 and not greater than m.If use these sets to combinate the new set,how many different new set you can get.The given sets can not be broken.
 

 

Input
There are several cases.For each case,the first line contains two positive integer n and m(1<=n<=100,1<=m<=14).Then the following n lines describe the n sets.These lines each contains k+1 positive integer,the first which is k,then k integers are given. The input is end by EOF.
 

 

Output
For each case,the output contain only one integer,the number of the different sets you get.
 

 

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
 

 

Source
 
题意:n个集合,每个集合里面有t个数字,每个数字都属于 1-m(m<=14) ,问这些集合合并起来总共有多少可能性??
题解:第一次用状态压缩,,在队友的提示下虽然WA了一次,RE了两次,但是还是挺开心的。
一个集合最多也就有14个数字,我们用 二进制表示 一个集合的所有情况 比如说 某个集合包含 {1,3,11} 那我们的表示为 k = 00010000000101
然后我们每次把当前状态置为a[k] = 1;然后当碰到下一个状态t时,我们就到所有状态(FOR i 1-(1<<14))里面去找a[i]=1
然后a[i|t] = 1 最后遍历求出有多少a[i]为1即可。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 14
using namespace std;

int a[(1<<N)+1];  ///14位,最低位存0,2的14次方保存的是 100000000000000可以存15位,所以最大用到 2^14-1

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        int t,num,k;
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++){
            scanf("%d",&t);
            k=0;
            for(int j=1;j<=t;j++){
                scanf("%d",&num);
                k+=(1<<(num-1));
            }
            a[k]=1;
            for(int j=1;j<=(1<<N);j++){
                if(a[j]){
                    int next = k|j;
                    a[next]=1;
                }
            }
        }
        int ans = 0;
        for(int i=1;i<=(1<<N);i++){
            if(a[i]) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/liyinggang/p/5405811.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值