問題描述
蒜廠幼兒園有n 個小朋友,每個小朋友都有自己想玩的玩具。身爲幼兒園園長的你決定給幼兒園買一批玩具,由於經費有限,你只能買m 個玩具。已知玩具商店一共賣k種玩具,編號爲1,2,3,…k,你讓每個小朋友把想玩的玩具編號都寫在了紙上。你希望滿足儘可能多的小朋友的需求,請計算出最多能滿足多少個小朋友的玩具需求。
輸入格式
第一行,輸入三個整數n,m,k(1≤n≤100,1≤m≤k≤15),中間用空格分開。
接下來n 行,第i+1行的第一個數字ai代表第i 個小朋友想玩的玩具數量,接下來有ai個數字,代表這 ai個玩具的編號。
輸出格式
輸出一個整數,表示最多能滿足多少小朋友的玩具需求。
樣例輸入
5 3 5
2 1 4
0
2 3 1
3 2 3 4
2 4 5
樣例輸出
3
思路:用二進制枚舉的方式枚舉不同的情況(也即遍歷玩具的子集),然後判斷是否合法,然後取最大的滿足人數。
ps:枚舉時應考慮超時問題,枚舉變量應儘可能小,此題n較大,則應考慮枚舉k而不是n。
代碼如下:
#include<iostream>
#include<cstring>
using namespace std;
struct a
{
int num;
int w[15];
}aa[100];
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<n;i++)
{
cin>>aa[i].num;
for(int j=0;j<aa[i].num;j++)
cin>>aa[i].w[j];
}
int max=0;//記錄能夠滿足的小朋友數目的最大值
for(int i=0;i<(1<<k);i++)
{
int bsum=0;//當前子集中包含的玩具個數
int b[15];//用於標記在當前子集中的玩具
memset(b,0,sizeof(b));
for(int j=0;j<k;j++)
{
if(i&(1<<j))//判斷該玩具是否是當前子集中的玩具
{
bsum++;//玩具個數+1
b[j]=1;//打上標記
}
int sum=0;//記錄能夠滿足的小朋友的數目
for(int x=0;x<n;x++)
{
int flag=1;//判斷當前小朋友的要求是否被滿足
for(int y=0;y<aa[x].num;y++)//遍歷小朋友要求的玩具
if(b[aa[x].w[y]-1]==0)
flag=0;
if(flag==1)
sum++;
}
if(sum>max&&bsum<=m)
max=sum;
}
}
cout<<max<<endl;
return 0;
}