HUST 1371 Emergency relief

Description

Before referring to this problem, please stand in silent tribute for the victims of Qinghai In April, 14th, 2010, two earthquakes take place in Yusu of Qinghai province in the morning, the highest earthquake e maqnitude reaches 7.1. Till 17:00 in 23th, it has caused 2192 death, 78 missing, 12135 injured. According to reports, the disaster area is now in urgent need of tents, bedclothes, living materials and cold protection materials etc. . HUST urgently calls these relief supplies to convey to the disaster area. Unfortunately, because of the limits of traffic conditions, there is only a part of kinds of relief supplies reached the victims. Considering the matter in any way urgent, HUST needs your help, it’s up to you to decide what kind of relief supplies will be conveyed so that it can help as many as victims. For a victim, he/she can be helped only if all the relief supplies he/she need have been reached. Assuming that every kind of material is abundant.

Input

50 groups of data in total, for every group of data, three integers , n m k, in the first row: n (0 < n <= 16) shows the total kinds of relief supplies, which is marked 1 to n; m (0 < m <= n) indicates the maximum possible kinds of relief supplies that can be conveyed; k (0 < k <= 100000) expresses the number of victims. The followed k lines are every victim’s needed relief supplies, whose form is p a1 a2 … ap, among them, p is the number of kinds of the relief supplies, ai is the id of relief supply, and 1 <= ai <= n, in addition, ai will not be repeated.

Output

For every group of data, please output the maximum number of victims who can be helped

Sample Input

1 1 2
1 1
1 1
3 2 7
2 1 3
1 1
1 2
3 1 2 3
1 2
1 1
2 1 2

Sample Output

2

5

此题要用到状态压缩,简单来说对于每个人,把他需要的东西全部一起压成一个二进制数字

然后统计进答案里,最后对于状态压缩的数组自身进行一次叠加,取1个数不大于m的答案中的最大值即可

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int maxn = 1e5 + 10;
int T, n, m, k, f[maxn], p, x;

void Scan(int &x)
{
	char ch;
	while ((ch = getchar()) > '9' || ch < '0');
	int res = ch - '0';
	while ((ch = getchar()) <= '9'&&ch >= '0') res = res * 10 + ch - '0';
	x = res;
}

void find(int x, int y, int z)
{
	if (y == n) { if (x != z) f[z] += f[x]; return; }
	find(x, y + 1, z);
	if (x&(1 << y)) find(x ^ (1 << y), y + 1, z);

}

int main()
{
	while (scanf("%d%d%d", &n, &m, &k) != EOF)
	{
		for (int i = 0; i < (1 << n); i++) f[i] = 0;
		while (k--)
		{
			scanf("%d", &p);
			int ans = 0;
			while (p--) { scanf("%d", &x); ans |= 1 << (x - 1); }
			f[ans]++;
		}
		int ans = f[0];
		for (int i = (1 << n); i; i--)
		{
			int cnt = 0;
			for (int j = 0; j < n; j++) if (i&(1 << j)) cnt++;
			if (cnt > m) continue;
			find(i, 0, i);
			ans = max(ans, f[i]);
		}
		printf("%d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值