uva 11825 黑客的攻击 状态dp 典型

第一想法是搜索,但有n^n种状态。

本题的数学模型可以是每台电脑和相连的电脑看作一个集合。p1,p2.....pn。要使停止的服务越多。要求从p中选出最多的字集,是每个子集的并集

为n台电脑都有。每个pi可以用整数的二进制位的状态表示。用dp,dp(i)=max{dp(i-j)}+1,i为是否选p1,p2....pn的状态表示,j是i的子集。

实现需要枚举i的子集。

/*
uva 11825
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
int main(int argc, char const *argv[])
{
	// freopen("input","r",stdin);
	int n;
	int q=0;
	while(scanf("%d",&n),q++,n)
	{
		int dp[1<<n];
		int A[1<<n];
		memset(A,false,sizeof(A));
		memset(dp,false,sizeof(dp));
		int p[20];
		int v=n;
		for(int i=0;i<n;i++)
		{
			int m;
			scanf("%d",&m);
			p[i]=1<<i;
			for(int j=0;j<m;j++)
			{
				int t;
				scanf("%d",&t);
				p[i]|=1<<t;
			}

		}

		
		for(int i=0;i<1<<n;i++)
		{
			int t=i;
			for(int j=0;j<n;j++,t=t>>1)//不要写成t>>1
				if(t & 1)	A[i]|=p[j];
			// printf("%da\n",A[i] );
		}


		int s=(1<<n)-1;//一定要加()
		for(int i=0;i<=s;i++)
		{
			if(i==0)
			{
				dp[i]=0;
				continue;
			}
			int j=i;
			do//枚举子集
			{
				if(A[j]==s)
				{
					// printf("%d\n",j );
					dp[i]=dp[i]>dp[i & ~j]+1 ? dp[i]:dp[i & ~j]+1;
				}
				
				j=(j-1) & i;
			}while(j!=i);

		}
		printf("Case %d: %d\n",q,dp[s] );

	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值