UVA - 11825 Hackers' Crackdown

题意: 假设你是一个黑客,入侵了一个有着n台计算机的网络(0,1,...n-1),一共有n种服务

每台计算机都运行着所有的业务,对于每台计算机,你都可以选择一项服务,终止这台计算机和所有与它相连的计算机的该业务,你的目标是让尽量多的服务完全瘫痪(没有计算机运行该业务),输出完全瘫痪的服务的最大数量

思路:本题的数学模型是:将n个集合P1,P2,...Pn分成尽量多组,使的每组中所有集合的并集等于全集,这里的集合Pi是计算机i及其相邻的计算机的集合,每组对应于题目中的一项服务,分的组越多那么就代表能破坏的服务越多

用cover(S)表示若干Pi的集合S中所有Pi的并集,状态转移方程是:

f(s) = max(f(S-S0)|S0是S的子集,cover[S0] = 全集) + 1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1<<17+10;

int p[MAXN],cover[MAXN],dp[MAXN];
int n;

int main(){
    int cas = 1;
    while (scanf("%d",&n) != EOF && n){
        for (int i = 0; i < n; i++){
            p[i] = 1<<i;
            int m;
            scanf("%d",&m);
            while (m--){
                int x;
                scanf("%d",&x);
                p[i] |= (1<<x);
            }
        }
        for (int i = 0; i < (1<<n); i++){
            cover[i] = 0;
            for (int j = 0; j < n; j++)
                if (i & (1<<j))
                    cover[i] |= p[j];
        }
        dp[0] = 0;
        int full = (1<<n) - 1;
        for (int i = 1; i <= full; i++){
            dp[i] = 0;
            for (int j = i; j; j = (j-1)&i)
                if (cover[j] == full)
                    dp[i] = max(dp[i],dp[i^j]+1);
        }
        printf("Case %d: %d\n",cas++,dp[full]);
    }
    return 0;
}


你可能感兴趣的:(UVA - 11825 Hackers' Crackdown)