UVA 11825 Hackers' Crackdown DP+状态压缩 -

题目地址:http://vjudge.net/problem/UVA-11825

题目难在怎么转化

因为题目求的是完全瘫痪,也就是所有的计算机都没有运行

将一个计算机及其相邻的计算机表示成集合A,如第一行的 2 1 2,表示为111

为了使所有的计算机都没有运行,就是求A这种集合任意组合能使 他们交集全为1,如A1=000111,A2=111000,A3=001100,那么000~111总的子集A1|A2=111111全为一,用S= 011表示这种排列,其满足题意的

便是求0~n-1的子集中满足题意的S有几个


直接枚举0~n-1的子集 找出这样的S,再进行DP,f[i] 表示i集合的子集中满足S要求的组合数 f[i]=max{f[i0]+1|i0为i的子集且集合满足S的要求}


还有因为为无向图,所以每组S只看成一个服务的暂停,虽然里面有多个计算机,可以暂停多个服务,但为了不混淆,只看成每组只暂停一个服务,其他的计算机可以看成是别的S组别

#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=a;i<=(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(b);--i)
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int A[16],cover[(1<<16)+5],f[(1<<16)+5];
int main(int argc, char const *argv[])
{
	int n,kase=0; 
	while(scanf("%d",&n)==1&&n){
		REP(i,0,n-1){      //读入,转化为集合
			int m,k;
			scanf("%d",&m);
			A[i]=1<<i;
			while(m--) {scanf("%d",&k); A[i]|=1<<k;}
		}
		REP(i,1,(1<<n)-1){  //1~n 的任意子集算出 A[]的交集
			cover[i]=0;
			REP(j,0,n-1) if((1<<j)&i) cover[i]|=A[j];
		}
		int ALL=(1<<n)-1;
		REP(S,1,ALL){
			f[S]=0;
			for(int S0=S;S0;S0=(S0-1)&S) if(cover[S0]==ALL) f[S]=max(f[S],f[S-S0]+1);
		}
		printf("Case %d: %d\n", ++kase,f[ALL]);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值