• uva11825


    题意是将n个集合P1,P2,P3,……,Pn分成尽量多组,使得每组中所有集合的并集等于全集。

    Pi是对于计算机i及其相邻计算机的集合。

    每个组就相当于一项服务。

    整个动规相当于对一个集合进行划分。

    对于一个集合S,我们枚举它的子集S0,如果S0已经满足了要求,我们就可以把S0从S中划去,再去研究剩下的部分。

    划去的操作是S^S0

    这里注意一下枚举一个集合的子集的操作,非常巧妙:

    S0 = (S0 - 1)& S

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 16;
    
    int n;
    
    int p[maxn], cover[1 << maxn], f[1 << maxn];
    
    int main()
    {
        int kase = 0;
        while (scanf("%d", &n) && n)
        {
            kase++;
            memset(p, 0, sizeof p);
            for (int i = 0; i < n; i++)
            {
                p[i] = 1 << i;
                int num;
                scanf("%d", &num);
                for (int j = 1; j <= num; j++)
                {
                    int x;
                    scanf("%d", &x);
                    p[i] |= (1 << x);
                }
            }
            for (int S = 0; S < (1 << n); S++)
            {
                cover[S] = 0;
                for (int i = 0; i < n; i++)
                    if (S & (1 << i)) 
                        cover[S] |= p[i];
            }
            f[0] = 0;
            int ALL = (1 << n) - 1;
            for (int S = 1; S < (1 << n); S++)
            {
                f[S] = 0;
                for (int S0 = S; S0; S0 = (S0 - 1) & S)//枚举子集
                    if (cover[S0] == ALL) f[S] = max(f[S], f[S ^ S0] + 1);
            }
            printf("Case %d: %d
    ", kase, f[ALL]);
        }
        return 0;
    }
  • 相关阅读:
    day08
    day07
    day06
    day06
    day05
    第三次作业
    第三次作业
    第二次作业
    java 数字和日期处理
    jsp文件导包
  • 原文地址:https://www.cnblogs.com/yohanlong/p/7762506.html
Copyright © 2020-2023  润新知