UVa 11825 Hackers’ Crackdown

参照大白书上面的解法,总共三个步骤,前两个步骤都较好理解。P[i]是用位表示的当选中i时,总共有0~n-1总共有多少个数字被覆盖。cover[S]则表示,当子集为S时,0~n-1中能够被覆盖的位数。若cover[S]的每位都为1,则说明子集S能对全集进行覆盖,当然可能子集S的子集就能做到这一点了。

关键的步骤是对状态转移方程的理解。书中的状态转移方程是f(S)=max{f(S0)|S0是S的子集,cover[S0]等于全集}+1,其实对于这个方程我一直感觉怪怪的,并不十分理解它的意思,虽然它最后也能AC。根据我自己的理解的转移方程应当是这样的,f(S)=max{f(S0)+f(S^S0)|S0是S的子集,cover[S0]等于全集}且必须保证cover[S]为全集时,f(S)至少为1,这样做是为了保证S为最小覆盖集时,f(S)的值为1。这样的解法,最后也是能AC的,而且我个人认为思路比书上的更清晰一些。

至于为啥for(int S0=S;S0;S0=(S0-1)&S)能遍历S的所有子集,严密的证明方法还没想到。但直观上来看,可以发现。例如S为10101,则S0依次为10101,10100,10001....我们完全可以将10101中间的0忽略,因此整个for循环就变为了111,110,101,100..这样逐个减一的过程。其实仔细想来也是,S0减一的过程,就是将最低的非0位置0,然后将比该位低的所有位都置1,经过与S相与之后,则之前的低位又变为了开始时候的样子,因此整个过程可以看做是一个递归循环的过程。(说得一点都不清楚....自己模拟一下应该就能理解)

#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAX     16+5
#define MAXN    (1<<16)+5
using namespace std;

int N,Case=1;
int cover[MAXN],P[MAX],f[MAXN];

int main()
{
    //freopen("data.txt","r",stdin);
    while(cin>>N){
        if(!N) break;

        for(int i=0;i<N;++i){
            int m,x;
            cin>>m;
            P[i]=1<<i;
            while(m--){cin>>x;P[i]|=(1<<x);}
        }

        for(int S=0;S<(1<<N);++S){
            cover[S]=0;
            for(int i=0;i<N;++i){
                if(S&(1<<i)) cover[S]|=P[i];//获得子集S的覆盖
            }
        }

        f[0]=0;
        int ALL=(1<<N)-1;//ALL表示全集
        for(int S=1;S<(1<<N);++S){
            if(cover[S]==ALL){
                f[S]=1;
            }
            else{
                f[S]=0;
                continue;
            }
            for(int S0=S;S0;S0=(S0-1)&S)//枚举S的子集
                if(cover[S0]==ALL) f[S]=max(f[S],f[S0^S]+f[S0]);

        }
        cout<<"Case "<<Case++<<": "<<f[ALL]<<endl;
    }

    return 0;
}
时间: 2024-09-29 05:01:54

UVa 11825 Hackers’ Crackdown的相关文章

UVA - 11825 —— Hackers&#39; Crackdown

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18913 这道题是一道状态压缩DP的好题,有几点要注意的: 1.uva给出的题目不知道为何,题意是有些描述不清的,详见<训练指南> 2.这道题可以有很多写法,整个的dp求解和cover那个部分既可以写成记忆化搜索自顶向下,也可以自底向上来实现. #include <cstdio> #include <iostream> #include <

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,子集枚举)

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

UVA 11825 Hackers&#39; Crackdown

题解: 首先将相邻点进行二进制,保存在p[i]中 然后将不同组合的p[i]组合的值记录下来,保存在cover[i]中 然后从小到大进行dp s0为集合s的子集 if(cover[ s0 ] == all - 1) f[s] = max( f[s], f[s ^ s0] + 1); 代码: #include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define se second

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, 枚举子集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

状压DP [Uva 11825] Hackers’ Crackdown

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 w

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 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

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