UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers‘ Crackdown 状态压缩 dp 枚举子集

ACM

题目地址:11825 - Hackers‘ Crackdown

题意:

有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态)。

求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务)。

分析:

题目说白了。就是:

把n个集合p[i],0<=i<n分成尽量多组,使得每组中各个集合的并集为全集。

利用状态压缩。记录每一个节点执行的服务。因为数据大小就16所以直接能够用int范围数字表示一个集合。

然后预处理下cover,处理16个节点组成的各个集合会带来的挺服务效果。

然后dp,假设cover[S0] == all (all全为1) 那么是S^S0 的部分也有可能终止服务 。dp[S] = max(dp[S], dp[S^S0]+1)

參考了凌乱的心巨巨的题解,嘛。是为了了解枚举子集做的题目。

枚举子集的模板:

  1. // 对于集合S
  2. for (int S0 = S; S0; S0 = S&(S0 - 1)) // 枚举S0为子集
  3. ...

原理:S&(S0 - 1) 实际上是把S中的0所有忽略。并不断减1的结果。

代码:

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        11825.cpp
*  Create Date: 2014-06-27 20:43:48
*  Descripton:  sub set/ dp/ numeric
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 16;

int n, m, t, mask[N], cover[1<<N], dp[1<<N], tot;

int main() {
	int cas = 0;
	while (~scanf("%d", &n) && n) {
		// input
		for (int i = 0; i < n; i++) {
			scanf("%d", &m);
			mask[i] = (1 << i);
			while (m--) {
				scanf("%d", &t);
				mask[i] |= (1 << t);
			}
		}

		// get the union set of cover
		for (int S = 0; S < (1 << n); S++) {
			cover[S] = 0;
			for (int i = 0; i < n; i++) {
				if (S & (1 << i)) {
					cover[S] |= mask[i];
				}
			}
		}

		// dp
		dp[0] = 0;
		tot = (1 << n) - 1;
		for (int S = 1; S < (1 << n); S++) {
			dp[S] = 0;
			for (int S0 = S; S0; S0 = (S0 - 1)&S) {
				if (cover[S0] == tot) {
					dp[S] = max(dp[S], dp[S^S0] + 1);
				}
			}
		}

		printf("Case %d: %d\n", ++cas, dp[tot]);
	}
	return 0;
}

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集

时间: 2024-10-26 14:10:32

UVA 11825 - Hackers&#39; Crackdown 状态压缩 dp 枚举子集的相关文章

11825 - Hackers&#39; Crackdown 状态压缩 dp 枚举子集

11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共有n种服务,每台计算机上都运行着全部服务,对于每台计算机,你可以选择停止一项服务,这个行为会导致与这台计算机和与他相连的其他计算机上的这项服务都停止(原来已经停止的继续保持停止状态).求最多能使多少个服务瘫痪(即没有任何一台计算机在运行这项服务). 分析: 题目说白了,就是: 把n个集合p

uva 11825 Hackers&amp;#39; Crackdown (状压dp,子集枚举)

题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪(没有计算机有该项服务). 思路:(见大白70页,我的方程与大白不同) 把n个集合P1.P2.Pn分成尽量多的组,使得每组中全部集合的并集等于全集,这里的集合Pi是计算机i及其相邻计算机的集合,用cover[i]表示若干Pi的集合S中全部集合的并集,dp[s]表示子集s最多能够分成多少组,则 假设co

uva 11825 ,Hacker&#39;s Crackdown 状态压缩 dp

// uva 11825 Hacker's Crackdown // // 题目意思看了很久才看懂,有n台计算机,有n种服务,每台计算机上运行所有 // 的服务,并且其中有的计算机与某些计算机相互邻接,对于每台计算机, // 你可以选择一项服务,停止这项服务,则与它邻接的计算机的该服务也停止了 // 你的目的是让经量多的服务完全瘫痪 // // 换而言之,这个问题就是在n个集合中(p[1]....p[n])分成尽量多的组数,使得每组 // 的并集等于全集(即所有的n台电脑都停止)... // /

UVA 11825 Hackers’ Crackdown 状压DP枚举子集势

Hackers’ Crackdown Miracle Corporations has a number of system services running in a distributed computer system which is a prime target for hackers. The system is basically a set of N computer nodes with each of them running a set of Nservices. Note

UVA 10817-Headmaster’s Headache(状态压缩DP)

题目大意:有S(S<=8)门课程,每门课程要求至少有2名老师教,雇佣每个老师需要一定的花费,每个老师可以教一门或多门课程.现有M(M<=20)名在职老师,N(N<=100)名应聘者,对于在职老师,必须每个都雇佣,求在满足每门课程至少2个老师教的情况下最少的花费是多少. 用d[i][j]表示前i名老师状态为j的情况下最少的花费,j是S位三进制数,对于每一位三进制位u,为0时表示课程u当前没有老师教,为1表示课程u当前有一名老师教,为2表示课程u当前有两名老师教.最终答案为d[N][3^S-

UVa 10651 Pebble Solitaire(状态压缩DP)

题意:转化为01序列,可以做如下转换011–>100, 110–>001 使得序列的1最少 二进制的集合表示: 空集:0 全集:( 1< #include<iostream> #include<algorithm> #include<map> #include<cstdio> #include<cstdlib> #include<vector> #include<cmath> #include<cs

uva 11825 Hackers&#39; Crackdown(状态压缩DP)

Hackers' Crackdown Input: Standard Input Output: Standard Output   Miracle Corporations has a number of system services running in a distributed computer system which is a prime target for hackers. The system is basically a set of N computer nodes wi

UVA 11825 Hackers&#39; Crackdown 状压DP

感觉白书上的做法很神! 首先状压表示电脑之间的联通关系,然后预处理出所有关闭电脑的组合达到的状态,然后枚举每个状态并且枚举每个状态的所有子集,之后无脑递推就木有了. 关于枚举一个状态所有子集的小技巧:假设当前状态是S0 有 for s = s0; s != 0; s =  (s - 1) & s0 #include <cstdio> #include <cstring> #include <iostream> #include <map> #incl

UVa 11825 - Hackers&#39; Crackdown DP, 枚举子集substa = (substa - 1)&amp;sta 难度: 2

题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2925 题意 n个节点,每个节点都有完全相同的n项服务. 每次可以选择一个节点,破坏该节点和相邻节点的某项服务. 问最多能完全破坏多少服务? 思路 如刘书, 直接枚举状态的子集 注意元素个数为k的集合有C^k_n个子集,那么枚举的时间复杂度为sum{c^k_n * 2^k} = 3^n