ProblemH Hackers’Crackdown
Miracle Corporations has a number of system services running in adistributed computer system which is a prime target for hackers.The system is basically a set of N computernodes with each of them running a set of N services.Note that, the set of services running on every node is sameeverywhere in the network. A hacker can destroy a service byrunning a specialized exploit for that service in all thenodes.
One day, a smart hacker collects necessary exploits for allthese N services andlaunches an attack on the system. He finds a security hole thatgives him just enough time to run a single exploit in eachcomputer. These exploits have the characteristic that, itssuccessfully infects the computer where it was originally run andall the neighbor computers of that node.
Given a network description, find the maximum number of servicesthat the hacker can damage.
Input
There will be multiple test cases in the input file. A test casebegins with an integer N(1<=N<=16),the number of nodes in the network. The nodes are denoted by 0to N- 1. Eachof the following N linesdescribes the neighbors of a node. Line i(0<=irepresentsthe description of node i.The description for node i startswith an integer m (Numberof neighbors for node i),followed by mintegersin the range of 0 to N- 1,each denoting a neighboring node of node i.
The end of input will be denoted by a casewith N = 0. This case should not beprocessed.
Output
For each test case, print a line in the format, “Case X: Y”,where X isthe case number & Y isthe maximum possible number of services that can bedamaged.
SampleInput
3
2 12
2 02
2 01
4
11
10
13
12
0
Output forSample Input
Case 1:3
Case 2:2
题意: 现在有n个服务,都运行在n台计算机上, 选择某台计算机上的一项服务停止, 与它相邻的计算机
上, 该服务也会停止的, 现在要你让尽量多的服务完全停止.(n台计算机上都不运行该服务).
解题思路:
1. 这题思路, 因为n<=16,可以采用枚举组合的情况.
设状态dp[S]表示当选择部分计算机的集合S, 最多可以停止的服务个数.
状态方程:dp[S] = max(dp[S], dp[S0]+1)
其中S0是S的子集,并且满足S0集合可以覆盖全部的计算机.
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 20
int n;
int p[MAX], cover[1<<MAX];
int dp[1<<MAX];
inline int max(int a, int b)
{
return a> b ? a : b;
}
int main()
{
// freopen("input.txt", "r", stdin);
int caseNum= 1;
while(scanf("%d", &n) !=EOF)
{
if(n == 0) break;
int num, v;
for(int i = 0; i < n; ++i)
{
scanf("%d",&num);
p[i] =(1<<i);
for(int j =0; j < num; ++j)
{
scanf("%d",&v);
p[i] |=(1<<v);
}
}
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 all = (1<<n)-1;
for(int s = 1; s <(1<<n); ++s)
{
dp[s] =0;