hdu 3006(状态压缩)

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

2009 Multi-University Training Contest 11 - Host by HRBEU

题意: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;
}
时间: 2024-10-11 11:42:40

hdu 3006(状态压缩)的相关文章

hdu 5180 状态压缩 dp 打表

hdu 5180 状态压缩 dp 打表 题意: 在n*n的国际象棋中,放置若干个国王和k个车,使得国王之间不互相攻击,车之间不互相攻击,车不可攻击到国王(这并不代表国王不能攻击到车).国王能攻击到它上下左右,左上左下右上右下八个位置的棋子,车可以攻击到同一行或同一列中的棋子,求方案总数对1000000007取模后的值. 限制: 1 <= n <=15; 0 <= k <=15 思路: 状态压缩,dp,打表套打表 打表程序如下: 打表程序1: tab[a][b]表示a*b的棋盘王的放

hdu 4917Permutation(状态压缩DP)

hdu 4917Permutation(状态压缩DP) 题意:将1~n的n个数排列成序列(n<=40),但有m(m<=20)个限制条件,其中第i个限制条件的表示为ai,bi.表示该序列的第ai的数要小于第bi的.问有多少中排列?保证有解 解法:我们首先可以明确一点,这m个限制条件,所表示的关系会构成若干个DAG(有向无环图,我将其称之为拓扑图).我们只要将这n个数,填入到拓扑图上,使其满足拓扑关系,那么这样的序列就是可以的.而这若干个拓扑图之间,是不会相互影响的,因而我们可以单独考虑每一个拓扑

[HDU]5094Maze(状态压缩BFS)

状态压缩的题,第一次WA了,怎么改都不对,交了十几遍,之后重新写了一个,1A了 #include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int maxn = 51; const int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}}; int n,m,t; int door[maxn][m

hdu 5135 状态压缩dp

题意是给出最对12条边你     问最大可组成三角形面积是多大 (可有多个三角形)   典型的状态压缩  (最多12条边) 思路: 先暴力枚举所有可能三角形的面积   然后再根据状态压缩来做    最多可组成n/3个三角形  对每个三角形都记录三边或(运算)    和面积    然后判断进行合并  (根据且运算)   就行了 #include<stdio.h> #include<string.h> #include<cmath> #include<iostream

HDU 2553 状态压缩

N皇后问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 23888    Accepted Submission(s): 10639 Problem Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上.你的任务是,对于给定的N,求

hdu 3811 状态压缩

题意就不对说了:  开始想用深搜过  感觉数据水的话应该能过,  哈哈  还是超时了!!! 正确做法应该是状态压缩吧,n小于等于17    2^17-1种状态,每种状态表示对应的数用没用过,如果用状态压缩dp的思路(从小状态跑到大状态)的话就不对了,开始一直没想明白,仔细想想也是,如果按以前的 就会改变dp里面的值,实际上对每一种状态的值是一定的,还有就是为什么要跑结果的对立面,看看测试数据   ,两个要求之间是有重复的,比如1,1和2,2    这样跑起来就不方便. 跑的时候三重for   外

hdu 1074 状态压缩

http://acm.hdu.edu.cn/showproblem.php?pid=1074 我们可以断定状态的终止态一定是n个数全部选完的情况,那么它的前一个状态是什么呢,一定是剔除任一门课程后的n种状态. 例如 dp[全选了]=min{(dp[除了math都做了]+math的超时天数),(dp[除了computer都做了]+computer的超时天数),(dp[除了english都做了]+english的超时天数)}那么接下来的dp状态依然如此. 好了,接下来,我们该如何去思考了,这个题目共

HDU 4856 (状态压缩DP+TSP)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的任务是访问完所有隧道且仅一次,求最短耗时. 解题思路: 暑假练习的时候.把英文读了N遍也没理解题意. 其实就是个最后不回到开头的TSP. 首先求BFS求两两隧道之间的最短路,注意BFS的起点是隧道i的终点,BFS的终点是隧道j的起点. 一定要特判一下两个隧道终点和起点是否一样,如果一样话dis=0,

HDU 5067 (状态压缩DP+TSP)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出来. 最少耗时肯定是从起点出发,把所有石子点走一遍且只走一遍,把石子装在车上,然后最后回到起点. 由于石子堆最多也就10个.不难看出这就是个裸的TSP. 首先BFS计算出每个石子间的最短路. 然后进行TSP就行了. 起点的石子无所谓.所以TSP的起点就是(1,1). #include "cstdio