UVA 11825Hackers' Crackdown dp+位运算状态压缩(子集枚举)
来源:互联网 发布:淘宝上的订单险是什么 编辑:程序博客网 时间:2024/06/05 22:35
题意:
有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<cstdio>#include<iostream>#include<cstring>using namespace std;const int maxn=16;int n,f[(1<<maxn)+5],crash[(1<<maxn)+5],p[maxn];void input(){int i,s,m,x;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&m);p[i]= 1<<i; //最初只有自己 while(m--){scanf("%d",&x);p[i]|=(1<<x); }}memset(crash,0,sizeof(crash));for(s=0;s<(1<<n);s++){ //预处理crash[s]; crash[s]=0;for(i=0;i<n;i++)if(s&(1<<i))crash[s]|=p[i]; //并集操作 } }void solve(int kase){int all= (1<<n)-1,s,s0;for(s=1;s<(1<<n);s++){f[s]=0; //多组数据。不要忘了初值 for(s0=s;s0;s0=(s0-1)&s) //枚举s的子集s0; if(crash[s0]==all)f[s]=max(f[s],f[s-s0]+1); //也可写成f[s^s0]+1; }printf("Case %d: %d\n",kase,f[all]);}int main(){for(int i=1;;i++){input();if(n==0)return 0;solve(i);}}/* 枚举子集的模型:对于集合s:for(s0=s;s0;s0=(s0-1)&s)*/
- UVA 11825Hackers' Crackdown dp+位运算状态压缩(子集枚举)
- UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集
- UVA 11825 Hackers' Crackdown(枚举子集+dp)
- uva 11825 - Hackers' Crackdown(dp+子集枚举)
- uva 11825 Hackers' Crackdown (状压dp,子集枚举)
- Uva 11825 - Hackers’ Crackdown 状态压缩DP
- UVA 11825 Hackers' Crackdown 状态压缩dp
- UVa 11825 Hackers’ Crackdown / 状态压缩DP
- UVA 11825 - Hackers' Crackdown(dp+状态压缩)
- UVA 11825 Hackers' Crackdown DP+状态压缩 -
- UVa 11825 Hackers' Crackdown (状态压缩DP)
- Uva - 11825 - Hackers' Crackdown(状态压缩dp)
- UVA 11825 - Hackers' Crackdown(状态压缩DP)
- uva 11825 Hackers' Crackdown(动态规划-状态压缩DP)
- UVA 11825 Hackers' Crackdown(状态压缩DP)
- Uva 11825 - Hackers' Crackdown 状态压缩
- UVA - 11825 Hackers' Crackdown 状态压缩
- UVa 11825 Hackers' Crackdown(二进制压缩+DP)
- 各种Linux下的HugePage 大小
- 递归调用详解
- 概率练习 (16.04.30)
- 单例模式的简单demo
- zookeeper中问题
- UVA 11825Hackers' Crackdown dp+位运算状态压缩(子集枚举)
- operation not allowed after resultset closed错误的解决
- Centos中查看nginx、apache、php、mysql配置文件路径
- LightOJ - 1236 Pairs Forming LCM 合数分解
- HDU - 1548 A strange lift(Dijkstra)
- C++ 左值引用和右值引用(C++11特性)
- 山东省第三届ACM大学生程序设计竞赛-Pixel density(模拟)
- HDU - 3790 最短路径问题(Dijkstra)
- Spring中的AOP(七)(实际上应该是一)——AspectJ的基本使用