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;
}
posted @ 2016-03-20 11:44  KatarinaYuan  阅读(93)  评论(0编辑  收藏  举报