题目大意;
有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);
}
}
}