UVA 11825 Hackers' Crackdown dp+位运算状态压缩(子集枚举)

题意:

      有N台电脑(编号为0,1,2......n-1),每台电脑有N(N<=16)个服务,一个黑客可以在每台电脑上种植让其中一种服务崩溃的病毒,并且这个病毒可以传播到跟他邻接的电脑,问最多这个黑客可以让多少个服务崩溃?(每台电脑上都是N个不同服务,每台电脑上跑的都是一样的服务,让一个服务崩溃是让所有的电脑上的这个服务崩溃)

Input

There will be multiple test cases in the input file. A test case begins with an integer N (1 ≤ N ≤ 16),the number of nodes in the network. The nodes are denoted by 0 to N − 1. Each of the followingN lines describes the neighbors of a node. Line i (0 ≤ i < N) represents the description of node i.The description for node i starts with an integer m (Number of neighbors for node i), followed by mintegers in the range of 0 to N − 1, each denoting a neighboring node of node i.

The end of input will be denoted by a case with N = 0. This case should not be processed.

Output

For each test case, print a line in the format, ‘Case X: Y ’, where X is the case number & Y is themaximum possible number of services that can be damaged.

Sample Input

3

2 1 2

2 0 2

2 0 1

4

1 1

1 0

1 3

1 2

0

Sample Output

Case 1: 3

Case 2: 2

 分析:

本题的数学模型:

把n个集合p1,p2,p3...pn分成尽量多组,并且使得每一组集合的并集等于全集S。

f[s]表示集合至多能分成几组,

注意到n<=16,于是每台电脑与其他电脑的关系,也就是前面说的p1,p2...pn,可以用一个二进制数来表示:

相邻的为1,不相邻的为0,全集全为1;

方程:

f(s)= max{f(s-S0) | S0是s的子集,并且crash[S0]==全集S}+1;

其中,crach[S]表示集合S关系到的所有的p[i]的并集(用位运算的'|‘来表达)

时间的复杂度等于{1,2,3......n}的所有子集的子集的个数。总之用很牛逼的方法可以知道,它是O(3^n)。

代码如下:

#include
#include
#include
using namespace std;
const int maxn=16;
int n,f[(1<


你可能感兴趣的:(动态规划,思维趣题,习题,位运算)