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

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 65536 + 100;
int a[N];
int main()
{
	int n,m,k,q,i,j,num;
	int temp,t1,t2,t3,ans;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
		memset(a,0,sizeof(a));
		for(i=1;i<=k;i++) {
			scanf("%d",&q);
			temp=0;
			while(q--) {
				scanf("%d",&num);
				num--;
				temp=temp+(1<<num);
			}
			a[temp]++;
		}
		ans=0;
		for(i=0;i<(1<<n);i++) {
			t1=i;
			temp=0;
			while(t1) {
				if(t1&1) temp++;
				t1=t1>>1;
			}
			if(temp!=m) continue;
			temp=0;
			for(j=0;j<=i;j++) {
				if((j|i)==i) temp+=a[j];
			}
			ans=max(ans,temp);
		}
		printf("%d\n",ans);
	}
	return 0;
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值