UVA 11825 Hackers' Crackdown - 状压dp
题目大意:
N台计算机连成网络,每台计算机上都同时运行着N种服务。对于每台计算机,可以选择仅一项服务,终止这台计算机和所有与它相邻计算机的该项服务。
求:最多可以让多少种服务完全终止运行。
分析:
每台电脑能影响的范围都是一定的,跟它是什么服务没关系。
原问题<=> 将N台电脑分为一些组,满足每个组的电脑能影响的并集等于全集。求最大的组数。
dp[S]=max{dp[S],dp[s^s0]+1} (s0满足其包含的电脑能影响的并集等于全集)
(参考了网上代码)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 16
#define MAXST 65536
int n,p[MAXN+10],c[MAXST+10],dp[MAXST+10],S;
void read()
{
int x,m;
memset(p,0,sizeof p);
for(int i=0;i<n;i++){
scanf("%d",&m);
p[i]=(1<<i);
for(int j=1;j<=m;j++){
scanf("%d",&x);
p[i]|=(1<<x);
}
}
memset(c,0,sizeof c);
S=(1<<n)-1;
for(int s=0;s<=S;s++){
for(int i=0;i<n;i++)
if(s&(1<<i))
c[s]|=p[i];
}
}
void DP()
{
memset(dp,0,sizeof dp);
for(int s=0;s<=S;s++){
for(int s0=s;s0;s0=(s0-1)&s){
if(c[s0]==S)
dp[s]=max(dp[s],dp[s^s0]+1);
}
}
}
int main()
{
int cas=0;
while(scanf("%d",&n)&&n){
read();
DP();
printf("Case %d: %d\n",++cas,dp[S]);
}
return 0;
}