Uva - 11825 - Hackers' Crackdown(状态压缩dp)

来源:互联网 发布:2017人工智能大会 编辑:程序博客网 时间:2024/06/01 09:43

题意:全集为0, 1, 2, ..., N-1,输入N个子集,求这N个子集最多能分成多少组,使得每组的并集都是全集。

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=226&page=show_problem&problem=2925

——>>设f[S]为集合S的最大拆分组数。

则对于S的所有子集S0,得状态转移方程:

(若S0的元素并集为全集)

f[S] = max(f[S], f[S^S0]+1);

#include <cstdio>#include <algorithm>using namespace std;const int maxn = 20;int cover[1<<maxn], f[1<<maxn];int main(){    int N, m, i, temp, p[maxn], S, S0, cnt = 1;    while(scanf("%d", &N) == 1 && N)    {        for(i = 0; i < N; i++)      //输入N个集合        {            p[i] = 1<<i;            scanf("%d", &m);            while(m--)            {                scanf("%d", &temp);                p[i] |= (1<<temp);            }        }        for(S = 0; S < (1<<N); S++)     //求子集所包含的域        {            cover[S] = 0;            for(i = 0; i < N; i++)                if(S & (1<<i)) cover[S] |= p[i];        }        f[0] = 0;        int ALL = (1<<N) - 1;        for(S = 1; S < (1<<N); S++)     //dp求解        {            f[S] = 0;            for(S0 = S; S0; S0 = S&(S0-1))                if(cover[S0] == ALL)                    f[S] = max(f[S], f[S^S0]+1);        }        printf("Case %d: %d\n", cnt++, f[ALL]);    }    return 0;}


原创粉丝点击