• uva 11825 巧妙地子集枚举方法


    https://vjudge.net/problem/UVA-11825

    题目大意,有n台服务器,有n种服务,每台服务器都运行着所有的服务,一台服务器可以被攻击一次其中的一种服务,当你选择攻击某台服务器的某个服务时,与他相邻的服务器上的同种的服务也会被攻击,当某种服务在所有的服务器上都不再运行时,我们称消灭了一种服务,求黑客最多消灭几种服务。

    n最大16,我们容易想到利用二进制表示已经攻击过的电脑,f(S)=MAX{f(S),f(S0^S)+1 | if(S0是S的子集&&S0攻击后可以覆盖全部的电脑)}

    接下来的问题是如何判断某个电脑集合可以攻击到的范围,我们不妨用P[i]表示攻击第i个电脑后受到影响的所有电脑的集合,cover[i]表示攻击i集合里的全部电脑后受到影响的所有电脑的集合。对于子集的枚举有一种巧妙地方法:

                                        for(int S0=S;S0;S0=(S0-1)&S);   //其中,S表示原集合,S0为他的子集

                                  

    当上面的问题都解决之后就好办了,

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int P[25],cover[1<<16],f[1<<16];
     4 int main()
     5 {
     6     int N,m,i,j,k=0,x;
     7     while(cin>>N&&N){
     8         memset(P,0,sizeof(P));
     9         memset(cover,0,sizeof(cover));
    10         memset(f,0,sizeof(f));
    11         for(i=0;i<N;++i)
    12         {
    13             P[i]|=(1<<i);
    14             scanf("%d",&m);
    15             while(m--){
    16                 scanf("%d",&x);
    17                 P[i]|=(1<<x);
    18             }
    19         }
    20        for(i=1;i<(1<<N);++i)
    21        {
    22            for(j=0;j<N;++j)
    23             if(i&(1<<j)) cover[i]|=P[j];
    24        }
    25        for(i=1;i<(1<<N);++i)
    26        {
    27            for(int S=i;S;S=(S-1)&i)
    28             if(cover[S]==(1<<N)-1&&f[i]<f[i^S]+1)
    29             f[i]=f[i^S]+1;
    30        }
    31        printf("Case %d: %d
    ",++k,f[(1<<N)-1]);
    32     }
    33     return 0;
    34 }
  • 相关阅读:
    ElasticSearch记录(1)底层原理
    hbase学习记录(4)hbase和Hadoop整合(实现wrodcount程序)
    flume记录(2)监控文件和目录,对hdfs操作
    flume记录(1)使用
    hbase学习记录(3)JAVA_API操作hbase
    hbase学习记录(2)shell常用命令
    hbase学习记录(1)简介
    ssh三大框架整合
    spring事务管理
    Ubuntu 18.04版本设置root账户
  • 原文地址:https://www.cnblogs.com/zzqc/p/7339016.html
Copyright © 2020-2023  润新知