hacker's Crackdown UVA 11825

题目大意;
有n台计算机(从0开始编号至n-1的网络.一共运行着n中服务,对于每一台计算机,你可以选择终止一项服务,这样就会终止与这台计算机所有相邻的计算机的这项服务,对于一项服务来说,如果没有一台计算机运行,就判定提供这项服务瘫痪, 试着求出瘫痪的最大服务的数量

分析
本题的数学模型是:把n个集合分成尽量多的组,使得每组中的所有集合的并集等于全集,这里的计算机p就是计算机i 与相邻计算机的一个集合,每组对应与题目中一项服务,注意n的值很小,可以使用状压dp输入代码是

		for (int i = 0; i < n; i++)
		{
			p[i]= (1 << i);
			cin >> m;
			while (m--) {
				cin >> posi, p[i] |= (1 << posi);
			}
		}

为了方便我们用cover(S)表示若干个p的集合S中的所有并集,只需要进行按位与就行

		for (int s = 0; s < (1 << n); s++)
		{
			cover[s] = 0;
			for (int j = 0; j < n; j++)
				if (s&(1 << j))	cover[s] |= p[j];
		}

因此不难想到这样的动态规划用发f(s)表示s集合中所可以取得的最大并集等于全集的数量 转移方程为:
d(s)=max(d(s0)|s0为s的子集合并且满足cover(s0))是全集}+1

核心代码

		all=(1<<n)-1;
		for (int s = 1; s < (1 << n); s++) {
			d[s] = 0;
			for (int s0 = s; s0; s0 = (s0 - 1)&s) {
				if (cover[s0] == all) {
					d[s] = max(d[s], d[s^s0] + 1);
				}
			}
		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值