UVA - 11825 Hackers' Crackdown

来源:互联网 发布:unity3d自动寻路插件 编辑:程序博客网 时间:2024/06/06 01:55

题意: 假设你是一个黑客,入侵了一个有着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;}


原创粉丝点击