(二进制枚举子集)买玩具
问题描述
蒜厂幼儿园有 n 个小朋友,每个小朋友都有自己想玩的玩具。身为幼儿园园长的你决定给幼儿园买一批玩具,由于经费有限,你只能买 m 个玩具。已知玩具商店一共卖 k 种玩具,编号为 1,2,3,…k,你让每个小朋友把想玩的玩具编号都写在了纸上。你希望满足尽可能多的小朋友的需求,请计算出最多同时能满足多少个小朋友的玩具需求。
输入格式
第一行,输入三个整数 n,m,k(1≤n≤100,1≤m≤k≤15),中间用空格分开。
接下来 n 行,第 i+1(0≤i< n) 行的第一个数字 ai代表第 i 个小朋友想玩的玩具数量,接下来有 ai个数字,代表这 ai 个玩具的编号。
输出格式
输出一个整数,表示最多能满足多少小朋友的玩具需求。
样例输入
5 3 5
2 1 4
0
2 3 1
3 2 3 4
2 4 5
样例输出
3
思路:
用二进制num[j]表示每个小朋友的需求,然后用二进制遍历i从0到(1<<k),i可以满足小朋友方案,结果加1,寻找最大可以满足的小朋友的个数
num[0]= 1001 ,1、4号玩具
num[1]= 0 ,不需要玩具
num[2]= 101 ,1、3号玩具
num[3]= 1110 ,2、3、4号玩具
num[4]=11000 ,4、5号玩具
位运算规矩:
![](https://img2018.cnblogs.com/i-beta/1623081/202002/1623081-20200229171331085-627292918.png)
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int kMax = 100 + 10; int num[kMax]; int main() { int mx=0; int n,m,k; //n个小朋友 买m个玩具 共用k个玩具 int a,t; cin>>n>>m>>k; for(int i=0;i<n;i++){ int cou=0; cin>>a; //每个小朋友想要的玩具个数 while(a){ cin>>t; cou+=(1<<(t-1)); //用二进制表示改小朋友想要的玩具方案 (1001表示想要4号和1号玩具) a--; } num[i]=cou; //用数组保存每个小朋友想要的玩具方案 } for(int i=0;i<(1<<k);i++){ //二进制枚举 int count=0; for(int j=0;j<k;j++){ if(i&(1<<j)) count++; //表示求i中的1的个数 即求i方案需要玩具个数 } if(count==m){ //满足购买的玩具等于m才符合要求 int peo=0; //每种方案满足小朋友个数 for(int j=0;j<n;j++){ //遍历每个小朋友的方案 是否和枚举的i方案相同 if((i|num[j])==i){ // |运算表示两个位有一个1,结果位就是1 (i|num[j])==i表示i方案大于等于num[j]的方案数 peo++; } } mx=max(mx,peo); //结果取满足最多人数的方案 } } cout<<mx; return 0; }