状态压缩dp--UVa11825

刚开始刷dp,看了好久才看明白是怎么回事。

首先是题意:有N台电脑,每台电脑有N(N<=16)个服务,一个黑客可以在每台电脑上跑一个(只能跑一个)让一种服务崩溃的病毒,并且这个病毒可以传播到跟他邻接的顶点,问最多这个黑客可以让多少个服务崩溃?(每台电脑上都是N个不同服务,每台电脑上跑的都是一样的服务,让一个服务崩溃是让所有的电脑上的这个服务崩溃)

思路:看书上的,把n个集合p1,p2...分成尽量多组,是得每组中所有集合的并集等于全集。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=1<<16;
//p[i]表示计算机i相连的机器的集合,cover[s]表示汝干p[i]的集合s中所有p[i]的并集
//其中s的二进制数表示中的1表示p[i]是否存在这个集合中
int p[20],cover[maxn],f[maxn];
int main()
{//freopen("in.txt","r",stdin);
    int n,m;
    int x;
    int loop=1;
    while(cin>>n,n)
    {
        memset(p,0,sizeof(p));
        for(int i=0;i<n;i++)
        {
            cin>>m;
            p[i]=1<<i;
            for(int j=0;j<m;j++)
            {
                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];
        }
        f[0]=0;
        int all=(1<<n)-1;
        for(int s=1;s<(1<<n);s++)
        {
            f[s]=0;
            //s中可能存在重复的,所以枚举子集
            for(int s0=s;s0;s0=(s0-1)&s)
                if(cover[s0]==all)
                f[s]=max(f[s],f[s^s0]+1);
        }
        cout<<"Case "<<loop++<<": "<<f[all]<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值